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]

C++ PATCH: PR 25439


This patch fixes PR c++/25439, an accepts-invalid regression.  We had
a nice comment in cp-tree.h saying that the unqualified name in an ID
declarator could only be an IDENTIFIER_NODE, BIT_NOT_EXPR, or
TEMPLATE_ID_EXPR -- but then we were creating declarators with
TYPE_DECL and BASELINK nodes.  Fixed by making the parser pre-resolve
such things, when they are returned from name lookup, so that the rest
of the compiler only sees the document nodes.  Added assertions to
make_id_declarator to make sure we play by our own rules.

Tested on x86_64-unknown-linux-gnu; applied to 4.0 and 4.1 branches.
Will apply to mainline when testing completes.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-12-26  Mark Mitchell  <mark@codesourcery.com>

	PR c++/25439
	* decl.c (grokdeclarator): Remove dead code.
	* ptree.c (cxx_print_xnode): Handle BASELINK.
	* parser.c (make_id_declarator): Add sfk parameter.  
	(cp_parser_direct_declarator): Do not pass TYPE_DECLs to
	make_id_declarator.
	(cp_parser_declarator_id): Simplify BASELINKs here.
	(cp_parser_member_declaration): Adjust calls to
	make_id_declarator.

2005-12-26  Mark Mitchell  <mark@codesourcery.com>

	PR c++/25439
	* g++.dg/parse/crash17.C: Adjust error markers.
	* g++.dg/template/error20.C: New test.

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 109035)
+++ gcc/cp/decl.c	(working copy)
@@ -6724,10 +6724,6 @@ grokdeclarator (const cp_declarator *dec
 		else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
 		  in_namespace = qualifying_scope;
 	      }
-	    if (TREE_CODE (decl) == BASELINK)
-	      decl = BASELINK_FUNCTIONS (decl);
-	    if (decl == error_mark_node)
-	      return error_mark_node;
 	    switch (TREE_CODE (decl))
 	      {
 	      case BIT_NOT_EXPR:
@@ -6791,11 +6787,6 @@ grokdeclarator (const cp_declarator *dec
 		  }
 		break;
 
-	      case TYPE_DECL:
-		dname = constructor_name (TREE_TYPE (decl));
-		name = IDENTIFIER_POINTER (dname);
-		break;
-
 	      default:
 		gcc_unreachable ();
 	      }
