OSDN Git Service

Emit compiler errors for unused values.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Sep 2011 15:50:34 +0000 (15:50 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Sep 2011 15:50:34 +0000 (15:50 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179008 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/statements.h
gcc/go/gofrontend/types.cc

index 70f5f7c..43bcb5e 100644 (file)
@@ -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();
index c6ae12c..8cdf94d 100644 (file)
@@ -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
index 4a89ca8..221826b 100644 (file)
@@ -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();
index b18c989..06281db 100644 (file)
@@ -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 "&lt;-" Expression .
index 82be112..d78d2e2 100644 (file)
@@ -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;
 }
index a22090a..86b0f30 100644 (file)
@@ -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.
index fa3332a..68c35f4 100644 (file)
@@ -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();