GO_EXTERN_C
void
go_parse_input_files(const char** filenames, unsigned int filename_count,
- bool only_check_syntax, bool require_return_statement)
+ bool only_check_syntax, bool)
{
go_assert(filename_count > 0);
// Finalize method lists and build stub methods for named types.
::gogo->finalize_methods();
+ // Check that functions have a terminating statement.
+ ::gogo->check_return_statements();
+
// Now that we have seen all the names, lower the parse tree into a
// form which is easier to use.
::gogo->lower_parse_tree();
if (only_check_syntax)
return;
- // Check that functions have return statements.
- if (require_return_statement)
- ::gogo->check_return_statements();
-
// Export global identifiers as appropriate.
::gogo->do_exports();
this->expr_->discarding_value();
}
-// An expression statement may fall through unless it is a call to a
-// function which does not return.
+// An expression statement is only a terminating statement if it is
+// a call to panic.
bool
Expression_statement::do_may_fall_through() const
if (call != NULL)
{
const Expression* fn = call->fn();
- const Func_expression* fe = fn->func_expression();
- if (fe != NULL)
+ // panic is still an unknown named object.
+ const Unknown_expression* ue = fn->unknown_expression();
+ if (ue != NULL)
{
- const Named_object* no = fe->named_object();
+ Named_object* no = ue->named_object();
- Function_type* fntype;
- if (no->is_function())
- fntype = no->func_value()->type();
- else if (no->is_function_declaration())
- fntype = no->func_declaration_value()->type();
- else
- fntype = NULL;
-
- // The builtin function panic does not return.
- if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
- return false;
+ if (no->is_unknown())
+ no = no->unknown_value()->real_named_object();
+ if (no != NULL)
+ {
+ Function_type* fntype;
+ if (no->is_function())
+ fntype = no->func_value()->type();
+ else if (no->is_function_declaration())
+ fntype = no->func_declaration_value()->type();
+ else
+ fntype = NULL;
+
+ // The builtin function panic does not return.
+ if (fntype != NULL && fntype->is_builtin() && no->name() == "panic")
+ return false;
+ }
}
}
return true;
void
do_check_types(Gogo*);
- bool
- do_may_fall_through() const;
-
Bstatement*
do_get_backend(Translate_context*);
this->set_is_error();
}
-// Return whether this switch may fall through.
-
-bool
-Constant_switch_statement::do_may_fall_through() const
-{
- if (this->clauses_ == NULL)
- return true;
-
- // If we have a break label, then some case needed it. That implies
- // that the switch statement as a whole can fall through.
- if (this->break_label_ != NULL)
- return true;
-
- return this->clauses_->may_fall_through();
-}
-
// Convert to GENERIC.
Bstatement*
ast_dump_context->ostream() << std::endl;
}
+// Return whether this switch may fall through.
+
+bool
+Switch_statement::do_may_fall_through() const
+{
+ if (this->clauses_ == NULL)
+ return true;
+
+ // If we have a break label, then some case needed it. That implies
+ // that the switch statement as a whole can fall through.
+ if (this->break_label_ != NULL)
+ return true;
+
+ return this->clauses_->may_fall_through();
+}
+
// Make a switch statement.
Switch_statement*
}
}
+// Return true if this type clause may fall through to the statements
+// following the switch.
+
+bool
+Type_case_clauses::Type_case_clause::may_fall_through() const
+{
+ if (this->statements_ == NULL)
+ return true;
+ return this->statements_->may_fall_through();
+}
+
// Dump the AST representation for a type case clause
void
NULL);
}
+// Return true if these clauses may fall through to the statements
+// following the switch statement.
+
+bool
+Type_case_clauses::may_fall_through() const
+{
+ bool found_default = false;
+ for (Type_clauses::const_iterator p = this->clauses_.begin();
+ p != this->clauses_.end();
+ ++p)
+ {
+ if (p->may_fall_through())
+ return true;
+ if (p->is_default())
+ found_default = true;
+ }
+ return !found_default;
+}
+
// Dump the AST representation for case clauses (from a switch statement)
void
return Statement::make_block_statement(b, loc);
}
+// Return whether this switch may fall through.
+
+bool
+Type_switch_statement::do_may_fall_through() const
+{
+ if (this->clauses_ == NULL)
+ return true;
+
+ // If we have a break label, then some case needed it. That implies
+ // that the switch statement as a whole can fall through.
+ if (this->break_label_ != NULL)
+ return true;
+
+ return this->clauses_->may_fall_through();
+}
+
// Return the break label for this type switch statement, creating it
// if necessary.
return Statement::make_block_statement(b, loc);
}
+// Whether the select statement itself may fall through to the following
+// statement.
+
+bool
+Select_statement::do_may_fall_through() const
+{
+ // A select statement is terminating if no break statement
+ // refers to it and all of its clauses are terminating.
+ if (this->break_label_ != NULL)
+ return true;
+ return this->clauses_->may_fall_through();
+}
+
// Return the backend representation for a select statement.
Bstatement*
this->continue_label_ = continue_label;
}
+// Whether the overall statement may fall through.
+
+bool
+For_statement::do_may_fall_through() const
+{
+ // A for loop is terminating if it has no condition and
+ // no break statement.
+ if(this->cond_ != NULL)
+ return true;
+ if(this->break_label_ != NULL)
+ return true;
+ return false;
+}
+
// Dump the AST representation for a for statement.
void
{ this->clauses_->check_types(); }
bool
- do_may_fall_through() const
- { return this->clauses_->may_fall_through(); }
+ do_may_fall_through() const;
Bstatement*
do_get_backend(Translate_context*);
Statement*
do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
+ bool
+ do_may_fall_through() const;
+
Bstatement*
do_get_backend(Translate_context*)
{ go_unreachable(); }
void
do_dump_statement(Ast_dump_context*) const;
+ bool
+ do_may_fall_through() const;
+
private:
// The value to switch on. This may be NULL.
Expression* val_;
lower(Type*, Block*, Temporary_statement* descriptor_temp,
Unnamed_label* break_label) const;
+ // Return true if these clauses may fall through to the statements
+ // following the switch statement.
+ bool
+ may_fall_through() const;
+
// Dump the AST representation to a dump context.
void
dump_clauses(Ast_dump_context*) const;
lower(Type*, Block*, Temporary_statement* descriptor_temp,
Unnamed_label* break_label, Unnamed_label** stmts_label) const;
+ // Return true if this clause may fall through to execute the
+ // statements following the switch statement. This is not the
+ // same as whether this clause falls through to the next clause.
+ bool
+ may_fall_through() const;
+
// Dump the AST representation to a dump context.
void
dump_clause(Ast_dump_context*) const;
void
do_dump_statement(Ast_dump_context*) const;
+ bool
+ do_may_fall_through() const;
+
private:
// The variable holding the value we are switching on.
Named_object* var_;