Commit 82daaf6d by Dodji Seketeli Committed by Dodji Seketeli

PR c++/51145 - Alias template in elaborated-type-specifier accepted

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
parent b64cd62a
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> 2011-11-22 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51265 PR c++/51265
......
...@@ -11342,6 +11342,9 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -11342,6 +11342,9 @@ check_elaborated_type_specifier (enum tag_types tag_code,
{ {
tree type; tree type;
if (decl == error_mark_node)
return error_mark_node;
/* In the case of: /* In the case of:
struct S { struct S *p; }; struct S { struct S *p; };
...@@ -11361,10 +11364,15 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -11361,10 +11364,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type, tag_name (tag_code)); type, tag_name (tag_code));
return error_mark_node; return error_mark_node;
} }
/* Accept bound template template parameters. */
else if (allow_template_p
&& TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
;
/* [dcl.type.elab] /* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template If the identifier resolves to a typedef-name or the
type-parameter, the elaborated-type-specifier is ill-formed. 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 In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when elaborated type specifier is the implicit typedef created when
...@@ -11373,8 +11381,13 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -11373,8 +11381,13 @@ check_elaborated_type_specifier (enum tag_types tag_code,
&& !DECL_SELF_REFERENCE_P (decl) && !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type) && tag_code != typename_type)
{ {
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code)); if (alias_template_specialization_p (type))
error ("%q+D has a previous declaration here", decl); 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; return error_mark_node;
} }
else if (TREE_CODE (type) != RECORD_TYPE else if (TREE_CODE (type) != RECORD_TYPE
......
...@@ -13960,7 +13960,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ...@@ -13960,7 +13960,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL) else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
type = NULL_TREE; type = NULL_TREE;
else else
type = TREE_TYPE (decl); type = check_elaborated_type_specifier (tag_type, decl,
/*allow_template_p=*/true);
} }
if (!type) if (!type)
......
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> 2011-11-22 Tom de Vries <tom@codesourcery.com>
PR rtl-optimization/50764 PR rtl-optimization/50764
......
...@@ -3,16 +3,24 @@ ...@@ -3,16 +3,24 @@
template <class T> using Ptr = T*; template <class T> using Ptr = T*;
Ptr<unsigned>; // { dg-error "does not declare anything" } Ptr<unsigned>; // { dg-error "does not declare anything" }
Ptr<char><int>; // { dg-error "not a template|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; template <class T> using Arg = T;
struct A {}; 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 <template <class> class TT, class T> using Instantiate = TT<T>;
template <class> struct Vector {}; 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> struct S {};
template<class T> using SFor = S<T>; 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" }
// 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\]*;" }
...@@ -6,7 +6,7 @@ template<class T> using AS0 = S0<T>; ...@@ -6,7 +6,7 @@ template<class T> using AS0 = S0<T>;
template<template<class> class TT> template<template<class> class TT>
void f(TT<int>); 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 void
foo() foo()
......
//PR c++/29980 //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" } struct __attribute__((unused)) A::X; // { dg-error "typedef-name" }
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
// the definition of C. // the definition of C.
struct A; 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" } 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 C; // { dg-error "using typedef-name" }
struct D; struct D;
......
namespace Name { namespace Name {
typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" } typedef void *(*Function)( void *, int ); // { dg-message "previous declaration" }
struct Foo { struct Foo {
struct Function xyz[5]; // { dg-error "" } struct Function xyz[5]; // { dg-error "" }
......
...@@ -2,6 +2,6 @@ struct A {}; ...@@ -2,6 +2,6 @@ struct A {};
struct B struct B
{ {
typedef A T; // { dg-error "previous declaration" } typedef A T; // { dg-message "previous declaration" }
friend struct T; // { dg-error "" } friend struct T; // { dg-error "" }
}; };
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
// Origin: <wanderer@rsu.ru> // Origin: <wanderer@rsu.ru>
// { dg-do compile } // { dg-do compile }
typedef int A; // { dg-error "previous" } typedef int A; // { dg-message "previous" }
enum ::A {}; // { dg-error "typedef-name|expected unqualified-id" } enum ::A {}; // { dg-error "typedef-name|expected unqualified-id" }
// PR c++/6477 // 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" } typedef struct A B; // { dg-error "typedef|invalid type" }
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
// Origin: Travis J.I. Corcoran <tjic@permabit.com> // Origin: Travis J.I. Corcoran <tjic@permabit.com>
// { dg-do compile } // { 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" } struct A::Ptr; // { dg-error "typedef|not declare anything" }
...@@ -7,6 +7,6 @@ ...@@ -7,6 +7,6 @@
template<class T> class smart_ptr2 { template<class T> class smart_ptr2 {
T* real_ptr; T* real_ptr;
public: 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" } friend class td; // { dg-error "typedef|not name a class" }
}; };
namespace A 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" } class A::T x; // { dg-error "using typedef-name|invalid type" }
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
// PR c++/18471: ICE redeclaration of typedef as class template // 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" } template<X> struct X {}; // { dg-error "typedef-name" }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
template <int> struct A 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" } template <B> struct B {}; // { dg-error "not a valid type|typedef" }
}; };
......
...@@ -18,7 +18,7 @@ typedef I I; ...@@ -18,7 +18,7 @@ typedef I I;
//p3--cannot redefine to a different type in a given scope //p3--cannot redefine to a different type in a given scope
class complex2 { /* ... */ };// { dg-error "" } .* class complex2 { /* ... */ };// { dg-error "" } .*
typedef int complex2;// { dg-error "" } .* typedef int complex2;// { dg-error "" } .*
typedef int complex3;// { dg-error "" } .* typedef int complex3;// { dg-message "" } .*
class complex3 { /* ... */ };// { dg-error "" } .* class complex3 { /* ... */ };// { dg-error "" } .*
...@@ -37,7 +37,7 @@ struct S { ...@@ -37,7 +37,7 @@ struct S {
~S(); ~S();
}; };
typedef struct S T; // { dg-error "previous declaration" } typedef struct S T; // { dg-message "previous declaration" }
S a = T(); // OK S a = T(); // OK
struct T * p; // { dg-error "" } using typedef after struct struct T * p; // { dg-error "" } using typedef after struct
......
// { dg-do assemble } // { dg-do assemble }
// GROUPS passed error-messages // 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.* struct S { int member:1; }; // the lineno for this should be 2, not 0// { dg-error "" } conflicting types.*
// { dg-do assemble } // { dg-do assemble }
typedef struct {} S; // { dg-error "" } Previous declaration of S typedef struct {} S; // { dg-message "" } Previous declaration of S
S s1; S s1;
struct S* s2; // { dg-error "" } S is a typedef name struct S* s2; // { dg-error "" } S is a typedef name
......
...@@ -17,7 +17,7 @@ class X { ...@@ -17,7 +17,7 @@ class X {
class Y { class Y {
public: public:
typedef ::X W; // { dg-error "" } previous declaration typedef ::X W; // { dg-message "" } previous declaration
class Z; class Z;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment