re PR c++/18738 (typename not allowed with non-dependent qualified name)
authorMark Mitchell <mark@codesourcery.com>
Wed, 15 Dec 2004 00:42:33 +0000 (00:42 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 15 Dec 2004 00:42:33 +0000 (00:42 +0000)
PR c++/18738
* decl.c (make_typename_type): Do not handle namespace-scoped
names here.
(tag_name): Handle typename_type.
(check_elaborated_type_specifier): Handle typenames.
* parser.c (cp_parser_diagnose_invalid_type_name): Improve
comment.
(cp_parser_elaborated_type_specifier): Use
cp_parser_diagnose_invalid_type_name.

PR c++/18738
* g++.dg/template/typename8.C: New test.
* g++.dg/parse/friend2.C: Tweak error message.

From-SVN: r92172

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/friend2.C
gcc/testsuite/g++.dg/template/typename8.C [new file with mode: 0644]

index ef5462859d97fe8f440bc2dac1fd1f3d2c7a5750..120f9b9cff85745a54cd77652ea60e22d01916ce 100644 (file)
@@ -1,3 +1,15 @@
+2004-12-14  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18738
+       * decl.c (make_typename_type): Do not handle namespace-scoped
+       names here.
+       (tag_name): Handle typename_type.
+       (check_elaborated_type_specifier): Handle typenames.
+       * parser.c (cp_parser_diagnose_invalid_type_name): Improve
+       comment.
+       (cp_parser_elaborated_type_specifier): Use
+       cp_parser_diagnose_invalid_type_name.
+
 2004-12-14  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR c++/18965
index 410f686a3ae1d90cf6165310ccdcc34d9e353b46..d711899bdaf0adcd7c3c5b86b804ac754ae93eba 100644 (file)
@@ -2669,15 +2669,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
       return error_mark_node;
     }
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-
-  if (TREE_CODE (context) == NAMESPACE_DECL)
-    {
-      /* We can get here from typename_sub0 in the explicit_template_type
-        expansion.  Just fail.  */
-      if (complain & tf_error)
-       error ("no class template named %q#T in %q#T", name, context);
-      return error_mark_node;
-    }
+  gcc_assert (TYPE_P (context));
 
   if (!dependent_type_p (context)
       || currently_open_class (context))
@@ -9048,6 +9040,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
   return ok;
 }
 \f
+/* Return a string giving the keyword associate with CODE.  */
+
 static const char *
 tag_name (enum tag_types code)
 {
@@ -9058,9 +9052,11 @@ tag_name (enum tag_types code)
     case class_type:
       return "class";
     case union_type:
-      return "union ";
+      return "union";
     case enum_type:
       return "enum";
+    case typename_type:
+      return "typename";
     default:
       gcc_unreachable ();
     }
@@ -9106,7 +9102,8 @@ check_elaborated_type_specifier (enum tag_types tag_code,
      In other words, the only legitimate declaration to use in the
      elaborated type specifier is the implicit typedef created when
      the type is declared.  */
-  else if (!DECL_IMPLICIT_TYPEDEF_P (decl))
+  else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+          && tag_code != typename_type)
     {
       error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
       cp_error_at ("%qD has a previous declaration here", decl);
@@ -9114,14 +9111,16 @@ check_elaborated_type_specifier (enum tag_types tag_code,
     }
   else if (TREE_CODE (type) != RECORD_TYPE
           && TREE_CODE (type) != UNION_TYPE
-          && tag_code != enum_type)
+          && tag_code != enum_type
+          && tag_code != typename_type)
     {
       error ("%qT referred to as %qs", type, tag_name (tag_code));
       cp_error_at ("%qT has a previous declaration here", type);
       return error_mark_node;
     }
   else if (TREE_CODE (type) != ENUMERAL_TYPE
-          && tag_code == enum_type)
+          && tag_code == enum_type
+          && tag_code != typename_type)
     {
       error ("%qT referred to as enum", type);
       cp_error_at ("%qT has a previous declaration here", type);
index 9d3696ff17f13042da1ef53dcd8bd2d8f06021df..13578f0e713cd55e6e71b8f30b4f63f4dba281c9 100644 (file)
@@ -1939,9 +1939,8 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
   return false;
 }
 
-/* Emit a diagnostic for an invalid type name. Consider also if it is
-   qualified or not and the result of a lookup, to provide a better
-   message.  */
+/* Emit a diagnostic for an invalid type name.  SCOPE is the
+   qualifying scope (or NULL, if none) for ID.  */
 
 static void
 cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
@@ -9647,7 +9646,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
        }
 
       /* For a `typename', we needn't call xref_tag.  */
-      if (tag_type == typename_type)
+      if (tag_type == typename_type 
+         && TREE_CODE (parser->scope) != NAMESPACE_DECL)
        return cp_parser_make_typename_type (parser, parser->scope,
                                             identifier);
       /* Look up a qualified name in the usual way.  */
@@ -9655,9 +9655,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
        {
          tree decl;
 
-         /* In an elaborated-type-specifier, names are assumed to name
-            types, so we set IS_TYPE to TRUE when calling
-            cp_parser_lookup_name.  */
          decl = cp_parser_lookup_name (parser, identifier,
                                        tag_type,
                                        /*is_template=*/false,
@@ -9692,7 +9689,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
          if (TREE_CODE (decl) != TYPE_DECL)
            {
-             error ("expected type-name");
+             cp_parser_diagnose_invalid_type_name (parser, 
+                                                   parser->scope,
+                                                   identifier);
              return error_mark_node;
            }
 
index f58377f015515074c46b6024a74b85f3c4fb94be..ec5facc72ac7c045d83e9ab625b6a1a51d7e2d0e 100644 (file)
@@ -1,3 +1,9 @@
+2004-12-14  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18738
+       * g++.dg/template/typename8.C: New test.
+       * g++.dg/parse/friend2.C: Tweak error message.
+
 2004-12-14  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * gcc.c-torture/20041214-1.c: New test.
index 2e88845cceb0ede102b18be448b189fb4e6fa5b8..1a2ad8bfad9280cf187154c6f972ae39d8324e91 100644 (file)
@@ -10,7 +10,7 @@ namespace NS {
 }
 
 template <class T> class X {
-  friend class NS::C;  // { dg-error "expected|friend" }
+  friend class NS::C;  // { dg-error "template|friend" }
 };
 
 X<int> c;
diff --git a/gcc/testsuite/g++.dg/template/typename8.C b/gcc/testsuite/g++.dg/template/typename8.C
new file mode 100644 (file)
index 0000000..85f585d
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/18738
+
+namespace foo {
+  typedef int my_type;
+}
+
+template<typename T>
+struct A {
+  typename foo::my_type bar();
+};