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 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
This commit is contained in:
parent
d7d5f241f0
commit
9638589faf
7 changed files with 45 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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++:
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue