186 lines
7.3 KiB
C++
186 lines
7.3 KiB
C++
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
|
||
|
|
||
|
struct S {
|
||
|
S();
|
||
|
#if __cplusplus <= 199711L
|
||
|
// expected-note@-2 {{because type 'S' has a user-provided default constructor}}
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
struct { // expected-error {{anonymous structs and classes must be class members}} expected-warning {{does not declare anything}}
|
||
|
};
|
||
|
|
||
|
struct E {
|
||
|
struct {
|
||
|
S x;
|
||
|
#if __cplusplus <= 199711L
|
||
|
// expected-error@-2 {{anonymous struct member 'x' has a non-trivial default constructor}}
|
||
|
#endif
|
||
|
};
|
||
|
static struct { // expected-warning {{does not declare anything}}
|
||
|
};
|
||
|
class {
|
||
|
int anon_priv_field; // expected-error {{anonymous struct cannot contain a private data member}}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
template <class T> void foo(T);
|
||
|
typedef struct { // expected-error {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration after its linkage was computed; add a tag name here to establish linkage prior to definition}}
|
||
|
#if __cplusplus <= 199711L
|
||
|
// expected-note@-2 {{declared here}}
|
||
|
#endif
|
||
|
|
||
|
void test() { // expected-note {{type is not C-compatible due to this member declaration}}
|
||
|
foo(this);
|
||
|
#if __cplusplus <= 199711L
|
||
|
// expected-warning@-2 {{template argument uses unnamed type}}
|
||
|
#endif
|
||
|
}
|
||
|
} A; // expected-note {{type is given name 'A' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
int x = 0; // expected-note {{type is not C-compatible due to this default member initializer}} expected-warning 0-1{{extension}}
|
||
|
} B; // expected-note {{type is given name 'B' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
: B { // expected-note {{type is not C-compatible due to this base class}}
|
||
|
} C; // expected-note {{type is given name 'C' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
#if __cplusplus > 201703L
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
static_assert([]{ return true; }()); // expected-note {{type is not C-compatible due to this lambda expression}}
|
||
|
} Lambda1; // expected-note {{type is given name 'Lambda1' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
template<int> struct X {};
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
X<[]{ return 0; }()> x; // expected-note {{type is not C-compatible due to this lambda expression}}
|
||
|
// FIXME: expected-error@-1 {{lambda expression cannot appear}}
|
||
|
} Lambda2; // expected-note {{type is given name 'Lambda2' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
enum E {
|
||
|
a = []{ return 1; }() // expected-note {{type is not C-compatible due to this lambda expression}}
|
||
|
};
|
||
|
} Lambda3; // expected-note {{type is given name 'Lambda3' for linkage purposes by this typedef declaration}}
|
||
|
#endif
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
template<int> void f() {} // expected-note {{type is not C-compatible due to this member declaration}}
|
||
|
} Template; // expected-note {{type is given name 'Template' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
struct U {
|
||
|
void f(); // expected-note {{type is not C-compatible due to this member declaration}}
|
||
|
};
|
||
|
} Nested; // expected-note {{type is given name 'Nested' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
friend void f() {} // expected-note {{type is not C-compatible due to this friend declaration}}
|
||
|
} Friend; // expected-note {{type is given name 'Friend' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
|
||
|
template<typename T> friend void f() {} // expected-note {{type is not C-compatible due to this friend declaration}}
|
||
|
} FriendTemplate; // expected-note {{type is given name 'FriendTemplate' for linkage purposes by this typedef declaration}}
|
||
|
|
||
|
// Check that we don't diagnose the permitted cases:
|
||
|
typedef struct {
|
||
|
// (non-members)
|
||
|
_Static_assert(true, "");
|
||
|
int : 0;
|
||
|
/*empty-declaration*/;
|
||
|
|
||
|
// non-static data members
|
||
|
int a;
|
||
|
// member enumerations
|
||
|
enum E { x, y, z };
|
||
|
// member classes
|
||
|
struct S {};
|
||
|
|
||
|
// recursively
|
||
|
struct T { int a; };
|
||
|
} OK;
|
||
|
|
||
|
// There are still some known permitted cases that require an early linkage
|
||
|
// computation. Ensure we diagnose those too.
|
||
|
namespace ValidButUnsupported {
|
||
|
#if __cplusplus >= 201402L
|
||
|
template<typename T> auto compute_linkage() {
|
||
|
static int n;
|
||
|
return &n;
|
||
|
}
|
||
|
|
||
|
typedef struct { // expected-error {{unsupported: anonymous type given name for linkage purposes by typedef declaration after its linkage was computed; add a tag name here to establish linkage}}
|
||
|
struct X {};
|
||
|
decltype(compute_linkage<X>()) a;
|
||
|
} A; // expected-note {{by this typedef declaration}}
|
||
|
#endif
|
||
|
|
||
|
// This fails in some language modes but not others.
|
||
|
template<typename T> struct Y {
|
||
|
static const int value = 10;
|
||
|
};
|
||
|
typedef struct { // expected-error 0-1{{unsupported}}
|
||
|
enum X {};
|
||
|
int arr[Y<X>::value];
|
||
|
} B; // expected-note 0-1{{by this typedef}}
|
||
|
|
||
|
template<typename T> void f() {}
|
||
|
typedef struct { // expected-error {{unsupported}}
|
||
|
enum X {};
|
||
|
int arr[&f<X> ? 1 : 2];
|
||
|
#if __cplusplus < 201103L
|
||
|
// expected-warning@-2 {{folded to constant}}
|
||
|
#endif
|
||
|
} C; // expected-note {{by this typedef}}
|
||
|
}
|
||
|
|
||
|
namespace ImplicitDecls {
|
||
|
struct Destructor {
|
||
|
~Destructor() {}
|
||
|
};
|
||
|
typedef struct {
|
||
|
} Empty;
|
||
|
|
||
|
typedef struct {
|
||
|
Destructor x;
|
||
|
} A;
|
||
|
|
||
|
typedef struct {
|
||
|
Empty E;
|
||
|
} B;
|
||
|
|
||
|
typedef struct {
|
||
|
const Empty E;
|
||
|
} C;
|
||
|
} // namespace ImplicitDecls
|
||
|
|
||
|
struct {
|
||
|
static int x; // expected-error {{static data member 'x' not allowed in anonymous struct}}
|
||
|
} static_member_1;
|
||
|
|
||
|
class {
|
||
|
struct A {
|
||
|
static int x; // expected-error {{static data member 'x' not allowed in anonymous class}}
|
||
|
} x;
|
||
|
} static_member_2;
|
||
|
|
||
|
union {
|
||
|
struct A {
|
||
|
struct B {
|
||
|
static int x; // expected-error {{static data member 'x' not allowed in anonymous union}}
|
||
|
} x;
|
||
|
} x;
|
||
|
} static_member_3;
|
||
|
|
||
|
// Ensure we don't compute the linkage of a member function just because it
|
||
|
// happens to have the same name as a builtin.
|
||
|
namespace BuiltinName {
|
||
|
// Note that this is not an error: we didn't trigger linkage computation in this example.
|
||
|
typedef struct { // expected-warning {{anonymous non-C-compatible type}}
|
||
|
void memcpy(); // expected-note {{due to this member}}
|
||
|
} A; // expected-note {{given name 'A' for linkage purposes by this typedef}}
|
||
|
}
|