From: ian Date: Tue, 20 Sep 2011 15:50:34 +0000 (+0000) Subject: Emit compiler errors for unused values. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=a7549a6a68672706dd0be3f65fe780f0632676fc Emit compiler errors for unused values. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179008 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 70f5f7c4423..43bcb5e616e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -135,13 +135,13 @@ Expression::do_traverse(Traverse*) } // This virtual function is called by the parser if the value of this -// expression is being discarded. By default, we warn. Expressions -// with side effects override. +// expression is being discarded. By default, we give an error. +// Expressions with side effects override. void Expression::do_discarding_value() { - this->warn_about_unused_value(); + this->unused_value_error(); } // This virtual function is called to export expressions. This will @@ -153,12 +153,12 @@ Expression::do_export(Export*) const go_unreachable(); } -// Warn that the value of the expression is not used. +// Give an error saying that the value of the expression is not used. void -Expression::warn_about_unused_value() +Expression::unused_value_error() { - warning_at(this->location(), OPT_Wunused_value, "value computed is not used"); + error_at(this->location(), "value computed is not used"); } // Note that this expression is an error. This is called by children @@ -5832,7 +5832,7 @@ Binary_expression::do_discarding_value() if (this->op_ == OPERATOR_OROR || this->op_ == OPERATOR_ANDAND) this->right_->discarding_value(); else - this->warn_about_unused_value(); + this->unused_value_error(); } // Get type. @@ -6951,6 +6951,9 @@ class Builtin_call_expression : public Call_expression bool do_complex_constant_value(mpfr_t, mpfr_t, Type**) const; + void + do_discarding_value(); + Type* do_type(); @@ -7760,6 +7763,44 @@ Builtin_call_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag, return false; } +// Give an error if we are discarding the value of an expression which +// should not normally be discarded. We don't give an error for +// discarding the value of an ordinary function call, but we do for +// builtin functions, purely for consistency with the gc compiler. + +void +Builtin_call_expression::do_discarding_value() +{ + switch (this->code_) + { + case BUILTIN_INVALID: + default: + go_unreachable(); + + case BUILTIN_APPEND: + case BUILTIN_CAP: + case BUILTIN_COMPLEX: + case BUILTIN_IMAG: + case BUILTIN_LEN: + case BUILTIN_MAKE: + case BUILTIN_NEW: + case BUILTIN_REAL: + case BUILTIN_ALIGNOF: + case BUILTIN_OFFSETOF: + case BUILTIN_SIZEOF: + this->unused_value_error(); + break; + + case BUILTIN_CLOSE: + case BUILTIN_COPY: + case BUILTIN_PANIC: + case BUILTIN_PRINT: + case BUILTIN_PRINTLN: + case BUILTIN_RECOVER: + break; + } +} + // Return the type. Type* @@ -11241,7 +11282,7 @@ Selector_expression::lower_method_expression(Gogo* gogo) size_t count = call->result_count(); Statement* s; if (count == 0) - s = Statement::make_statement(call); + s = Statement::make_statement(call, true); else { Expression_list* retvals = new Expression_list(); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index c6ae12ce048..8cdf94d2e78 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -359,9 +359,9 @@ class Expression string_constant_value(std::string* val) const { return this->do_string_constant_value(val); } - // This is called by the parser if the value of this expression is - // being discarded. This issues warnings about computed values - // being unused. + // This is called if the value of this expression is being + // discarded. This issues warnings about computed values being + // unused. void discarding_value() { this->do_discarding_value(); } @@ -725,9 +725,9 @@ class Expression virtual void do_export(Export*) const; - // For children to call to warn about an unused value. + // For children to call to give an error for an unused value. void - warn_about_unused_value(); + unused_value_error(); // For children to call when they detect that they are in error. void diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 4a89ca80ba5..221826bb62b 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -2017,7 +2017,7 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s) // be handled specially. We can't create a temporary // because there is no type to give it. Any actual uses of // the values will be done via Call_result_expressions. - s = Statement::make_statement(*pexpr); + s = Statement::make_statement(*pexpr, true); } block->insert_statement_before(*pindex, s); @@ -2072,7 +2072,7 @@ Order_eval::variable(Named_object* no) { // A call expression which returns multiple results needs to // be handled specially. - s = Statement::make_statement(*pexpr); + s = Statement::make_statement(*pexpr, true); } var->add_preinit_statement(this->gogo_, s); } @@ -2266,7 +2266,7 @@ Build_recover_thunks::function(Named_object* orig_no) Statement* s; if (orig_fntype->results() == NULL || orig_fntype->results()->empty()) - s = Statement::make_statement(call); + s = Statement::make_statement(call, true); else { Expression_list* vals = new Expression_list(); diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index b18c9892285..06281db96cf 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1839,7 +1839,7 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init, if (!type_from_init && init != NULL) { if (!this->gogo_->in_global_scope()) - this->gogo_->add_statement(Statement::make_statement(init)); + this->gogo_->add_statement(Statement::make_statement(init, true)); else return this->create_dummy_global(type, init, location); } @@ -3506,8 +3506,7 @@ Parse::statement_list_may_start_here() void Parse::expression_stat(Expression* exp) { - exp->discarding_value(); - this->gogo_->add_statement(Statement::make_statement(exp)); + this->gogo_->add_statement(Statement::make_statement(exp, false)); } // SendStmt = Channel "<-" Expression . diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 82be1129028..d78d2e2b529 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -924,7 +924,7 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, if ((*plhs)->is_sink_expression()) { - b->add_statement(Statement::make_statement(*prhs)); + b->add_statement(Statement::make_statement(*prhs, true)); continue; } @@ -1240,7 +1240,7 @@ Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, Expression* p4 = Expression::make_temporary_reference(insert_temp, loc); Expression* call = Runtime::make_call(Runtime::MAPASSIGN2, loc, 4, p1, p2, p3, p4); - Statement* s = Statement::make_statement(call); + Statement* s = Statement::make_statement(call, true); b->add_statement(s); return Statement::make_block_statement(b, loc); @@ -1614,9 +1614,9 @@ Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok, class Expression_statement : public Statement { public: - Expression_statement(Expression* expr) + Expression_statement(Expression* expr, bool is_ignored) : Statement(STATEMENT_EXPRESSION, expr->location()), - expr_(expr) + expr_(expr), is_ignored_(is_ignored) { } Expression* @@ -1632,6 +1632,9 @@ class Expression_statement : public Statement do_determine_types() { this->expr_->determine_type_no_context(); } + void + do_check_types(Gogo*); + bool do_may_fall_through() const; @@ -1643,8 +1646,21 @@ class Expression_statement : public Statement private: Expression* expr_; + // Whether the value of this expression is being explicitly ignored. + bool is_ignored_; }; +// Check the types of an expression statement. The only check we do +// is to possibly give an error about discarding the value of the +// expression. + +void +Expression_statement::do_check_types(Gogo*) +{ + if (!this->is_ignored_) + this->expr_->discarding_value(); +} + // An expression statement may fall through unless it is a call to a // function which does not return. @@ -1699,9 +1715,9 @@ Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context) // Make an expression statement from an Expression. Statement* -Statement::make_statement(Expression* expr) +Statement::make_statement(Expression* expr, bool is_ignored) { - return new Expression_statement(expr); + return new Expression_statement(expr, is_ignored); } // A block statement--a list of statements which may include variable @@ -2374,7 +2390,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name) // receiver parameter. call->set_varargs_are_lowered(); - Statement* call_statement = Statement::make_statement(call); + Statement* call_statement = Statement::make_statement(call, true); gogo->add_statement(call_statement); @@ -3791,7 +3807,7 @@ Switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing, Expression* val = this->val_; if (val == NULL) val = Expression::make_boolean(true, loc); - return Statement::make_statement(val); + return Statement::make_statement(val, true); } Temporary_statement* val_temp; @@ -4516,7 +4532,7 @@ Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function, } else { - init->add_statement(Statement::make_statement(recv)); + init->add_statement(Statement::make_statement(recv, true)); } } @@ -5593,7 +5609,7 @@ For_range_statement::lower_range_map(Gogo*, Expression* ref = Expression::make_temporary_reference(hiter, loc); Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc); Expression* call = Runtime::make_call(Runtime::MAPITERINIT, loc, 2, p1, p2); - init->add_statement(Statement::make_statement(call)); + init->add_statement(Statement::make_statement(call, true)); *pinit = init; @@ -5634,7 +5650,7 @@ For_range_statement::lower_range_map(Gogo*, Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc); call = Runtime::make_call(Runtime::MAPITER2, loc, 3, p1, p2, p3); } - iter_init->add_statement(Statement::make_statement(call)); + iter_init->add_statement(Statement::make_statement(call, true)); *piter_init = iter_init; @@ -5646,7 +5662,7 @@ For_range_statement::lower_range_map(Gogo*, ref = Expression::make_temporary_reference(hiter, loc); p1 = Expression::make_unary(OPERATOR_AND, ref, loc); call = Runtime::make_call(Runtime::MAPITERNEXT, loc, 1, p1); - post->add_statement(Statement::make_statement(call)); + post->add_statement(Statement::make_statement(call, true)); *ppost = post; } diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index a22090a5fe9..86b0f305148 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -178,9 +178,11 @@ class Statement Expression* expr, Type* type, source_location); - // Make an expression statement from an Expression. + // Make an expression statement from an Expression. IS_IGNORED is + // true if the value is being explicitly ignored, as in an + // assignment to _. static Statement* - make_statement(Expression*); + make_statement(Expression*, bool is_ignored); // Make a block statement from a Block. This is an embedded list of // statements which may also include variable definitions. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index fa3332ad556..68c35f40764 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -7432,7 +7432,7 @@ Type::build_one_stub_method(Gogo* gogo, Method* method, call->set_hidden_fields_are_ok(); size_t count = call->result_count(); if (count == 0) - gogo->add_statement(Statement::make_statement(call)); + gogo->add_statement(Statement::make_statement(call, true)); else { Expression_list* retvals = new Expression_list();