compiler: Don't initialize zero sized variables.
* go-gcc.cc (Gcc_backend::init_statement): Don't initialize a zero-sized variable. (go_non_zero_struct): New global variable. (Gcc_backend::non_zero_size_type): New function. (Gcc_backend::global_variable): Don't build an assignment for a zero-sized value. * go-c.h (go_non_zero_struct): Declare. * config-lang.in (gtfiles): Add go-c.h. From-SVN: r185115
This commit is contained in:
parent
b97190553d
commit
7d6be4c870
@ -1,3 +1,14 @@
|
||||
2012-03-08 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::init_statement): Don't initialize a
|
||||
zero-sized variable.
|
||||
(go_non_zero_struct): New global variable.
|
||||
(Gcc_backend::non_zero_size_type): New function.
|
||||
(Gcc_backend::global_variable): Don't build an assignment for a
|
||||
zero-sized value.
|
||||
* go-c.h (go_non_zero_struct): Declare.
|
||||
* config-lang.in (gtfiles): Add go-c.h.
|
||||
|
||||
2012-02-29 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* go-gcc.cc (class Gcc_tree): Add set_tree method.
|
||||
|
@ -34,7 +34,7 @@ target_libs="target-libgo target-libffi"
|
||||
# compiler during stage 1.
|
||||
lang_requires_boot_languages=c++
|
||||
|
||||
gtfiles="\$(srcdir)/go/go-lang.c"
|
||||
gtfiles="\$(srcdir)/go/go-lang.c \$(srcdir)/go/go-c.h"
|
||||
|
||||
# Do not build by default.
|
||||
build_by_default="no"
|
||||
|
@ -69,6 +69,8 @@ extern void go_write_export_data (const char *, unsigned int);
|
||||
|
||||
extern const char *go_read_export_data (int, off_t, char **, size_t *, int *);
|
||||
|
||||
extern GTY(()) tree go_non_zero_struct;
|
||||
|
||||
#if defined(__cplusplus) && !defined(ENABLE_BUILD_WITH_CXX)
|
||||
} /* End extern "C". */
|
||||
#endif
|
||||
|
@ -338,6 +338,9 @@ class Gcc_backend : public Backend
|
||||
|
||||
Btype*
|
||||
fill_in_array(Btype*, Btype*, Bexpression*);
|
||||
|
||||
tree
|
||||
non_zero_size_type(tree);
|
||||
};
|
||||
|
||||
// A helper function.
|
||||
@ -870,9 +873,27 @@ Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
|
||||
if (var_tree == error_mark_node || init_tree == error_mark_node)
|
||||
return this->error_statement();
|
||||
gcc_assert(TREE_CODE(var_tree) == VAR_DECL);
|
||||
DECL_INITIAL(var_tree) = init_tree;
|
||||
return this->make_statement(build1_loc(DECL_SOURCE_LOCATION(var_tree),
|
||||
DECL_EXPR, void_type_node, var_tree));
|
||||
|
||||
// To avoid problems with GNU ld, we don't make zero-sized
|
||||
// externally visible variables. That might lead us to doing an
|
||||
// initialization of a zero-sized expression to a non-zero sized
|
||||
// variable, or vice-versa. Avoid crashes by omitting the
|
||||
// initializer. Such initializations don't mean anything anyhow.
|
||||
if (int_size_in_bytes(TREE_TYPE(var_tree)) != 0
|
||||
&& init_tree != NULL_TREE
|
||||
&& int_size_in_bytes(TREE_TYPE(init_tree)) != 0)
|
||||
{
|
||||
DECL_INITIAL(var_tree) = init_tree;
|
||||
init_tree = NULL_TREE;
|
||||
}
|
||||
|
||||
tree ret = build1_loc(DECL_SOURCE_LOCATION(var_tree), DECL_EXPR,
|
||||
void_type_node, var_tree);
|
||||
if (init_tree != NULL_TREE)
|
||||
ret = build2_loc(DECL_SOURCE_LOCATION(var_tree), COMPOUND_EXPR,
|
||||
void_type_node, init_tree, ret);
|
||||
|
||||
return this->make_statement(ret);
|
||||
}
|
||||
|
||||
// Assignment.
|
||||
@ -885,6 +906,18 @@ Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
|
||||
tree rhs_tree = rhs->get_tree();
|
||||
if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
|
||||
return this->error_statement();
|
||||
|
||||
// To avoid problems with GNU ld, we don't make zero-sized
|
||||
// externally visible variables. That might lead us to doing an
|
||||
// assignment of a zero-sized expression to a non-zero sized
|
||||
// expression; avoid crashes here by avoiding assignments of
|
||||
// zero-sized expressions. Such assignments don't really mean
|
||||
// anything anyhow.
|
||||
if (int_size_in_bytes(TREE_TYPE(lhs_tree)) == 0
|
||||
|| int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0)
|
||||
return this->compound_statement(this->expression_statement(lhs),
|
||||
this->expression_statement(rhs));
|
||||
|
||||
return this->make_statement(fold_build2_loc(location.gcc_location(),
|
||||
MODIFY_EXPR,
|
||||
void_type_node,
|
||||
@ -1178,6 +1211,48 @@ Gcc_backend::block_statement(Bblock* bblock)
|
||||
return this->make_statement(bind_tree);
|
||||
}
|
||||
|
||||
// This is not static because we declare it with GTY(()) in go-c.h.
|
||||
tree go_non_zero_struct;
|
||||
|
||||
// Return a type corresponding to TYPE with non-zero size.
|
||||
|
||||
tree
|
||||
Gcc_backend::non_zero_size_type(tree type)
|
||||
{
|
||||
if (int_size_in_bytes(type) != 0)
|
||||
return type;
|
||||
|
||||
switch (TREE_CODE(type))
|
||||
{
|
||||
case RECORD_TYPE:
|
||||
{
|
||||
if (go_non_zero_struct == NULL_TREE)
|
||||
{
|
||||
type = make_node(RECORD_TYPE);
|
||||
tree field = build_decl(UNKNOWN_LOCATION, FIELD_DECL,
|
||||
get_identifier("dummy"),
|
||||
boolean_type_node);
|
||||
DECL_CONTEXT(field) = type;
|
||||
TYPE_FIELDS(type) = field;
|
||||
layout_type(type);
|
||||
go_non_zero_struct = type;
|
||||
}
|
||||
return go_non_zero_struct;
|
||||
}
|
||||
|
||||
case ARRAY_TYPE:
|
||||
{
|
||||
tree element_type = non_zero_size_type(TREE_TYPE(type));
|
||||
return build_array_type_nelts(element_type, 1);
|
||||
}
|
||||
|
||||
default:
|
||||
gcc_unreachable();
|
||||
}
|
||||
|
||||
gcc_unreachable();
|
||||
}
|
||||
|
||||
// Make a global variable.
|
||||
|
||||
Bvariable*
|
||||
@ -1193,6 +1268,10 @@ Gcc_backend::global_variable(const std::string& package_name,
|
||||
if (type_tree == error_mark_node)
|
||||
return this->error_variable();
|
||||
|
||||
// The GNU linker does not like dynamic variables with zero size.
|
||||
if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0)
|
||||
type_tree = this->non_zero_size_type(type_tree);
|
||||
|
||||
std::string var_name(package_name);
|
||||
var_name.push_back('.');
|
||||
var_name.append(name);
|
||||
|
@ -843,7 +843,9 @@ Gogo::write_globals()
|
||||
this->backend()->global_variable_set_init(var,
|
||||
tree_to_expr(init));
|
||||
}
|
||||
else if (is_sink)
|
||||
else if (is_sink
|
||||
|| int_size_in_bytes(TREE_TYPE(init)) == 0
|
||||
|| int_size_in_bytes(TREE_TYPE(vec[i])) == 0)
|
||||
var_init_tree = init;
|
||||
else
|
||||
var_init_tree = fold_build2_loc(no->location().gcc_location(),
|
||||
|
Loading…
Reference in New Issue
Block a user