The other Go compiler issues errors for unused values, including unused
calls to builtin functions that return no value. gccgo already had a
warning (under -Wunused-value) but not an error. This patch makes gccgo
compatible by issuing an error, and also issues errors for builtin
functions. Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 12eddb90c659 go/expressions.cc
--- a/go/expressions.cc Mon Sep 19 16:42:29 2011 -0700
+++ b/go/expressions.cc Tue Sep 20 08:47:01 2011 -0700
@@ -135,13 +135,13 @@
}
// 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 @@
go_unreachable();
}
-// Warn that the value of the expression is not used.
-
-void
-Expression::warn_about_unused_value()
-{
- warning_at(this->location(), OPT_Wunused_value, "value computed is not used");
+// Give an error saying that the value of the expression is not used.
+
+void
+Expression::unused_value_error()
+{
+ 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 @@
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 @@
bool
do_complex_constant_value(mpfr_t, mpfr_t, Type**) const;
+ void
+ do_discarding_value();
+
Type*
do_type();
@@ -7760,6 +7763,44 @@
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 @@
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 -r 12eddb90c659 go/expressions.h
--- a/go/expressions.h Mon Sep 19 16:42:29 2011 -0700
+++ b/go/expressions.h Tue Sep 20 08:47:01 2011 -0700
@@ -359,9 +359,9 @@
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 @@
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 -r 12eddb90c659 go/gogo.cc
--- a/go/gogo.cc Mon Sep 19 16:42:29 2011 -0700
+++ b/go/gogo.cc Tue Sep 20 08:47:01 2011 -0700
@@ -2017,7 +2017,7 @@
// 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 @@
{
// 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 @@
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 -r 12eddb90c659 go/parse.cc
--- a/go/parse.cc Mon Sep 19 16:42:29 2011 -0700
+++ b/go/parse.cc Tue Sep 20 08:47:01 2011 -0700
@@ -1839,7 +1839,7 @@
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 @@
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 -r 12eddb90c659 go/statements.cc
--- a/go/statements.cc Mon Sep 19 16:42:29 2011 -0700
+++ b/go/statements.cc Tue Sep 20 08:47:01 2011 -0700
@@ -924,7 +924,7 @@
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 @@
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 @@
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 @@
do_determine_types()
{ this->expr_->determine_type_no_context(); }
+ void
+ do_check_types(Gogo*);
+
bool
do_may_fall_through() const;
@@ -1643,8 +1646,21 @@
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 @@
// Make an expression statement from an Expression.
Statement*
-Statement::make_statement(Expression* expr)
-{
- return new Expression_statement(expr);
+Statement::make_statement(Expression* expr, bool is_ignored)
+{
+ return new Expression_statement(expr, is_ignored);
}
// A block statement--a list of statements which may include variable
@@ -2374,7 +2390,7 @@
// 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 @@
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 @@
}
else
{
- init->add_statement(Statement::make_statement(recv));
+ init->add_statement(Statement::make_statement(recv, true));
}
}
@@ -5593,7 +5609,7 @@
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 @@
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 @@
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 -r 12eddb90c659 go/statements.h
--- a/go/statements.h Mon Sep 19 16:42:29 2011 -0700
+++ b/go/statements.h Tue Sep 20 08:47:01 2011 -0700
@@ -178,9 +178,11 @@
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 -r 12eddb90c659 go/types.cc
--- a/go/types.cc Mon Sep 19 16:42:29 2011 -0700
+++ b/go/types.cc Tue Sep 20 08:47:01 2011 -0700
@@ -7432,7 +7432,7 @@
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();