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
This commit is contained in:
parent
b64cd62a6e
commit
82daaf6d55
22 changed files with 97 additions and 27 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
|
|
14
gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
Normal file
|
@ -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\]*;" }
|
|
@ -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()
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 "" }
|
||||
|
|
|
@ -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 "" }
|
||||
};
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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" }
|
||||
};
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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" }
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue