PR c++/51145 - Alias template in elaborated-type-specifier accepted
authorDodji Seketeli <dodji@redhat.com>
Wed, 23 Nov 2011 08:23:59 +0000 (08:23 +0000)
committerDodji Seketeli <dodji@gcc.gnu.org>
Wed, 23 Nov 2011 08:23:59 +0000 (09:23 +0100)
gcc/cp/

PR c++/51145
* decl.c (check_elaborated_type_specifier): Gracefully handle
error_mark_node.  Accept bound template template parameters.
Update diagnostics for alias template specializations.  Update
comment.
* parser.c (cp_parser_elaborated_type_specifier): Use
check_elaborated_type_specifier for simple-template-ids as well.

gcc/testsuite/

PR c++/51145
* g++.dg/cpp0x/alias-decl-14.C: New test.
* g++.dg/cpp0x/alias-decl-2.C: Adjust for tests that were wrongly
passing before.
* g++.dg/cpp0x/alias-decl-10.C: Likewise and adjust for diagnostic
change.
* g++.dg/ext/attrib27.C: Adjust for diagnostic change.
* g++.dg/lookup/struct1.C: Likewise.
* g++.dg/parse/elab1.C: Likewise.
* g++.dg/parse/elab2.C: Likewise.
* g++.dg/parse/int-as-enum1.C: Likewise.
* g++.dg/parse/typedef1.C: Likewise.
* g++.dg/parse/typedef3.C: Likewise.
* g++.dg/parse/typedef4.C: Likewise.
* g++.dg/parse/typedef5.C: Likewise.
* g++.dg/template/crash26.C: Likewise.
* g++.dg/template/nontype4.C: Likewise.
* g++.old-deja/g++.benjamin/typedef01.C: Likewise.
* g++.old-deja/g++.brendan/line1.C: Likewise.
* g++.old-deja/g++.other/elab1.C: Likewise.
* g++.old-deja/g++.other/syntax4.C: Likewise.

From-SVN: r181653

22 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
gcc/testsuite/g++.dg/ext/attrib27.C
gcc/testsuite/g++.dg/lookup/struct1.C
gcc/testsuite/g++.dg/parse/elab1.C
gcc/testsuite/g++.dg/parse/elab2.C
gcc/testsuite/g++.dg/parse/int-as-enum1.C
gcc/testsuite/g++.dg/parse/typedef1.C
gcc/testsuite/g++.dg/parse/typedef3.C
gcc/testsuite/g++.dg/parse/typedef4.C
gcc/testsuite/g++.dg/parse/typedef5.C
gcc/testsuite/g++.dg/template/crash26.C
gcc/testsuite/g++.dg/template/nontype4.C
gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
gcc/testsuite/g++.old-deja/g++.brendan/line1.C
gcc/testsuite/g++.old-deja/g++.other/elab1.C
gcc/testsuite/g++.old-deja/g++.other/syntax4.C

index 9d8f47b8666f78676234ec99505c6e1006387fac..6833fc390f293b596ae3f2d382ea55a51bca91ff 100644 (file)
@@ -1,3 +1,13 @@
+2011-11-22  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/51145
+       * decl.c (check_elaborated_type_specifier): Gracefully handle
+       error_mark_node.  Accept bound template template parameters.
+       Update diagnostics for alias template specializations.  Update
+       comment.
+       * parser.c (cp_parser_elaborated_type_specifier): Use
+       check_elaborated_type_specifier for simple-template-ids as well.
+
 2011-11-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/51265
index b77963b72df26da9cdaca16d10b49df1dc743ac1..84064326f4dd00172dd9c480eb77cac7eb9e2ab4 100644 (file)
@@ -11342,6 +11342,9 @@ check_elaborated_type_specifier (enum tag_types tag_code,
 {
   tree type;
 
+  if (decl == error_mark_node)
+    return error_mark_node;
+
   /* In the case of:
 
        struct S { struct S *p; };
@@ -11361,10 +11364,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
             type, tag_name (tag_code));
       return error_mark_node;
     }
+  /* Accept bound template template parameters.  */
+  else if (allow_template_p
+          && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+    ;
   /*   [dcl.type.elab]
 
-       If the identifier resolves to a typedef-name or a template
-       type-parameter, the elaborated-type-specifier is ill-formed.
+       If the identifier resolves to a typedef-name or the
+       simple-template-id resolves to an alias template
+       specialization, the elaborated-type-specifier is ill-formed.
 
      In other words, the only legitimate declaration to use in the
      elaborated type specifier is the implicit typedef created when
@@ -11373,8 +11381,13 @@ check_elaborated_type_specifier (enum tag_types tag_code,
           && !DECL_SELF_REFERENCE_P (decl)
           && tag_code != typename_type)
     {
-      error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
-      error ("%q+D has a previous declaration here", decl);
+      if (alias_template_specialization_p (type))
+       error ("using alias template specialization %qT after %qs",
+              type, tag_name (tag_code));
+      else
+       error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+      inform (DECL_SOURCE_LOCATION (decl),
+             "%qD has a previous declaration here", decl);
       return error_mark_node;
     }
   else if (TREE_CODE (type) != RECORD_TYPE
index d0adaa03c037c73791e24d02673097593d1df828..2fdd6753d08802add0bc441b9df28e47c9767f12 100644 (file)
@@ -13960,7 +13960,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
         type = NULL_TREE; 
       else 
-       type = TREE_TYPE (decl);
+       type = check_elaborated_type_specifier (tag_type, decl,
+                                               /*allow_template_p=*/true);
     }
 
   if (!type)
index 27365e4eabc5a65f2be3dae5259d60914e5c1b6e..9b3b01f97ef2c831c47d4ca3112b861c8337a944 100644 (file)
@@ -1,3 +1,27 @@
+2011-11-22  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/51145
+       * g++.dg/cpp0x/alias-decl-14.C: New test.
+       * g++.dg/cpp0x/alias-decl-2.C: Adjust for tests that were wrongly
+       passing before.
+       * g++.dg/cpp0x/alias-decl-10.C: Likewise and adjust for diagnostic
+       change.
+       * g++.dg/ext/attrib27.C: Adjust for diagnostic change.
+       * g++.dg/lookup/struct1.C: Likewise.
+       * g++.dg/parse/elab1.C: Likewise.
+       * g++.dg/parse/elab2.C: Likewise.
+       * g++.dg/parse/int-as-enum1.C: Likewise.
+       * g++.dg/parse/typedef1.C: Likewise.
+       * g++.dg/parse/typedef3.C: Likewise.
+       * g++.dg/parse/typedef4.C: Likewise.
+       * g++.dg/parse/typedef5.C: Likewise.
+       * g++.dg/template/crash26.C: Likewise.
+       * g++.dg/template/nontype4.C: Likewise.
+       * g++.old-deja/g++.benjamin/typedef01.C: Likewise.
+       * g++.old-deja/g++.brendan/line1.C: Likewise.
+       * g++.old-deja/g++.other/elab1.C: Likewise.
+       * g++.old-deja/g++.other/syntax4.C: Likewise.
+
 2011-11-22  Tom de Vries  <tom@codesourcery.com>
 
        PR rtl-optimization/50764
index 856e4297af5548256773eb9e3feced8e3ef2fe5f..733e791c2bc63b7e0ff65fc5a0015bd683a8527e 100644 (file)
@@ -3,16 +3,24 @@
 template <class T> using Ptr = T*;
 Ptr<unsigned>; // { dg-error "does not declare anything" }
 Ptr<char><int>; // { dg-error "not a template|does not declare anything" }
-template class Ptr<int>;//{ dg-error "explicit instantiation|non-class templ|does not decl|anything" }
+template class Ptr<int>;//{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
 
 template <class T> using Arg = T;
 struct A {};
-template class Arg<A>;// { dg-error "explicit instantiation|non-class templ" }
+template class Arg<A>;// { dg-error "alias templ\[^\n\r\]*specialization\[^\n\r\]*Arg<A>\[^\n\r\]*after\[^\n\r\]*class" }
 
 template <template <class> class TT, class T> using Instantiate = TT<T>;
 template <class> struct Vector {};
-template class Instantiate<Vector, int>; // OK Vector<int> can be explicitely instantiated
+
+// The below is not OK, because of [dcl.type.elab]:
+// 
+//     If the identifier resolves to a typedef-name or the
+//     simple-template-id resolves to an alias template
+//     specialization, the elaborated-type-specifier is ill-formed.
+//
+template class Instantiate<Vector, int>;//{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
 
 template <class T> struct S {};
 template<class T> using SFor = S<T>;
-template class SFor<int>; // OK, S<int> can be explicitely instantiated
+// Likewise, this is not OK.
+template class SFor<int>; //{ dg-error "alias template specialization\[^\n\r\]*after\[^\n\r\]*class" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
new file mode 100644 (file)
index 0000000..1a99802
--- /dev/null
@@ -0,0 +1,14 @@
+// Origin: PR c++/51145
+// { dg-options "-std=c++0x" }
+
+struct A {};
+
+template<class>
+using X = A;
+
+struct X<int>* px; // { dg-error "using\[^\n\r\]*alias\[^\n\r\]*specialization\[^\n\r\]*X<int>\[^\n\r\]*after\[^\n\r\]*struct|invalid type in declaration before\[^\n\r\]*;" }
+
+template<int>
+using Y = A;
+
+struct Y<0>* py;// { dg-error "alias\[^\n\r\]*specialization\[^\n\r\]*Y<0>\[^\n\r\]*after\[^\n\r\]*struct|invalid type in declaration before\[^\n\r\]*;" }
index 2e03dd897b53cdd122dcbc0e9de557fecc1d139d..6b5b42f7fde2f1a7e568659d164755e456fee45f 100644 (file)
@@ -6,7 +6,7 @@ template<class T> using AS0 = S0<T>;
 template<template<class> class TT>
 void f(TT<int>);
 
-template class AS0<char>;
+template class AS0<char>; // { dg-error "alias templ\[^\n\r\]*specialization\[^\n\r\]*after\[^\n\r\]*class" }
 
 void
 foo()
index 4f629aa5372050acec909f6a9e6b4ca67c22f03c..b770c1c4404b9093a615f2beeff2579b8473c483 100644 (file)
@@ -1,5 +1,5 @@
 //PR c++/29980
 
-struct A { typedef int X; };            // { dg-error "previous declaration" }
+struct A { typedef int X; };            // { dg-message "previous declaration" }
 
 struct __attribute__((unused)) A::X;    // { dg-error "typedef-name" }
index f4b83ecf6b8b568287cf077ee70db88cff9e6baa..7c1e38c1863fdeacbb8f9fe3a7545ab62c794522 100644 (file)
@@ -2,10 +2,10 @@
 // the definition of C.
 
 struct A;
-typedef struct A B;            // { dg-error "previous declaration" }
+typedef struct A B;            // { dg-message "previous declaration" }
 struct B;                      // { dg-error "using typedef-name" }
 
-typedef struct { int i; } C;   // { dg-error "previous declaration" }
+typedef struct { int i; } C;   // { dg-message "previous declaration" }
 struct C;                      // { dg-error "using typedef-name" }
 
 struct D;
index 92fcd1ca69c425fafdb98dff4b983a02102121b0..8108e1d0f6d106fb86d17e74e1fa192635f4fb90 100644 (file)
@@ -1,6 +1,6 @@
 namespace Name {
 
-    typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" }
+    typedef void *(*Function)( void *, int ); // { dg-message "previous declaration" }
 
     struct Foo {
       struct Function xyz[5]; // { dg-error "" }
index 6b42aed67a4c3df37a6fe4b47c91748cec1c4757..bf59f1b711dc956d8006d2e1c44857800f6263d0 100644 (file)
@@ -2,6 +2,6 @@ struct A {};
 
 struct B
 {
-  typedef A T; // { dg-error "previous declaration" }
+  typedef A T; // { dg-message "previous declaration" }
   friend struct T; // { dg-error "" }
 };
index 7c37eb08792b0e71e2de5981862f5e1ebba6ea5c..c5ed261f6254c34f56f4f00ef3342a57aecfb6aa 100644 (file)
@@ -2,5 +2,5 @@
 // Origin: <wanderer@rsu.ru>
 // { dg-do compile }
 
-typedef int A; // { dg-error "previous" }
+typedef int A; // { dg-message "previous" }
 enum ::A {};   // { dg-error "typedef-name|expected unqualified-id" }
index c4fbb950cf1acf20fe8d27aa5601222e55068590..4d6f5b4fba5df9fe15343f42701ae5dc5a03f262 100644 (file)
@@ -1,3 +1,3 @@
 // PR c++/6477
-typedef struct A_ *A;  // { dg-error "previous declaration" }
+typedef struct A_ *A;  // { dg-message "previous declaration" }
 typedef struct A B;    // { dg-error "typedef|invalid type" }
index 6b4e531b677293423d173b0ae4042d6fbf9575bc..3f6a7cb91b48f6bb2422670e45a1919b2e0c43e3 100644 (file)
@@ -2,6 +2,6 @@
 // Origin: Travis J.I. Corcoran <tjic@permabit.com>
 // { dg-do compile }
 
-struct A { typedef A* Ptr; };  // { dg-error "previous declaration" }
+struct A { typedef A* Ptr; };  // { dg-message "previous declaration" }
 
 struct A::Ptr;                 // { dg-error "typedef|not declare anything" }
index 8599fd1d88410ac36ceebeffbf12222024e7fed4..d4cec7f9c5241c00f49637eedb4012ab976869dd 100644 (file)
@@ -7,6 +7,6 @@
 template<class T> class smart_ptr2 {
     T* real_ptr;
  public:
-    typedef typename T::subT  td; // { dg-error "previous declaration" }
+    typedef typename T::subT  td; // { dg-message "previous declaration" }
     friend class td; // { dg-error "typedef|not name a class" }
 };
index 7079f371333cd1944f3606fec1a316d3554dc478..ecd1d513efa75decafb1edc2733db903e504615a 100644 (file)
@@ -1,6 +1,6 @@
 namespace A
 {
-  typedef int T;       // { dg-error "previous declaration" }
+  typedef int T;       // { dg-message "previous declaration" }
 }
 
 class A::T x;          // { dg-error "using typedef-name|invalid type" }
index f1bc399a31da981a083d19449c2f292b8780c791..3be7ff97c26f261de325bc5121403adebd8144f2 100644 (file)
@@ -4,5 +4,5 @@
 
 // PR c++/18471: ICE redeclaration of typedef as class template
 
-typedef int X;                 // { dg-error "previous" }
+typedef int X;                 // { dg-message "previous" }
 template<X> struct X {};       // { dg-error "typedef-name" }
index ab39ed443976216cc6997a69e5ec7f7d7e80b088..41e3e22c0003b6d7682dfb5695db3768f155dbaf 100644 (file)
@@ -7,7 +7,7 @@
 
 template <int> struct A
 {
-    typedef A<0> B;            // { dg-error "previous declaration" }
+    typedef A<0> B;            // { dg-message "previous declaration" }
     template <B> struct B {};  // { dg-error "not a valid type|typedef" }
 };
 
index 79a965b16f2539664152cca2677ef8e33ea20899..d5ed39af3644a919a07efd4020a4c78add6e95ae 100644 (file)
@@ -18,7 +18,7 @@ typedef I I;
 //p3--cannot redefine to a different type in a given scope
 class complex2 { /* ... */ };// { dg-error "" } .*
 typedef int complex2;// { dg-error "" } .*
-typedef int complex3;// { dg-error "" } .*
+typedef int complex3;// { dg-message "" } .*
 class complex3 { /* ... */ };// { dg-error "" } .*
 
 
@@ -37,7 +37,7 @@ struct S {
   ~S();
 };
 
-typedef struct S T;            // { dg-error "previous declaration" }
+typedef struct S T;            // { dg-message "previous declaration" }
 
 S a = T();                      // OK 
 struct T * p;                   // { dg-error "" } using typedef after struct
index b14ed8efa181182c752cfb19e274c40def16026a..94130ec467688a66ec474b1d4a8ea89ecbdcffd3 100644 (file)
@@ -1,4 +1,4 @@
 // { dg-do assemble  }
 // GROUPS passed error-messages
-typedef struct s S;// { dg-error "" }  previous.*
+typedef struct s S;// { dg-message "" }  previous.*
 struct S { int member:1; };  // the lineno for this should be 2, not 0// { dg-error "" }  conflicting types.*
index 5588651dfe5fef4152fe6ca9423b0fbebed92df8..f09ff6f1c4c9379b9990b91a2dcdec4541c9e41b 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-typedef struct {} S; // { dg-error "" } Previous declaration of S
+typedef struct {} S; // { dg-message "" } Previous declaration of S
 
 S s1;
 struct S* s2; // { dg-error "" } S is a typedef name
index 7aed1f5b14070c963f49629bf9268e5247b8c248..445c539c921107dce72fd6b3bc4df019f18217e5 100644 (file)
@@ -17,7 +17,7 @@ class X {
 
 class Y {
   public:
-  typedef ::X W;   // { dg-error "" } previous declaration
+  typedef ::X W;   // { dg-message "" } previous declaration
   class Z;
 };