public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/15946 (improved diagnostics for missing 'typename')
@ 2009-11-06 22:08 Jason Merrill
  2009-11-08  4:06 ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2009-11-06 22:08 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 387 bytes --]

The core changes are:

1) make cp_parser_diagnose_invalid_type_name handle A<T>::type in 
situations where we know we're looking at a declaration, and
2) make cp_parser_expression_statement suggest typename if we end up 
with a SCOPE_REF followed by a parse error.

The other changes are supporting, to make the error messages look better.

Tested x86_64-pc-linux-gnu, applied to trunk.

[-- Attachment #2: 15946.patch --]
[-- Type: text/x-patch, Size: 7011 bytes --]

commit fdc850e4101c456e9444da036b6667f3984c7591
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Nov 6 14:09:38 2009 -0500

    	PR c++/15946
    	* parser.c (cp_parser_check_template_parameters): Don't talk about
    	specialization at function scope.
    	(cp_parser_diagnose_invalid_type_name): Handle dependent scope.
    	(cp_parser_parse_and_diagnose_invalid_type_name): Likewise.
    	(cp_parser_expression_statement): Suggest typename.
    	* error.c (dump_decl) [SCOPE_REF]: Print the type here.
    	(dump_expr) [SCOPE_REF]: Call it.
    	(dump_type) [UNBOUND_CLASS_TEMPLATE]: Check TFF_UNQUALIFIED_NAME.
    	* cxx-pretty-print.c (pp_cxx_unqualified_id): Print class template
    	args.

diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 1d7f9cf..4851af9 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -200,6 +200,12 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
     case TYPENAME_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
       pp_cxx_unqualified_id (pp, TYPE_NAME (t));
+      if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t))
+	{
+	  pp_cxx_begin_template_argument_list (pp);
+	  pp_cxx_template_argument_list (pp, CLASSTYPE_TI_ARGS (t));
+	  pp_cxx_end_template_argument_list (pp);
+	}
       break;
 
     case BIT_NOT_EXPR:
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ce5660f..f423207 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -466,8 +466,11 @@ dump_type (tree t, int flags)
       break;
 
     case UNBOUND_CLASS_TEMPLATE:
-      dump_type (TYPE_CONTEXT (t), flags);
-      pp_cxx_colon_colon (cxx_pp);
+      if (! (flags & TFF_UNQUALIFIED_NAME))
+	{
+	  dump_type (TYPE_CONTEXT (t), flags);
+	  pp_cxx_colon_colon (cxx_pp);
+	}
       pp_cxx_ws_string (cxx_pp, "template");
       dump_type (DECL_NAME (TYPE_NAME (t)), flags);
       break;
@@ -947,7 +950,9 @@ dump_decl (tree t, int flags)
       break;
 
     case SCOPE_REF:
-      pp_expression (cxx_pp, t);
+      dump_type (TREE_OPERAND (t, 0), flags);
+      pp_string (cxx_pp, "::");
+      dump_decl (TREE_OPERAND (t, 1), flags|TFF_UNQUALIFIED_NAME);
       break;
 
     case ARRAY_REF:
@@ -2219,6 +2224,9 @@ dump_expr (tree t, int flags)
       break;
 
     case SCOPE_REF:
+      dump_decl (t, flags);
+      break;
+
     case EXPR_PACK_EXPANSION:
     case TYPEID_EXPR:
     case MEMBER_REF:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 28fcabc..83e450d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2400,6 +2400,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
 	error_at (location, "%qE in namespace %qE does not name a type",
 		  id, parser->scope);
+      else if (TYPE_P (parser->scope)
+	       && dependent_scope_p (parser->scope))
+	error_at (location, "need %<typename%> before %<%T::%E%> to name "
+		  "a type in dependent scope %qT",
+		  parser->scope, id, parser->scope);
       else if (TYPE_P (parser->scope))
 	error_at (location, "%qE in class %qT does not name a type",
 		  id, parser->scope);
@@ -2433,11 +2438,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 				/*declarator_p=*/true,
 				/*optional_p=*/false);
   /* After the id-expression, there should be a plain identifier,
-     otherwise this is not a simple variable declaration. Also, if
-     the scope is dependent, we cannot do much.  */
+     otherwise this is not a simple variable declaration.  */
   if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
