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 for c++/53563 (ice-on-invalid with s<void>::s<void>)


Here, we were parsing s<void>::s<void> wrong. When we've seen a class-key, an injected-class-name must be considered to name the class, not the constructor, because the class-key limits lookup to finding type names. Fixing that corrects the error message for this testcase, and avoids the ICE.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit f087a69f6320f9114101eb9117fb8e1c6ee44773
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 27 14:33:06 2012 -0400

    	PR c++/53563
    	* parser.c (cp_parser_template_id): Add tag_type parm.
    	(cp_parser_template_name): Likewise.
    	(cp_parser_id_expression, cp_parser_unqualified_id): Adjust.
    	(cp_parser_pseudo_destructor_name, cp_parser_type_name): Adjust.
    	(cp_parser_simple_type_specifier, cp_parser_class_name): Adjust.
    	(cp_parser_elaborated_type_specifier, cp_parser_class_head): Adjust.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 46f1401..7012caa 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2062,9 +2062,9 @@ static tree cp_parser_template_parameter
 static tree cp_parser_type_parameter
   (cp_parser *, bool *);
 static tree cp_parser_template_id
-  (cp_parser *, bool, bool, bool);
+  (cp_parser *, bool, bool, enum tag_types, bool);
 static tree cp_parser_template_name
-  (cp_parser *, bool, bool, bool, bool *);
+  (cp_parser *, bool, bool, bool, enum tag_types, bool *);
 static tree cp_parser_template_argument_list
   (cp_parser *);
 static tree cp_parser_template_argument
@@ -4466,6 +4466,7 @@ cp_parser_id_expression (cp_parser *parser,
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
+				  none_type,
 				  declarator_p);
       /* If that worked, we're done.  */
       if (cp_parser_parse_definitely (parser))
@@ -4543,6 +4544,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 	/* Try a template-id.  */
 	id = cp_parser_template_id (parser, template_keyword_p,
 				    check_dependency_p,
+				    none_type,
 				    declarator_p);
 	/* If it worked, we're done.  */
 	if (cp_parser_parse_definitely (parser))
