2012-02-23 09:36:12 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// New exciting ambiguities in C++11
// final 'context sensitive' mess.
namespace final {
struct S { int n ; } ;
2012-03-12 16:56:40 +08:00
struct T { int n ; } ;
2012-02-23 09:36:12 +08:00
namespace N {
int n ;
2012-03-12 16:56:40 +08:00
// These declare variables named final..
extern struct S final ;
extern struct S final [ [ ] ] ;
extern struct S final , foo ;
struct S final = S ( ) ;
2012-02-23 09:36:12 +08:00
// This defines a class, not a variable, even though it would successfully
// parse as a variable but not as a class. DR1318's wording suggests that
// this disambiguation is only performed on an ambiguity, but that was not
// the intent.
2012-03-12 16:56:40 +08:00
struct S final { // expected-note {{here}}
2012-02-23 09:36:12 +08:00
int ( n ) // expected-error {{expected ';'}}
} ;
2012-03-12 16:56:40 +08:00
// This too.
struct T final : S { } ; // expected-error {{base 'S' is marked 'final'}}
2012-03-12 23:39:49 +08:00
struct T bar : S { } ; // expected-error {{expected ';' after top level declarator}} expected-error {{expected unqualified-id}}
2012-02-23 09:36:12 +08:00
}
2013-02-22 14:46:23 +08:00
// _Alignas isn't allowed in the places where alignas is. We used to
// assert on this.
struct U final _Alignas ( 4 ) { } ; // expected-error 3{{}} expected-note {{}}
2012-02-23 09:36:12 +08:00
}
Fix parsing of enum-base to follow C++11 rules.
Previously we implemented non-standard disambiguation rules to
distinguish an enum-base from a bit-field but otherwise treated a :
after an elaborated-enum-specifier as introducing an enum-base. That
misparses various examples (anywhere an elaborated-type-specifier can
appear followed by a colon, such as within a ternary operator or
_Generic).
We now implement the C++11 rules, with the old cases accepted as
extensions where that seemed reasonable. These amount to:
* an enum-base must always be accompanied by an enum definition (except
in a standalone declaration of the form 'enum E : T;')
* in a member-declaration, 'enum E :' always introduces an enum-base,
never a bit-field
* in a type-specifier (or similar context), 'enum E :' is not
permitted; the colon means whatever else it would mean in that
context.
Fixed underlying types for enums are also permitted in Objective-C and
under MS extensions, plus as a language extension in all other modes.
The behavior in ObjC and MS extensions modes is unchanged (but the
bit-field disambiguation is a bit better); remaining language modes
follow the C++11 rules.
Fixes PR45726, PR39979, PR19810, PR44941, and most of PR24297, plus C++
core issues 1514 and 1966.
2020-05-09 10:24:18 +08:00
// enum versus bitfield. These are always required to be treated as an
// enum-base, but we disambiguate anyway for better error recovery.
2012-02-23 09:36:12 +08:00
namespace bitfield {
enum E { } ;
struct T {
constexpr T ( ) { }
constexpr T ( int ) { }
constexpr T ( T , T , T , T ) { }
2013-04-21 09:08:50 +08:00
constexpr T operator = ( T ) const { return * this ; }
constexpr operator int ( ) const { return 4 ; }
2012-02-23 09:36:12 +08:00
} ;
constexpr T a , b , c , d ;
struct S1 {
Fix parsing of enum-base to follow C++11 rules.
Previously we implemented non-standard disambiguation rules to
distinguish an enum-base from a bit-field but otherwise treated a :
after an elaborated-enum-specifier as introducing an enum-base. That
misparses various examples (anywhere an elaborated-type-specifier can
appear followed by a colon, such as within a ternary operator or
_Generic).
We now implement the C++11 rules, with the old cases accepted as
extensions where that seemed reasonable. These amount to:
* an enum-base must always be accompanied by an enum definition (except
in a standalone declaration of the form 'enum E : T;')
* in a member-declaration, 'enum E :' always introduces an enum-base,
never a bit-field
* in a type-specifier (or similar context), 'enum E :' is not
permitted; the colon means whatever else it would mean in that
context.
Fixed underlying types for enums are also permitted in Objective-C and
under MS extensions, plus as a language extension in all other modes.
The behavior in ObjC and MS extensions modes is unchanged (but the
bit-field disambiguation is a bit better); remaining language modes
follow the C++11 rules.
Fixes PR45726, PR39979, PR19810, PR44941, and most of PR24297, plus C++
core issues 1514 and 1966.
2020-05-09 10:24:18 +08:00
enum E : T ( a = 1 , b = 2 , c = 3 , 4 ) ; // expected-error {{ISO C++ only allows ':' in member enumeration declaration to introduce a fixed underlying type, not an anonymous bit-field}}
2012-02-23 09:36:12 +08:00
} ;
Fix parsing of enum-base to follow C++11 rules.
Previously we implemented non-standard disambiguation rules to
distinguish an enum-base from a bit-field but otherwise treated a :
after an elaborated-enum-specifier as introducing an enum-base. That
misparses various examples (anywhere an elaborated-type-specifier can
appear followed by a colon, such as within a ternary operator or
_Generic).
We now implement the C++11 rules, with the old cases accepted as
extensions where that seemed reasonable. These amount to:
* an enum-base must always be accompanied by an enum definition (except
in a standalone declaration of the form 'enum E : T;')
* in a member-declaration, 'enum E :' always introduces an enum-base,
never a bit-field
* in a type-specifier (or similar context), 'enum E :' is not
permitted; the colon means whatever else it would mean in that
context.
Fixed underlying types for enums are also permitted in Objective-C and
under MS extensions, plus as a language extension in all other modes.
The behavior in ObjC and MS extensions modes is unchanged (but the
bit-field disambiguation is a bit better); remaining language modes
follow the C++11 rules.
Fixes PR45726, PR39979, PR19810, PR44941, and most of PR24297, plus C++
core issues 1514 and 1966.
2020-05-09 10:24:18 +08:00
// Enum definition, not a bit-field.
2012-02-23 09:36:12 +08:00
struct S2 {
2013-12-31 14:26:03 +08:00
enum E : T { a = 1 , b = 2 , c = 3 , 4 } ; // expected-error {{non-integral type}} expected-error {{expected identifier}}
2012-02-23 09:36:12 +08:00
} ;
struct S3 {
enum E : int { a = 1 , b = 2 , c = 3 , d } ; // ok, defines an enum
} ;
// Ambiguous.
struct S4 {
enum E : int { a = 1 } ; // ok, defines an enum
} ;
// This could be a bit-field, but would be ill-formed due to the anonymous
// member being initialized.
struct S5 {
2012-06-26 05:37:02 +08:00
enum E : int { a = 1 } { b = 2 } ; // expected-error {{expected ';' after enum}} expected-error {{expected member name}}
2012-02-23 09:36:12 +08:00
} ;
// This could be a bit-field.
struct S6 {
2013-12-31 14:26:03 +08:00
enum E : int { 1 } ; // expected-error {{expected identifier}}
2012-02-23 09:36:12 +08:00
} ;
struct U {
2013-04-21 09:08:50 +08:00
constexpr operator T ( ) const { return T ( ) ; } // expected-note 2{{candidate}}
2012-02-23 09:36:12 +08:00
} ;
// This could be a bit-field.
struct S7 {
enum E : int { a = U ( ) } ; // expected-error {{no viable conversion}}
} ;
// This could be a bit-field, and does not conform to the grammar of an
// enum definition, because 'id(U())' is not a constant-expression.
constexpr const U & id ( const U & u ) { return u ; }
struct S8 {
enum E : int { a = id ( U ( ) ) } ; // expected-error {{no viable conversion}}
} ;
2020-05-11 04:14:51 +08:00
// PR26249: Disambiguate 'enum :' as an enum-base always, even if that would
// be ill-formed. It cannot be an elaborated-type-specifier.
struct S {
enum : undeclared_type { v = 0 } ; // expected-error {{unknown type name 'undeclared_type'}}
2020-05-11 04:39:23 +08:00
enum E : undeclared_type { w = 0 } ; // expected-error {{unknown type name 'undeclared_type'}}
enum X : undeclared_type { x = 0 } ; // expected-error {{unknown type name 'undeclared_type'}}
2020-05-11 04:14:51 +08:00
} ;
2012-02-23 09:36:12 +08:00
}
namespace trailing_return {
typedef int n ;
int a ;
struct S {
S ( int ) ;
2012-07-24 05:41:30 +08:00
S * operator ( ) ( . . . ) const ;
2012-02-23 09:36:12 +08:00
int n ;
} ;
namespace N {
void f ( ) {
// This parses as a function declaration, but DR1223 makes the presence of
// 'auto' be used for disambiguation.
S ( a ) ( ) - > n ; // ok, expression; expected-warning{{expression result unused}}
2012-07-24 05:41:30 +08:00
S ( a ) ( int ( ) ) - > n ; // ok, expression; expected-warning{{expression result unused}}
2012-02-23 09:36:12 +08:00
auto ( a ) ( ) - > n ; // ok, function declaration
2012-07-24 05:41:30 +08:00
auto ( b ) ( int ( ) ) - > n ; // ok, function declaration
2012-02-23 09:36:12 +08:00
using T = decltype ( a ) ;
using T = auto ( ) - > n ;
}
}
}
2012-03-28 07:05:05 +08:00
namespace ellipsis {
template < typename . . . T >
struct S {
2017-01-20 05:00:13 +08:00
void e ( S : : S ( ) ) ; // expected-error {{is a constructor name}}
2015-01-17 10:33:17 +08:00
void f ( S ( . . . args [ sizeof ( T ) ] ) ) ; // expected-note {{here}} expected-note {{here}}
void f ( S ( . . . args ) [ sizeof ( T ) ] ) ; // expected-error {{redeclared}}
2012-03-28 07:05:05 +08:00
void f ( S . . . args [ sizeof ( T ) ] ) ; // expected-error {{redeclared}}
2013-02-21 04:19:27 +08:00
void g ( S ( . . . [ sizeof ( T ) ] ) ) ; // expected-note {{here}} expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
2012-03-28 07:05:05 +08:00
void g ( S ( . . . ) [ sizeof ( T ) ] ) ; // expected-error {{function cannot return array type}}
void g ( S . . . [ sizeof ( T ) ] ) ; // expected-error {{redeclared}}
void h ( T ( . . . ) ) ; // function type, expected-error {{unexpanded parameter pack}}
void h ( T . . . ) ; // pack expansion, ok
void i ( int ( T . . . ) ) ; // expected-note {{here}}
void i ( int ( T . . . a ) ) ; // expected-error {{redeclared}}
void i ( int ( T , . . . ) ) ; // function type, expected-error {{unexpanded parameter pack}}
void i ( int ( T , . . . a ) ) ; // expected-error {{expected ')'}} expected-note {{to match}} expected-error {{unexpanded parameter pack}}
void j ( int ( int . . . ) ) ; // function type, ok
void j ( int ( int . . . a ) ) ; // expected-error {{does not contain any unexpanded parameter packs}}
void j ( T ( int . . . ) ) ; // expected-error {{unexpanded parameter pack}}
void j ( T ( T . . . ) ) ; // expected-error {{unexpanded parameter pack}}
void k ( int ( . . . ) ( T ) ) ; // expected-error {{cannot return function type}}
void k ( int . . . ( T ) ) ;
2013-02-21 04:19:27 +08:00
void l ( int ( & . . . ) ( T ) ) ; // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
void l ( int ( * . . . ) ( T ) ) ; // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
void l ( int ( S < int > : : * . . . ) ( T ) ) ; // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
2012-03-28 07:05:05 +08:00
} ;
2017-05-20 08:21:55 +08:00
struct CtorSink {
template < typename . . . T > constexpr CtorSink ( T & & . . . t ) { }
constexpr operator int ( ) const { return 42 ; }
} ;
template < unsigned . . . N > struct UnsignedTmplArgSink ;
template < typename . . . T >
void foo ( int x , T . . . t ) {
// Have a variety of cases where the syntax is technically unambiguous, but hinges on careful treatment of ellipses.
CtorSink ( t . . . ) , x ; // ok, expression; expected-warning 2{{expression result unused}}
int x0 ( CtorSink ( t . . . ) ) ; // ok, declares object x0
int * p0 = & x0 ;
( void ) p0 ;
CtorSink x1 ( int ( t ) . . . , int ( x ) ) ; // ok, declares object x1
CtorSink * p1 = & x1 ;
( void ) p1 ;
UnsignedTmplArgSink < T ( CtorSink ( t . . . ) ) . . . > * t0 ; // ok
UnsignedTmplArgSink < ( ( T * ) 0 , 42u ) . . . > * * t0p = & t0 ;
}
template void foo ( int , int , int ) ; // expected-note {{in instantiation of function template specialization 'ellipsis::foo<int, int>' requested here}}
2012-03-28 07:05:05 +08:00
}
2013-03-20 11:35:02 +08:00
namespace braced_init_list {
struct X {
void foo ( ) { }
} ;
void ( * pf1 ) ( ) { } ;
void ( X : : * pmf1 ) ( ) { & X : : foo } ;
void ( X : : * pmf2 ) ( ) = { & X : : foo } ;
void test ( ) {
void ( * pf2 ) ( ) { } ;
void ( X : : * pmf3 ) ( ) { & X : : foo } ;
void ( X : : * pmf4 ) ( ) = { & X : : foo } ;
}
}