compiler: avoid GCC middle-end control warnings
authorIan Lance Taylor <iant@golang.org>
Sat, 2 Dec 2017 00:38:54 +0000 (00:38 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 2 Dec 2017 00:38:54 +0000 (00:38 +0000)
    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

    Reviewed-on: https://go-review.googlesource.com/80416

* go-gcc.cc (Gcc_backend::Gcc_backend): Define
__builtin_unreachable.
(Gcc_backend::function): Add does_not_return parameter.

From-SVN: r255346

gcc/go/ChangeLog
gcc/go/go-gcc.cc
gcc/go/gofrontend/MERGE
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/runtime.def
gcc/go/gofrontend/statements.cc

index 26f823e0442d0522ba800cb6abc4da2dc8d333fb..03100610d71937385570d9463fb5510b94c46e1b 100644 (file)
@@ -1,3 +1,9 @@
+2017-12-01  Ian Lance Taylor  <iant@golang.org>
+
+       * go-gcc.cc (Gcc_backend::Gcc_backend): Define
+       __builtin_unreachable.
+       (Gcc_backend::function): Add does_not_return parameter.
+
 2017-12-01  Than McIntosh  <thanm@google.com>
 
        * go-c.h (go_create_gogo_args): Add nil_check_size_threshold
index 1b0190d954ba136f533ec594781ffa0c14848682..730e2da24edc02501940ed0f8fb39d2f6ef89b1d 100644 (file)
@@ -486,7 +486,8 @@ class Gcc_backend : public Backend
   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);
+           bool disable_split_stack, bool does_not_return,
+          bool in_unique_section, Location);
 
   Bstatement*
   function_defer_statement(Bfunction* function, Bexpression* undefer,
@@ -760,6 +761,12 @@ Gcc_backend::Gcc_backend()
                                                        const_ptr_type_node,
                                                        NULL_TREE),
                       false, false);
+
+  // The compiler uses __builtin_unreachable for cases that can not
+  // occur.
+  this->define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
+                      build_function_type(void_type_node, void_list_node),
+                      true, true);
 }
 
 // Get an unnamed integer type.
@@ -3012,8 +3019,8 @@ Bfunction*
 Gcc_backend::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 location)
+                      bool disable_split_stack, bool does_not_return,
+                     bool in_unique_section, Location location)
 {
   tree functype = fntype->get_tree();
   if (functype != error_mark_node)
@@ -3049,6 +3056,8 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
       tree attr = get_identifier ("no_split_stack");
       DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
     }
+  if (does_not_return)
+    TREE_THIS_VOLATILE(decl) = 1;
   if (in_unique_section)
     resolve_unique_section(decl, 0, 1);
 
index ca329c2de32be8da9bdb6dde81a77e64cb1c5279..61f941599741828a053446913a30781b501212ef 100644 (file)
@@ -1,4 +1,4 @@
-8cd42a3e9e0e618bb09e67be73f7d2f2477a0faa
+1949a203fca0c8bde6f2690ebc36427c5e3953c7
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 48dbe7eb0da6ae8a231f2db6ae13419c8830125c..601e7c95b3ae4588da6ff00eb008ebf28c419cc7 100644 (file)
@@ -711,12 +711,15 @@ class Backend
   // 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++:
index 74b45958f619fe0a42379de7868e045569aaef7f..b1c780794c905162e2badc5e60a8c8e07e8a8125 100644 (file)
@@ -711,7 +711,7 @@ Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction)
 
       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 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
       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 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
 {
   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 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
              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 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
       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_;
index 6df53498d720072507370e2e469fe77c6bf94dd6..ef148eec9b08b90038917f357db715b59728a4c3 100644 (file)
@@ -363,6 +363,9 @@ DEF_GO_RUNTIME(PRINTNL, "runtime.printnl", P0(), R0())
 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
index d3878a6ba0561c4e41ae7bdcb85b5786b5e65d5e..93718ff8c2af8dbeafd48f126197ea3369871053 100644 (file)
@@ -4866,8 +4866,8 @@ Select_clauses::get_backend(Translate_context* context,
                            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 @@ Select_clauses::get_backend(Translate_context* context,
       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,