This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: clean up handling of undefined types


While parsing, the Go frontend has to not consider an undefined type to
be an error, since it might be defined later.  After parsing is
complete, an undefined type is an error in most cases, except perhaps
for a reference to an imported variable that is not actually used.  This
patch tries to clean up the handling of undefined types by treating them
as error types when they have to be defined.  The main effect of this
change in practice is to avoid additional error messages.  Bootstrapped
and ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to
mainline.

Ian

diff -r 8abc3b3b94c8 go/expressions.cc
--- a/go/expressions.cc	Fri Mar 25 12:21:40 2011 -0700
+++ b/go/expressions.cc	Fri Mar 25 13:38:47 2011 -0700
@@ -205,17 +205,9 @@
   if (lhs_type == rhs_type)
     return rhs_tree;
 
-  if (lhs_type->is_error_type() || rhs_type->is_error_type())
+  if (lhs_type->is_error() || rhs_type->is_error())
     return error_mark_node;
 
-  if (lhs_type->is_undefined() || rhs_type->is_undefined())
-    {
-      // Make sure we report the error.
-      lhs_type->base();
-      rhs_type->base();
-      return error_mark_node;
-    }
-
   if (rhs_tree == error_mark_node || TREE_TYPE(rhs_tree) == error_mark_node)
     return error_mark_node;
 
