[patch] Fix PR c++/28552: ICE on invalid conversion operator

Volker Reichelt reichelt@igpm.rwth-aachen.de
Fri Aug 25 23:22:00 GMT 2006


Once again the C++ frontend stumbles over an invalid operator:

  struct A
  {
    operator int&(int);
  };

  A a;
  int& i = a;

bug.cc:3: error: 'A::operator int&(int)' must take 'void'
bug.cc:7: internal compiler error: Segmentation fault
Please submit a full bug report, [etc.]

An error is issued about the invalid declaration, but the decl is
not thrown away and triggers an ICE later. We already had a similar
issue in PR 27547, which was fixed at the point where the decl was
used, see

http://gcc.gnu.org/ml/gcc-patches/2006-05/msg00445.html

But as this seems to be a recurring problem, the following patch
tackles the root of the problem, i.e. it discards the invalid operator.
This was suggested later in the above thread an generally agreed upon:

http://gcc.gnu.org/ml/gcc-patches/2006-05/msg00611.html

The patch changes grok_op_properties to return an error status
(true, if the operator is okay, otherwise false). This is the largest
part of the patch, but mostly mechanical.
The two callers of grok_op_properties, namely grokfndecl and
tsubst_decl, check the return value and discard the declaration
if it is malformed.
In addition the patch reverts the change for PR 27547 as it is not
needed anymore.

Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline, 4.1 branch, and 4.0 branch?

Regards,
Volker

:ADDPATCH C++:


2006-08-25  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28852
	* cp-tree.h (grok_op_properties): Return bool instead of void.
	* decl.c (grokfndecl): Discard invalid operator declarations.
	(copy_fn_p): Revert change for PR 27547.
	(grok_op_properties): Return error status (true on success).
	* pt.c (tsubst_decl): Discard invalid operator declarations.

===================================================================
--- gcc/gcc/cp/cp-tree.h	2006-08-18 21:38:25 +0200
+++ gcc/gcc/cp/cp-tree.h	2006-08-18 21:30:40 +0200
@@ -3899,7 +3899,7 @@ extern int copy_fn_p				(tree);
 extern tree get_scope_of_declarator		(const cp_declarator *);
 extern void grok_special_member_properties	(tree);
 extern int grok_ctor_properties			(tree, tree);
-extern void grok_op_properties			(tree, bool);
+extern bool grok_op_properties			(tree, bool);
 extern tree xref_tag				(enum tag_types, tree, tag_scope, bool);
 extern tree xref_tag_from_type			(tree, tree, tag_scope);
 extern void xref_basetypes			(tree, tree);
===================================================================
--- gcc/gcc/cp/decl.c	2006-08-04 20:08:14 +0200
+++ gcc/gcc/cp/decl.c	2006-08-18 23:35:23 +0200
@@ -6128,8 +6128,9 @@ grokfndecl (tree ctype,
       quals = TYPE_UNQUALIFIED;
     }
 
-  if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
-    grok_op_properties (decl, /*complain=*/true);
+  if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
+      && !grok_op_properties (decl, /*complain=*/true))
+    return NULL_TREE;
 
   if (ctype && decl_function_context (decl))
     DECL_NO_STATIC_CHAIN (decl) = 1;
@@ -8892,9 +8893,7 @@ copy_fn_p (tree d)
   tree arg_type;
   int result = 1;
 