-      || (parser->scope && TYPE_P (parser->scope)
-	  && dependent_type_p (parser->scope))
       || TREE_CODE (id) == TYPE_DECL)
     {
       cp_parser_abort_tentative_parse (parser);
@@ -7760,12 +7762,21 @@ static tree
 cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
 {
   tree statement = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is a ';', then there is no expression
      statement.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
+  /* Give a helpful message for "A<T>::type t;"  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
+      && !cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && TREE_CODE (statement) == SCOPE_REF)
+    error_at (token->location, "need %<typename%> before %qE to name "
+	      "a type in dependent scope %qT",
+	      statement, TREE_OPERAND (statement, 0));
+
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
@@ -18197,11 +18208,15 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      if (declarator)
+      if (declarator && !current_function_decl)
 	error_at (location, "specializing member %<%T::%E%> "
 		  "requires %<template<>%> syntax", 
 		  declarator->u.id.qualifying_scope,
 		  declarator->u.id.unqualified_name);
+      else if (declarator)
+	error_at (location, "invalid declaration of %<%T::%E%>",
+		  declarator->u.id.qualifying_scope,
+		  declarator->u.id.unqualified_name);
       else 
 	error_at (location, "too few template-parameter-lists");
       return false;
diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C
new file mode 100644
index 0000000..92101e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error36.C
@@ -0,0 +1,17 @@
+// Test for helpful error message about missing typename.
+
+template <class T> struct A { typedef T foo; typedef T bar; };
+template <class T>
+void f(T t)
+{
+  typedef A<T>::foo type;	// { dg-error "typename" }
+  A<T>::bar b;			// { dg-error "typename" }
+} // { dg-error "expected ';'" "" { target *-*-* } 8 }
+
+template <class T> struct B
+{
+  void f()
+  {
+    A<T>::baz z;		// { dg-error "typename" }
+  } // { dg-error "expected ';'" "" { target *-*-* } 15 }
+};
diff --git a/gcc/testsuite/g++.dg/template/error26.C b/gcc/testsuite/g++.dg/template/error26.C
index 7545762..cd8d46d 100644
--- a/gcc/testsuite/g++.dg/template/error26.C
+++ b/gcc/testsuite/g++.dg/template/error26.C
@@ -2,4 +2,4 @@
 
 template<typename> struct A;
 
-template<typename T> void foo (A<&T::template i>); // { dg-error "T::template i|mismatch|& T::i" }
+template<typename T> void foo (A<&T::template i>); // { dg-error "T:: ?template i|mismatch|& T::i" }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/typename1.C b/gcc/testsuite/g++.old-deja/g++.other/typename1.C
index 43d1352..4bf3de3 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/typename1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/typename1.C
@@ -13,5 +13,5 @@ public:
 template<class T>
 void f()
 {
-  Vector<T>::iterator i = 0; // { dg-error "expected" } missing typename
-}
+  Vector<T>::iterator i = 0; // { dg-error "typename" } missing typename
+} // { dg-error "expected" "" { target *-*-* } 16 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++ PATCH for c++/15946 (improved diagnostics for missing 'typename')
  2009-11-06 22:08 C++ PATCH for c++/15946 (improved diagnostics for missing 'typename') Jason Merrill
@ 2009-11-08  4:06 ` Jason Merrill
  2010-04-24 15:55   ` H.J. Lu
  2011-01-07 12:10   ` H.J. Lu
  0 siblings, 2 replies; 4+ messages in thread
From: Jason Merrill @ 2009-11-08  4:06 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 293 bytes --]

I noticed that the earlier patch didn't fix all the testcases in the 
various duplicate bugs.  So here's some more.  Lots of testsuite changes 
to deal with places that need typename, but previously weren't expecting 
a helpful error about that.

Tested x86_64-pc-linux-gnu, applied to trunk.

[-- Attachment #2: 15946-2.patch --]
[-- Type: text/x-patch, Size: 19141 bytes --]

commit 8b72008322a11346967026742bc3baa34b85308a
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Nov 7 18:07:32 2009 -0500

    	PR c++/18451
    	PR c++/40738
    	* cp-tree.h (cp_decl_specifier_seq): Add any_type_specifiers_p.
    	* parser.c (cp_parser_single_declaration): Call
    	cp_parser_parse_and_diagnose_invalid_type_name here, too.
    	(cp_parser_parameter_declaration): And here.
    	(cp_parser_parse_and_diagnose_invalid_type_name): Be
    	less picky about declarator form.  Don't skip to
    	the end of the block if	we're in a declarator.
    	(cp_parser_decl_specifier_seq): Set any_type_specifiers_p.
    	(cp_parser_simple_declaration): Check it.
    	(cp_parser_member_declaration): Likewise.
    	(cp_parser_diagnose_invalid_type_name): Tweak error message.
    	(cp_parser_expression_statement): Likewise.
    	* decl2.c (grokfield): Mention decltype instead of typeof.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c4b088b..68be934 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4267,6 +4267,8 @@ typedef struct cp_decl_specifier_seq {
   BOOL_BITFIELD conflicting_specifiers_p : 1;
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
+  /* True iff at least one type-specifier was found.  */
+  BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
   /* True iff "char" was explicitly provided.  */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 53f66ad..ba987f7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -789,7 +789,7 @@ grokfield (const cp_declarator *declarator,
 
   if (TREE_CODE (value) == TYPE_DECL && init)
     {
-      error ("typedef %qD is initialized (use __typeof__ instead)", value);
+      error ("typedef %qD is initialized (use decltype instead)", value);
       init = NULL_TREE;
     }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 47f5f13..7bafb67 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2402,8 +2402,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
 		  id, parser->scope);
       else if (TYPE_P (parser->scope)
 	       && dependent_scope_p (parser->scope))
-	error_at (location, "need %<typename%> before %<%T::%E%> to name "
-		  "a type in dependent scope %qT",
+	error_at (location, "need %<typename%> before %<%T::%E%> because "
+		  "%qT is a dependent scope",
 		  parser->scope, id, parser->scope);
       else if (TYPE_P (parser->scope))
 	error_at (location, "%qE in class %qT does not name a type",
@@ -2437,9 +2437,9 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 				/*template_p=*/NULL,
 				/*declarator_p=*/true,
 				/*optional_p=*/false);
-  /* After the id-expression, there should be a plain identifier,
-     otherwise this is not a simple variable declaration.  */
-  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+  /* If the next token is a (, this is a function with no explicit return
+     type, i.e. constructor, destructor or conversion op.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
       || TREE_CODE (id) == TYPE_DECL)
     {
       cp_parser_abort_tentative_parse (parser);
@@ -2451,9 +2451,11 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
   /* Emit a diagnostic for the invalid type.  */
   cp_parser_diagnose_invalid_type_name (parser, parser->scope,
 					id, token->location);
-  /* Skip to the end of the declaration; there's no point in
-     trying to process it.  */
-  cp_parser_skip_to_end_of_block_or_statement (parser);
+  /* If we aren't in the middle of a declarator (i.e. in a
+     parameter-declaration-clause), skip to the end of the declaration;
+     there's no point in trying to process it.  */
+  if (!parser->in_declarator_p)
+    cp_parser_skip_to_end_of_block_or_statement (parser);
   return true;
 }
 
@@ -7773,8 +7775,8 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
       && !cp_parser_uncommitted_to_tentative_parse_p (parser)
       && TREE_CODE (statement) == SCOPE_REF)
-    error_at (token->location, "need %<typename%> before %qE to name "
-	      "a type in dependent scope %qT",
+    error_at (token->location, "need %<typename%> before %qE because "
+	      "%qT is a dependent scope",
 	      statement, TREE_OPERAND (statement, 0));
 
   /* Consume the final `;'.  */
@@ -8846,7 +8848,7 @@ cp_parser_simple_declaration (cp_parser* parser,
        T t;
 
      where "T" should name a type -- but does not.  */
-  if (!decl_specifiers.type
+  if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     {
       /* If parsing tentatively, we should commit; we really are
@@ -9211,6 +9213,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 	    {
 	      constructor_possible_p = false;
 	      found_decl_spec = true;
+	      if (!is_cv_qualifier)
+		decl_specs->any_type_specifiers_p = true;
 	    }
 	}
 
@@ -14973,6 +14977,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
 				CP_PARSER_FLAGS_NONE,
 				&decl_specifiers,
 				&declares_class_or_enum);
+
+  /* Complain about missing 'typename' or other invalid type names.  */
+  if (!decl_specifiers.any_type_specifiers_p)
+    cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
   /* If an error occurred, there's no reason to attempt to parse the
      rest of the declaration.  */
   if (cp_parser_error_occurred (parser))
@@ -16523,7 +16532,7 @@ cp_parser_member_declaration (cp_parser* parser)
   prefix_attributes = decl_specifiers.attributes;
   decl_specifiers.attributes = NULL_TREE;
   /* Check for an invalid type-name.  */
-  if (!decl_specifiers.type
+  if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
   /* If there is no declarator, then the decl-specifier-seq should
@@ -18775,6 +18784,11 @@ cp_parser_single_declaration (cp_parser* parser,
 	  cp_parser_perform_template_parameter_access_checks (checks);
 	}
     }
+
+  /* Complain about missing 'typename' or other invalid type names.  */
+  if (!decl_specifiers.any_type_specifiers_p)
+    cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
   /* If it's not a template class, try for a template function.  If
      the next token is a `;', then this declaration does not declare
      anything.  But, if there were errors in the decl-specifiers, then
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
index d5ebf0d..485fffa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
@@ -1,4 +1,4 @@
 // { dg-options "-std=gnu++0x" }
 template<typename ... Elements> class Tuple;
 Tuple<>* t; // OK: Elements is empty
-Tuple* u; // { dg-error "expected" }
+Tuple* u; // { dg-error "template-name" }
diff --git a/gcc/testsuite/g++.dg/ext/typedef-init.C b/gcc/testsuite/g++.dg/ext/typedef-init.C
index 95a96d5..153303d 100644
--- a/gcc/testsuite/g++.dg/ext/typedef-init.C
+++ b/gcc/testsuite/g++.dg/ext/typedef-init.C
@@ -11,8 +11,7 @@
 
 /* Case A: just the bare name = initializer.  */
 
-typedef A = 0;  /* { dg-error "initialized" "A" } */
-                /* { dg-warning "no type" "A warns" { target *-*-* } 14 } */
+typedef A = 0;  /* { dg-error "does not name a type" "A" } */
 A a;            /* { dg-error "does not name a type" "A error cascade" } */
 
 /* Case B: with a type also.  */
@@ -24,9 +23,8 @@ B b;		    /* { dg-error "does not name a type" "B error cascade" } */
    field declarations go by a different code path in C++ (ick).  */
 
 struct S {
-  typedef C = 0; /* { dg-error "initialized" "C" } */
-                 /* { dg-warning "no type" "C warns" { target *-*-* } 27 } */
-  C c;		 /* { dg-bogus "" "C error cascade" } */
+  typedef C = 0; /* { dg-error "does not name a type" "C" } */
+  C c;		 /* { dg-error "" "C error cascade" } */
 
   typedef int D = 0; /* { dg-error "initialized" "D" } */
   D d;		     /* { dg-bogus "" "D error cascade" } */
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class1.C b/gcc/testsuite/g++.dg/lookup/hidden-class1.C
index fc71e96..b3be4e8 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-class1.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class1.C
@@ -4,5 +4,5 @@
 
 class A {
   friend class B;
-  B *b;		// { dg-error "no type|expected" }
+  B *b;		// { dg-error "type|expected" }
 };
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class10.C b/gcc/testsuite/g++.dg/lookup/hidden-class10.C
index f68196f..c9b5ca9 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-class10.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class10.C
@@ -7,5 +7,5 @@
 
 class A {
   friend class abort;
-  abort *b;	// { dg-error "no type|expected" }
+  abort *b;	// { dg-error "type|expected" }
 };
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class5.C b/gcc/testsuite/g++.dg/lookup/hidden-class5.C
index 1cf06bc..c241354 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-class5.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class5.C
@@ -6,4 +6,4 @@ class A {
   friend class B;
 };
 
-B* b;		// { dg-error "expected" }
+B* b;		// { dg-error "type|expected" }
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class7.C b/gcc/testsuite/g++.dg/lookup/hidden-class7.C
index f681cd6..a46ae71 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-class7.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class7.C
@@ -10,4 +10,4 @@ class C {
   friend class B;
 };
 
-B *b;		// { dg-error "expected" }
+B *b;		// { dg-error "type|expected" }
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-temp-class1.C b/gcc/testsuite/g++.dg/lookup/hidden-temp-class1.C
index c92b7f6..8cdb235 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-temp-class1.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-temp-class1.C
@@ -4,5 +4,5 @@
 
 class A {
   template <class T> friend class B;
-  B<int> *b;	// { dg-error "no type|expected" }
+  B<int> *b;	// { dg-error "type|expected" }
 };
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-temp-class4.C b/gcc/testsuite/g++.dg/lookup/hidden-temp-class4.C
index 02dc9c3..3d085e2 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-temp-class4.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-temp-class4.C
@@ -6,4 +6,4 @@ class A {
   template <class T> friend class B;
 };
 
-B<int> *b;	// { dg-error "expected" }
+B<int> *b;	// { dg-error "type|expected" }
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-temp-class7.C b/gcc/testsuite/g++.dg/lookup/hidden-temp-class7.C
index 22804d7..19dd952 100644
--- a/gcc/testsuite/g++.dg/lookup/hidden-temp-class7.C
+++ b/gcc/testsuite/g++.dg/lookup/hidden-temp-class7.C
@@ -10,4 +10,4 @@ class C {
   template <class T> friend class B;
 };
 
-B<int> *b;	// { dg-error "expected" }
+B<int> *b;	// { dg-error "type|expected" }
diff --git a/gcc/testsuite/g++.dg/lookup/strong-using-2.C b/gcc/testsuite/g++.dg/lookup/strong-using-2.C
index 5c4b425..314aa52 100644
--- a/gcc/testsuite/g++.dg/lookup/strong-using-2.C
+++ b/gcc/testsuite/g++.dg/lookup/strong-using-2.C
@@ -20,4 +20,4 @@ namespace baz {
 
 foo::T *t1;
 bar::T *t2;
-baz::T *t3; // { dg-error "(ambiguous|expected|extra)" "" }
+baz::T *t3; // { dg-error "(ambiguous|does not name a type)" "" }
diff --git a/gcc/testsuite/g++.dg/other/typedef1.C b/gcc/testsuite/g++.dg/other/typedef1.C
index 55d62bb..ef1684d 100644
--- a/gcc/testsuite/g++.dg/other/typedef1.C
+++ b/gcc/testsuite/g++.dg/other/typedef1.C
@@ -2,6 +2,6 @@
 // { dg-do compile }
 
 void f1(typedef) {}        // { dg-error "no type|typedef declaration" }
-void f2(typedef x) {}      // { dg-error "no type|typedef declaration" }
-void f3(typedef x[]) {}    // { dg-error "no type|typedef declaration" }
+void f2(typedef x) {}      // { dg-error "type|typedef declaration" }
+void f3(typedef x[]) {}    // { dg-error "type|typedef declaration" }
 void f4(typedef int x) {}  // { dg-error "typedef declaration" }
diff --git a/gcc/testsuite/g++.dg/parse/access10.C b/gcc/testsuite/g++.dg/parse/access10.C
index ebfeea9..62adc1b 100644
--- a/gcc/testsuite/g++.dg/parse/access10.C
+++ b/gcc/testsuite/g++.dg/parse/access10.C
@@ -7,7 +7,5 @@ template<int> struct A
     ::A~();			// { dg-bogus "using-declaration" }
 };
 
-// Instead of the bogus error we get 3 separate errors.
-// { dg-error "no type" "" { target *-*-* } 7 }
-// { dg-error "::" "" { target *-*-* } 7 }
-// { dg-error "~" "" { target *-*-* } 7 }
+// Instead of the bogus error we get a different error.
+// { dg-error "template-name" "" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/parse/constructor1.C b/gcc/testsuite/g++.dg/parse/constructor1.C
index 1796531..1bb9ee0 100644
--- a/gcc/testsuite/g++.dg/parse/constructor1.C
+++ b/gcc/testsuite/g++.dg/parse/constructor1.C
@@ -1,8 +1,8 @@
 // { dg-do compile }
 // { dg-options "-fshow-column" }
 
-ACE_Process_Descriptor::ACE_Process_Descriptor () : // { dg-error "declared" "declared" }
-  // { dg-error "no type" "no type" { target *-*-* } 4 }
-  process_ (0) // { dg-error "3: only constructors take base initializers" }
+ACE_Process_Descriptor::ACE_Process_Descriptor () :
+  // { dg-error "does not name a type" "no type" { target *-*-* } 4 }
+  process_ (0)
 {
 }
diff --git a/gcc/testsuite/g++.dg/parse/crash38.C b/gcc/testsuite/g++.dg/parse/crash38.C
index c050b93..724f9b8 100644
--- a/gcc/testsuite/g++.dg/parse/crash38.C
+++ b/gcc/testsuite/g++.dg/parse/crash38.C
@@ -3,7 +3,7 @@
 /* This would not ICE.  */
 namespace M { } /* { dg-error "previous declaration" } */
 struct M; /* { dg-error "redeclared as different kind of symbol" } */
-M *p; /* { dg-error "expected constructor" } */
+M *p; /* { dg-error "does not name a type" } */
 
 /* This would ICE when processing 'p'.  */
 namespace N { } /* { dg-error "previous declaration" } */
diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C
index 55ae024..7e8cf8d 100644
--- a/gcc/testsuite/g++.dg/parse/error3.C
+++ b/gcc/testsuite/g++.dg/parse/error3.C
@@ -5,5 +5,5 @@ static void InstantiateConstraint(const float&, unsigned,
                                   void(*AddFunction)(const TYPE&,bool&,
                                                      char*, char*,
                                                      unsigned*));
-// { dg-error "64:expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
-// { dg-error "60:ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 5 } }
+// { dg-error "64: ISO C\\+\\+ forbids declaration of 'parameter' with no type" "" { target *-*-* }  { 5 } }
+// { dg-error "60: 'TYPE' does not name a type" "" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C
index 92101e9..0d7f8cf 100644
--- a/gcc/testsuite/g++.dg/parse/error36.C
+++ b/gcc/testsuite/g++.dg/parse/error36.C
@@ -1,17 +1,33 @@
+// PR c++/15946
 // Test for helpful error message about missing typename.
 
-template <class T> struct A { typedef T foo; typedef T bar; };
+template <class T> struct A
+{
+  struct B { };
+  static B b;
+};
+
 template <class T>
 void f(T t)
 {
   typedef A<T>::foo type;	// { dg-error "typename" }
   A<T>::bar b;			// { dg-error "typename" }
-} // { dg-error "expected ';'" "" { target *-*-* } 8 }
+} // { dg-error "expected ';'" "" { target *-*-* } 14 }
 
+// PR c++/36353
 template <class T> struct B
 {
   void f()
   {
     A<T>::baz z;		// { dg-error "typename" }
-  } // { dg-error "expected ';'" "" { target *-*-* } 15 }
+  } // { dg-error "expected ';'" "" { target *-*-* } 22 }
 };
+
+// PR c++/40738
+template <class T>
+void g(const A<T>::type &t);	// { dg-error "typename" }
+// { dg-error "no type" "" { target *-*-* } 28 }
+
+// PR c++/18451
+template <class T> A<T>::B A<T>::b; // { dg-error "typename" }
+// { dg-error "expected" "" { target *-*-* } 32 }
diff --git a/gcc/testsuite/g++.dg/parse/typespec1.C b/gcc/testsuite/g++.dg/parse/typespec1.C
index a371f8b..44ee116 100644
--- a/gcc/testsuite/g++.dg/parse/typespec1.C
+++ b/gcc/testsuite/g++.dg/parse/typespec1.C
@@ -1,4 +1,4 @@
 // PR c++/26571
 
 struct A {};
-unsigned A a;			// { dg-error "multiple" }
+unsigned A a;			// { dg-error "expected initializer" }
diff --git a/gcc/testsuite/g++.dg/template/typedef5.C b/gcc/testsuite/g++.dg/template/typedef5.C
index abd9ebb..04b8eac 100644
--- a/gcc/testsuite/g++.dg/template/typedef5.C
+++ b/gcc/testsuite/g++.dg/template/typedef5.C
@@ -2,6 +2,6 @@
 // { dg-do compile }
 
 template<typedef,int>        struct A1; // { dg-error "no type|typedef declaration|default argument" }
-template<typedef x,int>      struct A2; // { dg-error "no type|typedef declaration|default argument" }
-template<typedef x[],int>    struct A3; // { dg-error "no type|typedef declaration|default argument" }
+template<typedef x,int>      struct A2; // { dg-error "type|typedef declaration|default argument" }
+template<typedef x[],int>    struct A3; // { dg-error "no type|typedef declaration|expected" }
 template<typedef int x, int> struct A4; // { dg-error "typedef declaration|default argument" }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
index 9b41275..0708f1f 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
@@ -17,5 +17,5 @@ struct B : public A<U>
 
 
 template <class U>
-B<U>::A_Type B<U>::Func() { // { dg-error "expected" } implicit typename
-}
+B<U>::A_Type B<U>::Func() { // { dg-error "typename" } implicit typename
+}			    // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
index 286795c..7238470 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
@@ -22,5 +22,5 @@ struct C : public B<U>
 
 
 template <class U>
-C<U>::A_Type C<U>::Func() { // { dg-error "expected" } implicit typename
-}
+C<U>::A_Type C<U>::Func() { // { dg-error "typename" } implicit typename
+}			    // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
index 2794479..0a5f018 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
@@ -15,6 +15,6 @@ struct B : public A<U>
 };
 
 template <class U>
-A<U>::A_Type B<U>::Func()       // { dg-error "expected" } function
+A<U>::A_Type B<U>::Func()       // { dg-error "typename" } function
 {				
-}
+} // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb94.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb94.C
index b3d2da1..5350236 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb94.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb94.C
@@ -10,7 +10,7 @@ static int variable;
 class myClass : public baseClass
 {
 private:
-static int variable;                    // this is intentionally duplicated
+static int variable;                    // { dg-error "private" }
 };
 
 myClass::variable = 0;                  //{ dg-error "" } no type

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++ PATCH for c++/15946 (improved diagnostics for missing   'typename')
  2009-11-08  4:06 ` Jason Merrill
@ 2010-04-24 15:55   ` H.J. Lu
  2011-01-07 12:10   ` H.J. Lu
  1 sibling, 0 replies; 4+ messages in thread
From: H.J. Lu @ 2010-04-24 15:55 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Sat, Nov 7, 2009 at 8:46 PM, Jason Merrill <jason@redhat.com> wrote:
> I noticed that the earlier patch didn't fix all the testcases in the various
> duplicate bugs.  So here's some more.  Lots of testsuite changes to deal
> with places that need typename, but previously weren't expecting a helpful
> error about that.
>
> Tested x86_64-pc-linux-gnu, applied to trunk.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43868

-- 
H.J.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++ PATCH for c++/15946 (improved diagnostics for missing 'typename')
  2009-11-08  4:06 ` Jason Merrill
  2010-04-24 15:55   ` H.J. Lu
@ 2011-01-07 12:10   ` H.J. Lu
  1 sibling, 0 replies; 4+ messages in thread
From: H.J. Lu @ 2011-01-07 12:10 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Sat, Nov 7, 2009 at 7:46 PM, Jason Merrill <jason@redhat.com> wrote:
> I noticed that the earlier patch didn't fix all the testcases in the various
> duplicate bugs.  So here's some more.  Lots of testsuite changes to deal
> with places that need typename, but previously weren't expecting a helpful
> error about that.
>
> Tested x86_64-pc-linux-gnu, applied to trunk.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47198


-- 
H.J.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-01-07  5:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-06 22:08 C++ PATCH for c++/15946 (improved diagnostics for missing 'typename') Jason Merrill
2009-11-08  4:06 ` Jason Merrill
2010-04-24 15:55   ` H.J. Lu
2011-01-07 12:10   ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).