compiler: avoid GCC middle-end control warnings

GCC has started emitting "control reaches end of non-void function"
warnings. Avoid them for Go by 1) marking the builtin function panic
and the compiler-generated function __go_runtime_error as not
returning and 2) adding a default case to the switch used for select
statements that simply calls __builtin_unreachable.

Fixes golang/go#22767

Change-Id: Ic278dd841369ab922e3d791e340a3831227c2f9d
Reviewed-on: https://go-review.googlesource.com/80416
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/backend.h b/go/backend.h
index 48dbe7e..601e7c9 100644
--- a/go/backend.h
+++ b/go/backend.h
@@ -711,12 +711,15 @@
   // IS_INLINABLE is true if the function can be inlined.
   // DISABLE_SPLIT_STACK is true if this function may not split the stack; this
   // is used for the implementation of recover.
+  // DOES_NOT_RETURN is true for a function that does not return; this is used
+  // for the implementation of panic.
   // IN_UNIQUE_SECTION is true if this function should be put into a unique
   // location if possible; this is used for field tracking.
   virtual Bfunction*
   function(Btype* fntype, const std::string& name, const std::string& asm_name,
            bool is_visible, bool is_declaration, bool is_inlinable,
-           bool disable_split_stack, bool in_unique_section, Location) = 0;
+           bool disable_split_stack, bool does_not_return,
+	   bool in_unique_section, Location) = 0;
 
   // Create a statement that runs all deferred calls for FUNCTION.  This should
   // be a statement that looks like this in C++:
diff --git a/go/gogo.cc b/go/gogo.cc
index 74b4595..b1c7807 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -711,7 +711,7 @@
 
       Bfunction* pfunc = this->backend()->function(fntype, user_name, init_name,
                                                    true, true, true, false,
-                                                   false, unknown_loc);
+                                                   false, false, unknown_loc);
       Bexpression* pfunc_code =
           this->backend()->function_code_expression(pfunc, unknown_loc);
       Bexpression* pfunc_call =
@@ -5435,8 +5435,8 @@
       this->fndecl_ =
           gogo->backend()->function(functype, no->get_id(gogo), asm_name,
                                     is_visible, false, is_inlinable,
-                                    disable_split_stack, in_unique_section,
-				    this->location());
+                                    disable_split_stack, false,
+				    in_unique_section, this->location());
     }
   return this->fndecl_;
 }
@@ -5448,6 +5448,8 @@
 {
   if (this->fndecl_ == NULL)
     {
+      bool does_not_return = false;
+
       // Let Go code use an asm declaration to pick up a builtin
       // function.
       if (!this->asm_name_.empty())
@@ -5459,6 +5461,10 @@
 	      this->fndecl_ = builtin_decl;
 	      return this->fndecl_;
 	    }
+
+	  if (this->asm_name_ == "runtime.gopanic"
+	      || this->asm_name_ == "__go_runtime_error")
+	    does_not_return = true;
 	}
 
       std::string asm_name;
@@ -5475,8 +5481,8 @@
       Btype* functype = this->fntype_->get_backend_fntype(gogo);
       this->fndecl_ =
           gogo->backend()->function(functype, no->get_id(gogo), asm_name,
-                                    true, true, true, false, false,
-                                    this->location());
+                                    true, true, true, false, does_not_return,
+				    false, this->location());
     }
 
   return this->fndecl_;
diff --git a/go/runtime.def b/go/runtime.def
index 6df5349..ef148ee 100644
--- a/go/runtime.def
+++ b/go/runtime.def
@@ -363,6 +363,9 @@
 DEF_GO_RUNTIME(FIELDTRACK, "__go_fieldtrack", P1(POINTER), R0())
 
 
+// Unreachable code.
+DEF_GO_RUNTIME(UNREACHABLE, "__builtin_unreachable", P0(), R0())
+
 // Remove helper macros.
 #undef ABFT6
 #undef ABFT2
diff --git a/go/statements.cc b/go/statements.cc
index d3878a6..93718ff 100644
--- a/go/statements.cc
+++ b/go/statements.cc
@@ -4866,8 +4866,8 @@
 			    Location location)
 {
   size_t count = this->clauses_.size();
-  std::vector<std::vector<Bexpression*> > cases(count);
-  std::vector<Bstatement*> clauses(count);
+  std::vector<std::vector<Bexpression*> > cases(count + 1);
+  std::vector<Bstatement*> clauses(count + 1);
 
   Type* int_type = Type::lookup_integer_type("int");
 
@@ -4905,10 +4905,15 @@
       return context->backend()->expression_statement(bfunction, bcall);
     }
 
+  Bfunction* bfunction = context->function()->func_value()->get_decl();
+
+  Expression* crash = Runtime::make_call(Runtime::UNREACHABLE, location, 0);
+  Bexpression* bcrash = crash->get_backend(context);
+  clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
+
   std::vector<Bstatement*> statements;
   statements.reserve(2);
 
-  Bfunction* bfunction = context->function()->func_value()->get_decl();
   Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
 								 bcall,
 								 cases,