@@ -2628,7 +2620,7 @@
 void
 Const_expression::check_for_init_loop()
 {
-  if (this->type_ != NULL && this->type_->is_error_type())
+  if (this->type_ != NULL && this->type_->is_error())
     return;
 
   if (this->seen_)
@@ -2647,7 +2639,7 @@
 
   if (find_named_object.found())
     {
-      if (this->type_ == NULL || !this->type_->is_error_type())
+      if (this->type_ == NULL || !this->type_->is_error())
 	{
 	  this->report_error(_("constant refers to itself"));
 	  this->type_ = Type::make_error_type();
@@ -2661,7 +2653,7 @@
 void
 Const_expression::do_check_types(Gogo*)
 {
-  if (this->type_ != NULL && this->type_->is_error_type())
+  if (this->type_ != NULL && this->type_->is_error())
     return;
 
   this->check_for_init_loop();
@@ -3311,14 +3303,8 @@
   Type* expr_type = this->expr_->type();
   std::string reason;
 
-  if (type->is_error_type()
-      || type->is_undefined()
-      || expr_type->is_error_type()
-      || expr_type->is_undefined())
-    {
-      // Make sure we emit an error for an undefined type.
-      type->base();
-      expr_type->base();
+  if (type->is_error() || expr_type->is_error())
+    {
       this->set_is_error();
       return;
     }
@@ -4027,7 +4013,7 @@
 Unary_expression::do_check_types(Gogo*)
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     {
       this->set_is_error();
       return;
@@ -5447,9 +5433,9 @@
       {
 	Type* left_type = this->left_->type();
 	Type* right_type = this->right_->type();
-	if (left_type->is_error_type())
+	if (left_type->is_error())
 	  return left_type;
-	else if (right_type->is_error_type())
+	else if (right_type->is_error())
 	  return right_type;
 	else if (!Type::are_compatible_for_binop(left_type, right_type))
 	  {
@@ -5688,7 +5674,7 @@
 
   Type* left_type = this->left_->type();
   Type* right_type = this->right_->type();
-  if (left_type->is_error_type() || right_type->is_error_type())
+  if (left_type->is_error() || right_type->is_error())
     {
       this->set_is_error();
       return;
@@ -7001,7 +6987,7 @@
       if (arg == NULL)
 	return false;
       Type* arg_type = arg->type();
-      if (arg_type->is_error_type() || arg_type->is_undefined())
+      if (arg_type->is_error())
 	return false;
       if (arg_type->is_abstract())
 	return false;
@@ -7354,8 +7340,7 @@
       return false;
     }
   if (args->front()->is_error_expression()
-      || args->front()->type()->is_error_type()
-      || args->front()->type()->is_undefined())
+      || args->front()->type()->is_error())
     {
       this->set_is_error();
       return false;
@@ -7389,7 +7374,7 @@
 	      arg_type = arg_type->points_to();
 	    if (this->code_ == BUILTIN_CAP)
 	      {
-		if (!arg_type->is_error_type()
+		if (!arg_type->is_error()
 		    && arg_type->array_type() == NULL
 		    && arg_type->channel_type() == NULL)
 		  this->report_error(_("argument must be array or slice "
@@ -7397,7 +7382,7 @@
 	      }
 	    else
 	      {
-		if (!arg_type->is_error_type()
+		if (!arg_type->is_error()
 		    && !arg_type->is_string_type()
 		    && arg_type->array_type() == NULL
 		    && arg_type->map_type() == NULL
@@ -7429,7 +7414,7 @@
 		 ++p)
 	      {
 		Type* type = (*p)->type();
-		if (type->is_error_type()
+		if (type->is_error()
 		    || type->is_string_type()
 		    || type->integer_type() != NULL
 		    || type->float_type() != NULL
@@ -7493,7 +7478,7 @@
 	  }
 	Type* arg1_type = args->front()->type();
 	Type* arg2_type = args->back()->type();
-	if (arg1_type->is_error_type() || arg2_type->is_error_type())
+	if (arg1_type->is_error() || arg2_type->is_error())
 	  break;
 
 	Type* e1;
@@ -7568,9 +7553,9 @@
 	else if (args->size() > 2)
 	  this->report_error(_("too many arguments"));
 	else if (args->front()->is_error_expression()
-		 || args->front()->type()->is_error_type()
+		 || args->front()->type()->is_error()
 		 || args->back()->is_error_expression()
-		 || args->back()->type()->is_error_type())
+		 || args->back()->type()->is_error())
 	  this->set_is_error();
 	else if (!Type::are_identical(args->front()->type(),
 				      args->back()->type(), true, NULL))
@@ -8540,7 +8525,7 @@
   Function_type* fntype = this->get_function_type();
   if (fntype == NULL)
     {
-      if (!this->fn_->type()->is_error_type())
+      if (!this->fn_->type()->is_error())
 	this->report_error(_("expected function"));
       return;
     }
@@ -9060,7 +9045,7 @@
   Expression* end = this->end_;
 
   Type* type = left->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return Expression::make_error(location);
   else if (left->is_type_expression())
     {
@@ -9236,7 +9221,7 @@
   Array_type* array_type = this->array_->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->array_->type()->is_error_type());
+      gcc_assert(this->array_->type()->is_error());
       return;
     }
 
@@ -9318,7 +9303,7 @@
   Array_type* array_type = this->array_->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->array_->type()->is_error_type());
+      gcc_assert(this->array_->type()->is_error());
       return error_mark_node;
     }
 
@@ -9979,7 +9964,7 @@
 Field_reference_expression::do_type()
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return type;
   Struct_type* struct_type = type->struct_type();
   gcc_assert(struct_type != NULL);
@@ -9992,7 +9977,7 @@
 Field_reference_expression::do_check_types(Gogo*)
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return;
   Struct_type* struct_type = type->struct_type();
   gcc_assert(struct_type != NULL);
@@ -11140,7 +11125,7 @@
   Array_type* array_type = this->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->type()->is_error_type());
+      gcc_assert(this->type()->is_error());
       return error_mark_node;
     }
 
@@ -11659,7 +11644,7 @@
 	type = type->map_type()->val_type();
       else
 	{
-	  if (!type->is_error_type())
+	  if (!type->is_error())
 	    error_at(this->location(),
 		     ("may only omit types within composite literals "
 		      "of slice, array, or map type"));
@@ -11667,7 +11652,7 @@
 	}
     }
 
-  if (type->is_error_type())
+  if (type->is_error())
     return Expression::make_error(this->location());
   else if (type->struct_type() != NULL)
     return this->lower_struct(gogo, type);
@@ -12132,7 +12117,7 @@
     }
   else if (expr_type->interface_type() == NULL)
     {
-      if (!expr_type->is_error_type() && !this->type_->is_error_type())
+      if (!expr_type->is_error() && !this->type_->is_error())
 	this->report_error(_("type assertion only valid for interface types"));
       this->set_is_error();
     }
@@ -12142,7 +12127,7 @@
       if (!expr_type->interface_type()->implements_interface(this->type_,
 							     &reason))
 	{
-	  if (!this->type_->is_error_type())
+	  if (!this->type_->is_error())
 	    {
 	      if (reason.empty())
 		this->report_error(_("impossible type assertion: "
@@ -12294,7 +12279,7 @@
 Receive_expression::do_check_types(Gogo*)
 {
   Type* type = this->channel_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     {
       this->set_is_error();
       return;
@@ -12319,7 +12304,7 @@
   Channel_type* channel_type = this->channel_->type()->channel_type();
   if (channel_type == NULL)
     {
-      gcc_assert(this->channel_->type()->is_error_type());
+      gcc_assert(this->channel_->type()->is_error());
       return error_mark_node;
     }
   Type* element_type = channel_type->element_type();
diff -r 8abc3b3b94c8 go/gogo-tree.cc
--- a/go/gogo-tree.cc	Fri Mar 25 12:21:40 2011 -0700
+++ b/go/gogo-tree.cc	Fri Mar 25 13:38:47 2011 -0700
@@ -914,14 +914,10 @@
 	    Type* type = named_constant->type();
 	    if (type != NULL && !type->is_abstract())
 	      {
-		if (!type->is_undefined())
+		if (!type->is_error())
 		  expr_tree = fold_convert(type->get_tree(gogo), expr_tree);
 		else
-		  {
-		    // Make sure we report the error.
-		    type->base();
-		    expr_tree = error_mark_node;
-		  }
+		  expr_tree = error_mark_node;
 	      }
 	    if (expr_tree == error_mark_node)
 	      decl = error_mark_node;
@@ -1047,12 +1043,8 @@
       {
 	Result_variable* result = this->u_.result_var_value;
 	Type* type = result->type();
-	if (type->is_error_type() || type->is_undefined())
-	  {
-	    // Force the error.
-	    type->base();
-	    decl = error_mark_node;
-	  }
+	if (type->is_error())
+	  decl = error_mark_node;
 	else
 	  {
 	    gcc_assert(result->function() == function->func_value());
diff -r 8abc3b3b94c8 go/gogo.cc
--- a/go/gogo.cc	Fri Mar 25 12:21:40 2011 -0700
+++ b/go/gogo.cc	Fri Mar 25 13:38:47 2011 -0700
@@ -1527,7 +1527,7 @@
       && !ctype->is_boolean_type()
       && !ctype->is_string_type())
     {
-      if (!ctype->is_error_type())
+      if (!ctype->is_error())
 	error_at(constant->location(), "invalid constant type");
       constant->set_error();
     }
diff -r 8abc3b3b94c8 go/statements.cc
--- a/go/statements.cc	Fri Mar 25 12:21:40 2011 -0700
+++ b/go/statements.cc	Fri Mar 25 13:38:47 2011 -0700
@@ -517,7 +517,7 @@
       && this->lhs_->map_index_expression() == NULL
       && !this->lhs_->is_sink_expression())
     {
-      if (!this->lhs_->type()->is_error_type())
+      if (!this->lhs_->type()->is_error())
 	this->report_error(_("invalid left hand side of assignment"));
       return;
     }
@@ -535,16 +535,8 @@
       this->set_is_error();
     }
 
-  if (lhs_type->is_error_type()
-      || rhs_type->is_error_type()
-      || lhs_type->is_undefined()
-      || rhs_type->is_undefined())
-    {
-      // Make sure we get the error for an undefined type.
-      lhs_type->base();
-      rhs_type->base();
-      this->set_is_error();
-    }
+  if (lhs_type->is_error() || rhs_type->is_error())
+    this->set_is_error();
 }
 
 // Build a tree for an assignment statement.
@@ -817,9 +809,9 @@
       gcc_assert(prhs != this->rhs_->end());
 
       if ((*plhs)->is_error_expression()
-	  || (*plhs)->type()->is_error_type()
+	  || (*plhs)->type()->is_error()
 	  || (*prhs)->is_error_expression()
-	  || (*prhs)->type()->is_error_type())
+	  || (*prhs)->type()->is_error())
 	continue;
 
       if ((*plhs)->is_sink_expression())
@@ -843,9 +835,9 @@
        ++plhs, ++prhs)
     {
       if ((*plhs)->is_error_expression()
-	  || (*plhs)->type()->is_error_type()
+	  || (*plhs)->type()->is_error()
 	  || (*prhs)->is_error_expression()
-	  || (*prhs)->type()->is_error_type())
+	  || (*prhs)->type()->is_error())
 	continue;
 
       if ((*plhs)->is_sink_expression())
@@ -1363,7 +1355,7 @@
   Type* expr_type = this->expr_->type();
   if (expr_type->interface_type() == NULL)
     {
-      if (!expr_type->is_error_type() && !this->type_->is_error_type())
+      if (!expr_type->is_error() && !this->type_->is_error())
 	this->report_error(_("type assertion only valid for interface types"));
       return Statement::make_error_statement(loc);
     }
@@ -2624,16 +2616,8 @@
 		     i, reason.c_str());
 	  this->set_is_error();
 	}
-      else if (pt->type()->is_error_type()
-	       || (*pe)->type()->is_error_type()
-	       || pt->type()->is_undefined()
-	       || (*pe)->type()->is_undefined())
-	{
-	  // Make sure we get the error for an undefined type.
-	  pt->type()->base();
-	  (*pe)->type()->base();
-	  this->set_is_error();
-	}
+      else if (pt->type()->is_error() || (*pe)->type()->is_error())
+	this->set_is_error();
     }
 
   if (pt != results->end())
@@ -3001,7 +2985,7 @@
 If_statement::do_check_types(Gogo*)
 {
   Type* type = this->cond_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     this->set_is_error();
   else if (!type->is_boolean_type())
     this->report_error(_("expected boolean expression"));
@@ -3023,7 +3007,7 @@
 If_statement::do_get_tree(Translate_context* context)
 {
   gcc_assert(this->cond_->type()->is_boolean_type()
-	     || this->cond_->type()->is_error_type());
+	     || this->cond_->type()->is_error());
   tree cond_tree = this->cond_->get_tree(context);
   tree then_tree = this->then_block_->get_tree(context);
   tree else_tree = (this->else_block_ == NULL
@@ -3554,7 +3538,7 @@
 
   if (this->val_ != NULL
       && (this->val_->is_error_expression()
-	  || this->val_->type()->is_error_type()))
+	  || this->val_->type()->is_error()))
     return Statement::make_error_statement(loc);
 
   if (this->val_ != NULL
@@ -4023,7 +4007,7 @@
 Send_statement::do_check_types(Gogo*)
 {
   Type* type = this->channel_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     {
       this->set_is_error();
       return;
@@ -4739,7 +4723,7 @@
       index_type = range_type->channel_type()->element_type();
       if (this->value_var_ != NULL)
 	{
-	  if (!this->value_var_->type()->is_error_type())
+	  if (!this->value_var_->type()->is_error())
 	    this->report_error(_("too many variables for range clause "
 				 "with channel"));
 	  return Statement::make_error_statement(this->location());
diff -r 8abc3b3b94c8 go/types.h
--- a/go/types.h	Fri Mar 25 12:21:40 2011 -0700
+++ b/go/types.h	Fri Mar 25 13:38:47 2011 -0700
@@ -587,11 +587,19 @@
   has_pointer() const
   { return this->do_has_pointer(); }
 
-  // Return true if this is an error type.  An error type indicates a
-  // parsing error.
+  // Return true if this is the error type.  This returns false for a
+  // type which is not defined, as it is called by the parser before
+  // all types are defined.
   bool
   is_error_type() const;
 
+  // Return true if this is the error type or if the type is
+  // undefined.  If the type is undefined, this will give an error.
+  // This should only be called after parsing is complete.
+  bool
+  is_error() const
+  { return this->base()->is_error_type(); }
+
   // Return true if this is a void type.
   bool
   is_void_type() const

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]