@@ -7261,8 +7252,6 @@ grokdeclarator (const cp_declarator *dec
   else
     {
       unqualified_id = id_declarator->u.id.unqualified_name;
-      if (TREE_CODE (unqualified_id) == BASELINK)
-	unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
       switch (TREE_CODE (unqualified_id))
 	{
 	case BIT_NOT_EXPR:
@@ -7270,11 +7259,6 @@ grokdeclarator (const cp_declarator *dec
 	    = constructor_name (TREE_OPERAND (unqualified_id, 0));
 	  break;
 
-	case TYPE_DECL:
-	  unqualified_id
-	    = constructor_name (TREE_TYPE (unqualified_id));
-	  break;
-
 	case IDENTIFIER_NODE:
 	case TEMPLATE_ID_EXPR:
 	  break;
Index: gcc/cp/ptree.c
===================================================================
--- gcc/cp/ptree.c	(revision 109035)
+++ gcc/cp/ptree.c	(working copy)
@@ -168,6 +168,12 @@ cxx_print_xnode (FILE *file, tree node, 
 {
   switch (TREE_CODE (node))
     {
+    case BASELINK:
+      print_node (file, "functions", BASELINK_FUNCTIONS (node), indent + 4);
+      print_node (file, "binfo", BASELINK_BINFO (node), indent + 4);
+      print_node (file, "access_binfo", BASELINK_ACCESS_BINFO (node), 
+		  indent + 4);
+      break;
     case OVERLOAD:
       print_node (file, "function", OVL_FUNCTION (node), indent+4);
       print_node (file, "chain", TREE_CHAIN (node), indent+4);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 109035)
+++ gcc/cp/parser.c	(working copy)
@@ -833,12 +833,15 @@ make_declarator (cp_declarator_kind kind
   return declarator;
 }
 
-/* Make a declarator for a generalized identifier.  If non-NULL, the
-   identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is
-   just UNQUALIFIED_NAME.  */
+/* Make a declarator for a generalized identifier.  If
+   QUALIFYING_SCOPE is non-NULL, the identifier is
+   QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is just
+   UNQUALIFIED_NAME.  SFK indicates the kind of special function this
+   is, if any.   */
 
 static cp_declarator *
-make_id_declarator (tree qualifying_scope, tree unqualified_name)
+make_id_declarator (tree qualifying_scope, tree unqualified_name,
+		    special_function_kind sfk)
 {
   cp_declarator *declarator;
 
@@ -855,10 +858,14 @@ make_id_declarator (tree qualifying_scop
   if (qualifying_scope && TYPE_P (qualifying_scope))
     qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope);
 
+  gcc_assert (TREE_CODE (unqualified_name) == IDENTIFIER_NODE
+	      || TREE_CODE (unqualified_name) == BIT_NOT_EXPR
+	      || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR);
+
   declarator = make_declarator (cdk_id);
   declarator->u.id.qualifying_scope = qualifying_scope;
   declarator->u.id.unqualified_name = unqualified_name;
-  declarator->u.id.sfk = sfk_none;
+  declarator->u.id.sfk = sfk;
 
   return declarator;
 }
@@ -11350,6 +11357,7 @@ cp_parser_direct_declarator (cp_parser* 
 	{
 	  tree qualifying_scope;
 	  tree unqualified_name;
+	  special_function_kind sfk;
 
 	  /* Parse a declarator-id */
 	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
@@ -11407,9 +11415,7 @@ cp_parser_direct_declarator (cp_parser* 
 	      qualifying_scope = type;
 	    }
 
-	  declarator = make_id_declarator (qualifying_scope,
-					   unqualified_name);
-	  declarator->id_loc = token->location;
+	  sfk = sfk_none;
 	  if (unqualified_name)
 	    {
 	      tree class_type;
@@ -11420,28 +11426,9 @@ cp_parser_direct_declarator (cp_parser* 
 	      else
 		class_type = current_class_type;
 
-	      if (class_type)
+	      if (TREE_CODE (unqualified_name) == TYPE_DECL)
 		{
-		  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
-		    declarator->u.id.sfk = sfk_destructor;
-		  else if (IDENTIFIER_TYPENAME_P (unqualified_name))
-		    declarator->u.id.sfk = sfk_conversion;
-		  else if (/* There's no way to declare a constructor
-			      for an anonymous type, even if the type
-			      got a name for linkage purposes.  */
-			   !TYPE_WAS_ANONYMOUS (class_type)
-			   && (constructor_name_p (unqualified_name,
-						   class_type)
-			       || (TREE_CODE (unqualified_name) == TYPE_DECL
-				   && (same_type_p
-				       (TREE_TYPE (unqualified_name),
-					class_type)))))
-		    declarator->u.id.sfk = sfk_constructor;
-
-		  if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
-		    *ctor_dtor_or_conv_p = -1;
-		  if (qualifying_scope
-		      && TREE_CODE (unqualified_name) == TYPE_DECL
+		  if (qualifying_scope 
 		      && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
 		    {
 		      error ("invalid use of constructor as a template");
@@ -11450,9 +11437,50 @@ cp_parser_direct_declarator (cp_parser* 
 			      class_type,
 			      DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
 			      class_type, class_type);
+		      declarator = cp_error_declarator;
+		      break;
+		    }
+		  else if (class_type
+			   && same_type_p (TREE_TYPE (unqualified_name),
+					   class_type))
+		    unqualified_name = constructor_name (class_type);
+		  else
+		    {
+		      /* We do not attempt to print the declarator
+			 here because we do not have enough
+			 information about its original syntactic
+			 form.  */
+		      error ("invalid declarator");
+		      declarator = cp_error_declarator;
+		      break;
+		    }
+		}
+
+	      if (class_type)
+		{
+		  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+		    sfk = sfk_destructor;
+		  else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+		    sfk = sfk_conversion;
+		  else if (/* There's no way to declare a constructor
+			      for an anonymous type, even if the type
+			      got a name for linkage purposes.  */
+			   !TYPE_WAS_ANONYMOUS (class_type)
+			   && constructor_name_p (unqualified_name,
+						  class_type))
+		    {
+		      unqualified_name = constructor_name (class_type);
+		      sfk = sfk_constructor;
 		    }
+
+		  if (ctor_dtor_or_conv_p && sfk != sfk_none)
+		    *ctor_dtor_or_conv_p = -1;
 		}
 	    }
+	  declarator = make_id_declarator (qualifying_scope, 
+					   unqualified_name,
+					   sfk);
+	  declarator->id_loc = token->location;
 
 	handle_declarator:;
 	  scope = get_scope_of_declarator (declarator);
@@ -11662,6 +11690,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parse
 static tree
 cp_parser_declarator_id (cp_parser* parser)
 {
+  tree id;
   /* The expression must be an id-expression.  Assume that qualified
      names are the names of types so that:
 
@@ -11676,11 +11705,14 @@ cp_parser_declarator_id (cp_parser* pars
        int S<T>::R<T>::i = 3;
 
      will work, too.  */
-  return cp_parser_id_expression (parser,
-				  /*template_keyword_p=*/false,
-				  /*check_dependency_p=*/false,
-				  /*template_p=*/NULL,
-				  /*declarator_p=*/true);
+  id = cp_parser_id_expression (parser,
+				/*template_keyword_p=*/false,
+				/*check_dependency_p=*/false,
+				/*template_p=*/NULL,
+				/*declarator_p=*/true);
+  if (BASELINK_P (id))
+    id = BASELINK_FUNCTIONS (id);
+  return id;
 }
 
 /* Parse a type-id.
@@ -13459,7 +13491,8 @@ cp_parser_member_declaration (cp_parser*
 	      /* Create the bitfield declaration.  */
 	      decl = grokbitfield (identifier
 				   ? make_id_declarator (NULL_TREE,
-							 identifier)
+							 identifier,
+							 sfk_none)
 				   : NULL,
 				   &decl_specifiers,
 				   width);
@@ -17095,7 +17128,8 @@ cp_parser_objc_class_ivars (cp_parser* p
 	    {
 	      /* Get the name of the bitfield.  */
 	      declarator = make_id_declarator (NULL_TREE,
-					       cp_parser_identifier (parser));
+					       cp_parser_identifier (parser),
+					       sfk_none);
 
 	     eat_colon:
 	      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
Index: gcc/testsuite/g++.dg/parse/crash17.C
===================================================================
--- gcc/testsuite/g++.dg/parse/crash17.C	(revision 109035)
+++ gcc/testsuite/g++.dg/parse/crash17.C	(working copy)
@@ -5,5 +5,5 @@ template <typename> class allocator; 
 template<typename T> class vector { 
   // With the dg-error on the next line, we are really just trying to
   // check that the message is not an ICE message.
-  typedef typename allocator<T> allocator_type; // { dg-error "expected|forbids" }
+  typedef typename allocator<T> allocator_type; // { dg-error "expected|invalid" }
 }; 
Index: gcc/testsuite/g++.dg/template/error20.C
===================================================================
--- gcc/testsuite/g++.dg/template/error20.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/error20.C	(revision 0)
@@ -0,0 +1,4 @@
+// PR c++/25439
+
+template<int> struct A;
+template<> int A<0>; // { dg-error "invalid" }


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