-  if (!DECL_FUNCTION_MEMBER_P (d))
-    /* Non-members are invalid.  We complained, but kept the declaration.  */
-    return 0;
+  gcc_assert (DECL_FUNCTION_MEMBER_P (d));
 
   if (TREE_CODE (d) == TEMPLATE_DECL
       || (DECL_TEMPLATE_INFO (d)
@@ -9047,7 +9046,7 @@ unary_op_p (enum tree_code code)
 /* DECL is a declaration for an overloaded operator.  If COMPLAIN is true,
    errors are issued for invalid declarations.  */
 
-void
+bool
 grok_op_properties (tree decl, bool complain)
 {
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
@@ -9133,9 +9132,15 @@ grok_op_properties (tree decl, bool comp
       if (DECL_NAMESPACE_SCOPE_P (decl))
 	{
 	  if (CP_DECL_CONTEXT (decl) != global_namespace)
-	    error ("%qD may not be declared within a namespace", decl);
+	    {
+	      error ("%qD may not be declared within a namespace", decl);
+	      return false;
+	    }
 	  else if (!TREE_PUBLIC (decl))
-	    error ("%qD may not be declared as static", decl);
+	    {
+	      error ("%qD may not be declared as static", decl);
+	      return false;
+	    }
 	}
     }
 
@@ -9157,7 +9162,7 @@ grok_op_properties (tree decl, bool comp
 	      || operator_code == NOP_EXPR)
 	    {
 	      error ("%qD must be a nonstatic member function", decl);
-	      return;
+	      return false;
 	    }
 	  else
 	    {
@@ -9167,14 +9172,14 @@ grok_op_properties (tree decl, bool comp
 		{
 		  error ("%qD must be either a non-static member "
 			 "function or a non-member function", decl);
-		  return;
+		  return false;
 		}
 
 	      for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
 		{
 		  tree arg = non_reference (TREE_VALUE (p));
 		  if (arg == error_mark_node)
-		    return;
+		    return false;
 
 		  /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
 		     because these checks are performed even on
@@ -9185,12 +9190,10 @@ grok_op_properties (tree decl, bool comp
 
 	      if (!p || p == void_list_node)
 		{
-		  if (!complain)
-		    return;
-
-		  error ("%qD must have an argument of class or "
-			 "enumerated type",
-			 decl);
+		  if (complain)
+		    error ("%qD must have an argument of class or "
+			   "enumerated type", decl);
+		  return false;
 		}
 	    }
 	}
@@ -9198,7 +9201,7 @@ grok_op_properties (tree decl, bool comp
       /* There are no restrictions on the arguments to an overloaded
 	 "operator ()".  */
       if (operator_code == CALL_EXPR)
-	return;
+	return true;
 
       /* Warn about conversion operators that will never be used.  */
       if (IDENTIFIER_TYPENAME_P (name)
@@ -9238,9 +9241,13 @@ grok_op_properties (tree decl, bool comp
 	{
 	  /* 13.4.0.3 */
 	  error ("ISO C++ prohibits overloading operator ?:");
+	  return false;
 	}
       else if (ellipsis_p)
-	error ("%qD must not have variable number of arguments", decl);
+	{
+	  error ("%qD must not have variable number of arguments", decl);
+	  return false;
+	}
       else if (ambi_op_p (operator_code))
 	{
 	  if (arity == 1)
@@ -9290,11 +9297,11 @@ grok_op_properties (tree decl, bool comp
 		{
 		  if (methodp)
 		    error ("postfix %qD must take %<int%> as its argument",
-			      decl);
+			   decl);
 		  else
-		    error
-		      ("postfix %qD must take %<int%> as its second argument",
-		       decl);
+		    error ("postfix %qD must take %<int%> as its second "
+			   "argument", decl);
+		  return false;
 		}
 	    }
 	  else
@@ -9303,6 +9310,7 @@ grok_op_properties (tree decl, bool comp
 		error ("%qD must take either zero or one argument", decl);
 	      else
 		error ("%qD must take either one or two arguments", decl);
+	      return false;
 	    }
 
 	  /* More Effective C++ rule 6.  */
@@ -9341,6 +9349,7 @@ grok_op_properties (tree decl, bool comp
 		error ("%qD must take %<void%>", decl);
 	      else
 		error ("%qD must take exactly one argument", decl);
+	      return false;
 	    }
 	}
       else /* if (binary_op_p (operator_code)) */
@@ -9351,6 +9360,7 @@ grok_op_properties (tree decl, bool comp
 		error ("%qD must take exactly one argument", decl);
 	      else
 		error ("%qD must take exactly two arguments", decl);
+	      return false;
 	    }
 
 	  /* More Effective C++ rule 7.  */
@@ -9387,11 +9397,13 @@ grok_op_properties (tree decl, bool comp
 		  pedwarn ("%qD cannot have default arguments", decl);
 	      }
 	    else
-	      error ("%qD cannot have default arguments", decl);
+	      {
+		error ("%qD cannot have default arguments", decl);
+		return false;
+	      }
 	  }
-
     }
-
+  return true;
 }
 
 /* Return a string giving the keyword associate with CODE.  */
===================================================================
--- gcc/gcc/cp/pt.c	2006-08-18 10:31:43 +0200
+++ gcc/gcc/cp/pt.c	2006-08-18 21:44:51 +0200
@@ -6653,8 +6653,9 @@ tsubst_decl (tree t, tree args, tsubst_f
 	    if (PRIMARY_TEMPLATE_P (gen_tmpl))
 	      clone_function_decl (r, /*update_method_vec_p=*/0);
 	  }
-	else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
-	  grok_op_properties (r, (complain & tf_error) != 0);
+	else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
+		 && !grok_op_properties (r, (complain & tf_error) != 0))
+	  return error_mark_node;
 
 	if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
 	  SET_DECL_FRIEND_CONTEXT (r,
===================================================================

2006-08-25  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28852
	* g++.dg/other/operator1.C: Add error-marker.
	* g++.dg/other/operator2.C: New test.

===================================================================
--- gcc/gcc/testsuite/g++.dg/other/operator1.C	2006-05-11 16:41:03 +0200
+++ gcc/gcc/testsuite/g++.dg/other/operator1.C	2006-08-18 22:06:48 +0200
@@ -5,5 +5,5 @@ int operator=(int);  // { dg-error "memb
 
 void foo()
 {
-  operator=(0);
+  operator=(0);  // { dg-error "not defined" }
 }
===================================================================
--- gcc/gcc/testsuite/g++.dg/other/operator2.C	2003-09-23 19:59:22 +0200
+++ gcc/gcc/testsuite/g++.dg/other/operator2.C	2006-08-18 21:57:43 +0200
@@ -0,0 +1,10 @@
+// PR c++/28852
+// { do-do compile }
+
+struct A
+{
+  operator int&(int);  // { dg-error "void" }
+};
+
+A a;
+int& i = a;  // { dg-error "initialization" }
===================================================================




More information about the Gcc-patches mailing list