@@ -4554,6 +4556,7 @@ cp_parser_unqualified_id (cp_parser* parser,
     case CPP_TEMPLATE_ID:
       return cp_parser_template_id (parser, template_keyword_p,
 				    check_dependency_p,
+				    none_type,
 				    declarator_p);
 
     case CPP_COMPL:
@@ -4769,6 +4772,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 	  /* Try a template-id.  */
 	  id = cp_parser_template_id (parser, template_keyword_p,
 				      /*check_dependency_p=*/true,
+				      none_type,
 				      declarator_p);
 	  /* If that worked, we're done.  */
 	  if (cp_parser_parse_definitely (parser))
@@ -6280,6 +6284,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
       cp_parser_template_id (parser,
 			     /*template_keyword_p=*/true,
 			     /*check_dependency_p=*/false,
+			     class_type,
 			     /*is_declaration=*/true);
       /* Look for the `::' token.  */
       cp_parser_require (parser, CPP_SCOPE, RT_SCOPE);
@@ -12376,6 +12381,7 @@ static tree
 cp_parser_template_id (cp_parser *parser,
 		       bool template_keyword_p,
 		       bool check_dependency_p,
+		       enum tag_types tag_type,
 		       bool is_declaration)
 {
   int i;
@@ -12432,6 +12438,7 @@ cp_parser_template_id (cp_parser *parser,
   templ = cp_parser_template_name (parser, template_keyword_p,
 				   check_dependency_p,
 				   is_declaration,
+				   tag_type,
 				   &is_identifier);
   if (templ == error_mark_node || is_identifier)
     {
@@ -12604,6 +12611,7 @@ cp_parser_template_name (cp_parser* parser,
 			 bool template_keyword_p,
 			 bool check_dependency_p,
 			 bool is_declaration,
+			 enum tag_types tag_type,
 			 bool *is_identifier)
 {
   tree identifier;
@@ -12710,7 +12718,7 @@ cp_parser_template_name (cp_parser* parser,
 
   /* Look up the name.  */
   decl = cp_parser_lookup_name (parser, identifier,
-				none_type,
+				tag_type,
 				/*is_template=*/true,
 				/*is_namespace=*/false,
 				check_dependency_p,
@@ -13699,6 +13707,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	  type = cp_parser_template_id (parser,
 					/*template_keyword_p=*/true,
 					/*check_dependency_p=*/true,
+					none_type,
 					/*is_declaration=*/false);
 	  /* If the template-id did not name a type, we are out of
 	     luck.  */
@@ -13811,6 +13820,7 @@ cp_parser_type_name (cp_parser* parser)
       type_decl = cp_parser_template_id (parser,
 					 /*template_keyword_p=*/false,
 					 /*check_dependency_p=*/false,
+					 none_type,
 					 /*is_declaration=*/false);
       /* Note that this must be an instantiation of an alias template
 	 because [temp.names]/6 says:
@@ -14035,6 +14045,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
 				    /*check_dependency_p=*/true,
+				    tag_type,
 				    is_declaration);
       /* If we didn't find a template-id, look for an ordinary
 	 identifier.  */
@@ -17865,6 +17876,7 @@ cp_parser_class_name (cp_parser *parser,
       /* Try a template-id.  */
       decl = cp_parser_template_id (parser, template_keyword_p,
 				    check_dependency_p,
+				    tag_type,
 				    is_declaration);
       if (decl == error_mark_node)
 	return error_mark_node;
@@ -18317,7 +18329,7 @@ cp_parser_class_head (cp_parser* parser,
     = cp_parser_nested_name_specifier_opt (parser,
 					   /*typename_keyword_p=*/false,
 					   /*check_dependency_p=*/false,
-					   /*type_p=*/false,
+					   /*type_p=*/true,
 					   /*is_declaration=*/false);
   /* If there was a nested-name-specifier, then there *must* be an
      identifier.  */
@@ -18392,6 +18404,7 @@ cp_parser_class_head (cp_parser* parser,
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
+				  class_key,
 				  /*is_declaration=*/true);
       /* If that didn't work, it could still be an identifier.  */
       if (!cp_parser_parse_definitely (parser))
diff --git a/gcc/testsuite/g++.dg/parse/template27.C b/gcc/testsuite/g++.dg/parse/template27.C
new file mode 100644
index 0000000..8eee471
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template27.C
@@ -0,0 +1,12 @@
+// PR c++/53563
+
+template<class T>
+struct s
+{
+ template<class U>
+ s(){}
+};
+
+int main() {
+ struct s<void>::s<int> a;	// { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/template/crash74.C b/gcc/testsuite/g++.dg/template/crash74.C
index 9f2e415..d236947 100644
--- a/gcc/testsuite/g++.dg/template/crash74.C
+++ b/gcc/testsuite/g++.dg/template/crash74.C
@@ -2,5 +2,5 @@
 // { dg-do compile }
 // { dg-options "" }
 
-template<typename F> void foo () { }
-template<typename F> struct foo<F> { };	// { dg-error "redeclared as" }
+template<typename F> void foo () { } // { dg-prune-output "previous" }
+template<typename F> struct foo<F> { };	// { dg-error "template" }
commit 62fa7b236eba79613821976219d952d1898f02df
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 27 14:43:06 2012 -0400

    	* parser.c (cp_parser_check_for_invalid_template_id): tag_type parm.
    	(cp_parser_simple_type_specifier, cp_parser_class_head): Adjust.
    	(cp_parser_elaborated_type_specifier): Adjust.
    	* decl.c (duplicate_decls): Return error_mark_node on template
    	mismatch.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1346f92..ab56019 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1463,6 +1463,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 	    {
 	      error ("declaration of template %q#D", newdecl);
 	      error ("conflicts with previous declaration %q+#D", olddecl);
+	      return error_mark_node;
 	    }
 	  else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
 		   && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7012caa..027a7b9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2278,7 +2278,7 @@ static bool cp_parser_check_type_definition
 static void cp_parser_check_for_definition_in_return_type
   (cp_declarator *, tree, location_t type_location);
 static void cp_parser_check_for_invalid_template_id
-  (cp_parser *, tree, location_t location);
+  (cp_parser *, tree, enum tag_types, location_t location);
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, non_integral_constant);
 static void cp_parser_diagnose_invalid_type_name
@@ -2551,7 +2551,9 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
 
 static void
 cp_parser_check_for_invalid_template_id (cp_parser* parser,
-					 tree type, location_t location)
+					 tree type,
+					 enum tag_types tag_type,
+					 location_t location)
 {
   cp_token_position start = 0;
 
@@ -2560,7 +2562,12 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
       if (TYPE_P (type))
 	error_at (location, "%qT is not a template", type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-	error_at (location, "%qE is not a template", type);
+	{
+	  if (tag_type != none_type)
+	    error_at (location, "%qE is not a class template", type);
+	  else
+	    error_at (location, "%qE is not a template", type);
+	}
       else
 	error_at (location, "invalid template-id");
       /* Remember the location of the invalid "<".  */
@@ -13668,7 +13675,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       /* There is no valid C++ program where a non-template type is
 	 followed by a "<".  That usually indicates that the user thought
 	 that the type was a template.  */
-      cp_parser_check_for_invalid_template_id (parser, type, token->location);
+      cp_parser_check_for_invalid_template_id (parser, type, none_type,
+					       token->location);
 
       return TYPE_NAME (type);
     }
@@ -13770,6 +13778,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	 followed by a "<".  That usually indicates that the user
 	 thought that the type was a template.  */
       cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
+					       none_type,
 					       token->location);
     }
 
@@ -14273,7 +14282,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   /* A "<" cannot follow an elaborated type specifier.  If that
      happens, the user was probably trying to form a template-id.  */
-  cp_parser_check_for_invalid_template_id (parser, type, token->location);
+  cp_parser_check_for_invalid_template_id (parser, type, tag_type,
+					   token->location);
 
   return type;
 }
@@ -18429,6 +18439,7 @@ cp_parser_class_head (cp_parser* parser,
   if (id)
     {
       cp_parser_check_for_invalid_template_id (parser, id,
+					       class_key,
                                                type_start_token->location);
     }
   virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C
index 0d8871d..4d5a412 100644
--- a/gcc/testsuite/g++.dg/cpp0x/override2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/override2.C
@@ -18,7 +18,7 @@ template <class T> struct B4 final {};
 
 template <class T> struct B5 final {};
 
-struct undeclared<int> final { }; // { dg-error "not a template" }
+struct undeclared<int> final { }; // { dg-error "not a class template" }
 
 struct D5 : B3<D5> {};
 
diff --git a/gcc/testsuite/g++.dg/parse/crash28.C b/gcc/testsuite/g++.dg/parse/crash28.C
index 67d78d6..68a9759 100644
--- a/gcc/testsuite/g++.dg/parse/crash28.C
+++ b/gcc/testsuite/g++.dg/parse/crash28.C
@@ -5,10 +5,10 @@
 // Origin:Andrew Pinski <pinskia@gcc.gnu.org>
 //        Volker Reichelt <reichelt@gcc.gnu.org>
 
-template <class _Tp> class insert_iterator<slist<_Tp> > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" }
+template <class _Tp> class insert_iterator<slist<_Tp> > {}; // { dg-error "not a class template|not declared in this scope|expected unqualified-id|extra" }
 template <class _Value> class insert_iterator<int > { // { dg-error "template" }
   hash_set<_Value>;
 };
 
-template<int> struct A<X<> > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" }
+template<int> struct A<X<> > {}; // { dg-error "not a class template|not declared in this scope|expected unqualified-id|extra" }
 struct A {};
diff --git a/gcc/testsuite/g++.dg/template/error5.C b/gcc/testsuite/g++.dg/template/error5.C
index 0c79350..72d3c29 100644
--- a/gcc/testsuite/g++.dg/template/error5.C
+++ b/gcc/testsuite/g++.dg/template/error5.C
@@ -1,6 +1,6 @@
 template <typename T>
-struct X<T*> { // { dg-error "not a template" }
+struct X<T*> { // { dg-error "not a class template" }
    typedef int Y;
 };
 
-extern struct Z<int> s; // { dg-error "not a template" }
+extern struct Z<int> s; // { dg-error "not a class template" }

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