#include "convert.h"
#include "output.h"
#include "diagnostic.h"
-#include "rtl.h"
#ifndef ENABLE_BUILD_WITH_CXX
}
if (this->init_fn_name_.empty())
{
gcc_assert(this->package_ != NULL);
- if (this->package_name() == "main")
+ if (this->is_main_package())
{
// Use a name which the runtime knows.
this->init_fn_name_ = "__go_init_main";
void
Gogo::init_imports(tree* init_stmt_list)
{
- gcc_assert(this->package_name() == "main");
+ gcc_assert(this->is_main_package());
if (this->imported_init_fns_.empty())
return;
void_type_node,
build_pointer_type(root_list_type),
build_fold_addr_expr(decl));
- append_to_statement_list(call, init_stmt_list);
+ if (call != error_mark_node)
+ append_to_statement_list(call, init_stmt_list);
}
// Build the decl for the initialization function.
{
// Make sure that we thought we needed an initialization function,
// as otherwise we will not have reported it in the export data.
- gcc_assert(this->package_name() == "main" || this->need_init_fn_);
+ gcc_assert(this->is_main_package() || this->need_init_fn_);
if (fndecl == NULL_TREE)
fndecl = this->initialization_function_decl();
void
Gogo::write_globals()
{
+ this->convert_named_types();
+ this->build_interface_method_tables();
+
Bindings* bindings = this->current_bindings();
size_t count = bindings->size_definitions();
tree init_fndecl = NULL_TREE;
tree init_stmt_list = NULL_TREE;
- if (this->package_name() == "main")
+ if (this->is_main_package())
this->init_imports(&init_stmt_list);
// A list of variable initializations.
pop_cfun();
}
- if (var_init_tree != NULL_TREE)
+ if (var_init_tree != NULL_TREE && var_init_tree != error_mark_node)
{
if (no->var_value()->init() == NULL
&& !no->var_value()->has_pre_init())
// This will be called if this package is imported.
if (init_stmt_list != NULL_TREE
|| this->need_init_fn_
- || this->package_name() == "main")
+ || this->is_main_package())
this->write_initialization_function(init_fndecl, init_stmt_list);
// Pass everything back to the middle-end.
- if (this->imported_unsafe_)
- {
- // Importing the "unsafe" package automatically disables TBAA.
- flag_strict_aliasing = false;
-
- // This is a real hack. init_varasm_once has already grabbed an
- // alias set, which we don't want when we aren't going strict
- // aliasing. We reinitialize to make it do it again. FIXME.
- init_varasm_once();
- }
-
wrapup_global_declarations(vec, count);
cgraph_finalize_compilation_unit();
Translate_context context(gogo, function, NULL, NULL_TREE);
tree block_tree = this->preinit_->get_tree(&context);
+ if (block_tree == error_mark_node)
+ return error_mark_node;
gcc_assert(TREE_CODE(block_tree) == BIND_EXPR);
tree statements = BIND_EXPR_BODY(block_tree);
- while (TREE_CODE(statements) == TRY_FINALLY_EXPR
- || TREE_CODE(statements) == TRY_CATCH_EXPR)
+ while (statements != NULL_TREE
+ && (TREE_CODE(statements) == TRY_FINALLY_EXPR
+ || TREE_CODE(statements) == TRY_CATCH_EXPR))
statements = TREE_OPERAND(statements, 0);
// It's possible to have pre-init statements without an initializer
if (this->init_ != NULL)
{
tree rhs_tree = this->init_->get_tree(&context);
+ if (rhs_tree == error_mark_node)
+ return error_mark_node;
if (var_decl == NULL_TREE)
append_to_statement_list(rhs_tree, &statements);
else
this->init_->type(),
rhs_tree,
this->location());
+ if (val == error_mark_node)
+ return error_mark_node;
tree set = fold_build2_loc(this->location(), MODIFY_EXPR,
void_type_node, var_decl, val);
append_to_statement_list(set, &statements);
this->fndecl_ = decl;
- gcc_assert(no->package() == NULL);
- if (this->enclosing_ != NULL || Gogo::is_thunk(no))
+ if (no->package() != NULL)
+ ;
+ else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
;
else if (Gogo::unpack_hidden_name(no->name()) == "init"
&& !this->type_->is_method())
;
else if (Gogo::unpack_hidden_name(no->name()) == "main"
- && gogo->package_name() == "main")
+ && gogo->is_main_package())
TREE_PUBLIC(decl) = 1;
// Methods have to be public even if they are hidden because
// they can be pulled into type descriptors when using
push_struct_function(decl);
tree closure_decl = this->closure_var_->get_tree(gogo, no);
+ if (closure_decl == error_mark_node)
+ this->fndecl_ = error_mark_node;
+ else
+ {
+ DECL_ARTIFICIAL(closure_decl) = 1;
+ DECL_IGNORED_P(closure_decl) = 1;
+ TREE_USED(closure_decl) = 1;
+ DECL_ARG_TYPE(closure_decl) = TREE_TYPE(closure_decl);
+ TREE_READONLY(closure_decl) = 1;
- DECL_ARTIFICIAL(closure_decl) = 1;
- DECL_IGNORED_P(closure_decl) = 1;
- TREE_USED(closure_decl) = 1;
- DECL_ARG_TYPE(closure_decl) = TREE_TYPE(closure_decl);
- TREE_READONLY(closure_decl) = 1;
+ DECL_STRUCT_FUNCTION(decl)->static_chain_decl = closure_decl;
+ }
- DECL_STRUCT_FUNCTION(decl)->static_chain_decl = closure_decl;
pop_cfun();
}
}
tree
Function::make_receiver_parm_decl(Gogo* gogo, Named_object* no, tree var_decl)
{
+ if (var_decl == error_mark_node)
+ return error_mark_node;
// If the function takes the address of a receiver which is passed
// by value, then we will have an INDIRECT_REF here. We need to get
// the real variable.
{
gcc_assert(is_in_heap);
var_decl = TREE_OPERAND(var_decl, 0);
+ if (var_decl == error_mark_node)
+ return error_mark_node;
gcc_assert(POINTER_TYPE_P(TREE_TYPE(var_decl)));
val_type = TREE_TYPE(TREE_TYPE(var_decl));
}
tree
Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree ref)
{
+ if (ref == error_mark_node)
+ return error_mark_node;
+
gcc_assert(TREE_CODE(ref) == INDIRECT_REF);
tree var_decl = TREE_OPERAND(ref, 0);
+ if (var_decl == error_mark_node)
+ return error_mark_node;
gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
source_location loc = DECL_SOURCE_LOCATION(var_decl);
tree var = *pp;
if (TREE_CODE(var) == INDIRECT_REF)
var = TREE_OPERAND(var, 0);
- gcc_assert(TREE_CODE(var) == VAR_DECL);
- DECL_CHAIN(var) = declare_vars;
- declare_vars = var;
+ if (var != error_mark_node)
+ {
+ gcc_assert(TREE_CODE(var) == VAR_DECL);
+ DECL_CHAIN(var) = declare_vars;
+ declare_vars = var;
+ }
*pp = parm_decl;
}
else if ((*p)->var_value()->is_in_heap())
// If we take the address of a parameter, then we need
// to copy it into the heap.
tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp);
- gcc_assert(TREE_CODE(*pp) == INDIRECT_REF);
- tree var_decl = TREE_OPERAND(*pp, 0);
- gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
- DECL_CHAIN(var_decl) = declare_vars;
- declare_vars = var_decl;
+ if (*pp != error_mark_node)
+ {
+ gcc_assert(TREE_CODE(*pp) == INDIRECT_REF);
+ tree var_decl = TREE_OPERAND(*pp, 0);
+ if (var_decl != error_mark_node)
+ {
+ gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
+ DECL_CHAIN(var_decl) = declare_vars;
+ declare_vars = var_decl;
+ }
+ }
*pp = parm_decl;
}
void_type_node,
ptr_type_node,
this->defer_stack(end_loc));
- append_to_statement_list(call, &stmt_list);
+ if (call != error_mark_node)
+ append_to_statement_list(call, &stmt_list);
tree retval = this->return_value(gogo, named_function, end_loc, &stmt_list);
tree set;
void_type_node,
ptr_type_node,
this->defer_stack(end_loc));
- TREE_NOTHROW(undefer_fndecl) = 0;
+ if (undefer_fndecl != NULL_TREE)
+ TREE_NOTHROW(undefer_fndecl) = 0;
tree defer = Gogo::call_builtin(&check_fndecl,
end_loc,
Map_descriptors::iterator p = ins.first;
if (!ins.second)
{
+ if (p->second == error_mark_node)
+ return error_mark_node;
gcc_assert(p->second != NULL_TREE && DECL_P(p->second));
return build_fold_addr_expr(p->second);
}
"__val",
valtype->get_tree(this));
if (map_entry_type == error_mark_node)
- return error_mark_node;
+ {
+ p->second = error_mark_node;
+ return error_mark_node;
+ }
tree map_entry_key_field = DECL_CHAIN(TYPE_FIELDS(map_entry_type));
gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(map_entry_key_field)),
DECL_INITIAL(decl) = constructor;
- if (type_descriptor_location == TYPE_DESCRIPTOR_COMMON)
+ if (type_descriptor_location == TYPE_DESCRIPTOR_DEFINED)
+ TREE_PUBLIC(decl) = 1;
+ else
{
+ gcc_assert(type_descriptor_location == TYPE_DESCRIPTOR_COMMON);
make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
resolve_unique_section(decl, 1, 0);
}
- else
- {
-#ifdef OBJECT_FORMAT_ELF
- // Give the decl protected visibility. This avoids out-of-range
- // references with shared libraries with the x86_64 small model
- // when the type descriptor gets a COPY reloc into the main
- // executable. There is no need to have unique pointers to type
- // descriptors, as the runtime code compares reflection strings
- // if necessary.
- DECL_VISIBILITY(decl) = VISIBILITY_PROTECTED;
- DECL_VISIBILITY_SPECIFIED(decl) = 1;
-#endif
-
- TREE_PUBLIC(decl) = 1;
- }
rest_of_decl_compilation(decl, 1, 0);
}
// definition of the table. Otherwise it is a comdat table which
// may be defined in multiple packages.
if (has_hidden_methods)
- {
-#ifdef OBJECT_FORMAT_ELF
- // Give the decl protected visibility. This avoids out-of-range
- // references with shared libraries with the x86_64 small model
- // when the table gets a COPY reloc into the main executable.
- DECL_VISIBILITY(decl) = VISIBILITY_PROTECTED;
- DECL_VISIBILITY_SPECIFIED(decl) = 1;
-#endif
-
- TREE_PUBLIC(decl) = 1;
- }
+ TREE_PUBLIC(decl) = 1;
else
{
make_decl_one_only(decl, DECL_ASSEMBLER_NAME(decl));
types[i] = va_arg(ap, tree);
args[i] = va_arg(ap, tree);
if (types[i] == error_mark_node || args[i] == error_mark_node)
- return error_mark_node;
+ {
+ delete[] types;
+ delete[] args;
+ return error_mark_node;
+ }
}
va_end(ap);
void_type_node,
integer_type_node,
build_int_cst(integer_type_node, code));
+ if (ret == error_mark_node)
+ return error_mark_node;
// The runtime error function panics and does not return.
TREE_NOTHROW(runtime_error_fndecl) = 0;
TREE_THIS_VOLATILE(runtime_error_fndecl) = 1;
Gogo::send_on_channel(tree channel, tree val, bool blocking, bool for_select,
source_location location)
{
+ if (channel == error_mark_node || val == error_mark_node)
+ return error_mark_node;
+
if (int_size_in_bytes(TREE_TYPE(val)) <= 8
&& !AGGREGATE_TYPE_P(TREE_TYPE(val))
&& !FLOAT_TYPE_P(TREE_TYPE(val)))
(for_select
? boolean_true_node
: boolean_false_node));
+ if (ret == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW(send_small_fndecl) = 0;
channel,
uint64_type_node,
val);
+ if (ret == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW(send_nonblocking_small_fndecl) = 0;
(for_select
? boolean_true_node
: boolean_false_node));
+ if (call == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW(send_big_fndecl) = 0;
channel,
ptr_type_node,
val);
+ if (call == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW(send_nonblocking_big_fndecl) = 0;
Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
source_location location)
{
+ if (type_tree == error_mark_node || channel == error_mark_node)
+ return error_mark_node;
+
if (int_size_in_bytes(type_tree) <= 8
&& !AGGREGATE_TYPE_P(type_tree)
&& !FLOAT_TYPE_P(type_tree))
(for_select
? boolean_true_node
: boolean_false_node));
+ if (call == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a closed
// channel.
TREE_NOTHROW(receive_small_fndecl) = 0;
(for_select
? boolean_true_node
: boolean_false_node));
+ if (call == error_mark_node)
+ return error_mark_node;
// This can panic if there are too many operations on a closed
// channel.
TREE_NOTHROW(receive_big_fndecl) = 0;
ptr_type_node,
fold_convert_loc(location, ptr_type_node,
closure));
+ if (x == error_mark_node)
+ return error_mark_node;
x = save_expr(x);