anonymous-struct.cpp
7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// 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];
} 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}}
}