OSDN Git Service

PR c++/15946
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Nov 2009 21:18:42 +0000 (21:18 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Nov 2009 21:18:42 +0000 (21:18 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153978 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cxx-pretty-print.c
gcc/cp/error.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/error36.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/error26.C
gcc/testsuite/g++.old-deja/g++.other/typename1.C

index 36f7255..4db5aac 100644 (file)
@@ -1,5 +1,17 @@
 2009-11-06  Jason Merrill  <jason@redhat.com>
 
+       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.
+
        PR c++/9381
        * decl2.c (build_memfn_type): Preserve attributes.
        (cp_reconstruct_complex_type): Likewise.
index 1d7f9cf..4851af9 100644 (file)
@@ -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:
index ce5660f..f423207 100644 (file)
@@ -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:
index 1d677cb..47f5f13 100644 (file)
@@ -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;
index be66e31..77cf10c 100644 (file)
@@ -1,5 +1,9 @@
 2009-11-06  Jason Merrill  <jason@redhat.com>
 
+       PR c++/15946
+       * g++.dg/parse/error36.C: New.
+       * g++.old-deja/g++.other/typename1.C: Adjust.
+
        PR c++/9381
        * g++.dg/abi/regparm1.C: New.
 
diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C
new file mode 100644 (file)
index 0000000..92101e9
--- /dev/null
@@ -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 }
+};
index 7545762..cd8d46d 100644 (file)
@@ -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" }
index 43d1352..4bf3de3 100644 (file)
@@ -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 }