xref: /llvm-project/clang/test/SemaCXX/anonymous-struct.cpp (revision 84a3aadf0f2483dde0acfc4e79f2a075a5f35bd1)
1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
4 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
5 
6 struct S {
7   S();
8 #if __cplusplus <= 199711L
9   // expected-note@-2 {{because type 'S' has a user-provided default constructor}}
10 #endif
11 };
12 
13 struct { // expected-error {{anonymous structs and classes must be class members}} expected-warning {{does not declare anything}}
14 };
15 
16 struct E {
17   struct {
18     S x;
19 #if __cplusplus <= 199711L
20     // expected-error@-2 {{anonymous struct member 'x' has a non-trivial default constructor}}
21 #endif
22   };
23   static struct { // expected-warning {{does not declare anything}}
24   };
25   class {
26     int anon_priv_field; // expected-error {{anonymous struct cannot contain a private data member}}
27   };
28 };
29 
30 template <class T> void foo(T);
31 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}}
32 #if __cplusplus <= 199711L
33 // expected-note@-2 {{declared here}}
34 #endif
35 
test__anon6c201779050836   void test() { // expected-note {{type is not C-compatible due to this member declaration}}
37     foo(this);
38 #if __cplusplus <= 199711L
39     // expected-warning@-2 {{template argument uses unnamed type}}
40 #endif
41   }
42 } A; // expected-note {{type is given name 'A' for linkage purposes by this typedef declaration}}
43 
44 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
45   int x = 0; // expected-note {{type is not C-compatible due to this default member initializer}} expected-warning 0-1{{extension}}
46 } B; // expected-note {{type is given name 'B' for linkage purposes by this typedef declaration}}
47 
48 typedef struct // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
49 : B { // expected-note {{type is not C-compatible due to this base class}}
50 } C; // expected-note {{type is given name 'C' for linkage purposes by this typedef declaration}}
51 
52 #if __cplusplus > 201703L && __cplusplus < 202002L
53 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
__anon6c2017790902__anon6c201779080854   static_assert([]{ return true; }()); // expected-note {{type is not C-compatible due to this lambda expression}}
55 } Lambda1; // expected-note {{type is given name 'Lambda1' for linkage purposes by this typedef declaration}}
56 
57 template<int> struct X {};
58 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
__anon6c2017790b02__anon6c2017790a0859   X<[]{ return 0; }()> x; // expected-note {{type is not C-compatible due to this lambda expression}}
60   // FIXME: expected-error@-1 {{lambda expression cannot appear}}
61 } Lambda2; // expected-note {{type is given name 'Lambda2' for linkage purposes by this typedef declaration}}
62 
63 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
64   enum E {
__anon6c2017790d02null65     a = []{ return 1; }() // expected-note {{type is not C-compatible due to this lambda expression}}
66   };
67 } Lambda3; // expected-note {{type is given name 'Lambda3' for linkage purposes by this typedef declaration}}
68 #endif
69 
70 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
f__anon6c2017790e0871   template<int> void f() {} // expected-note {{type is not C-compatible due to this member declaration}}
72 } Template; // expected-note {{type is given name 'Template' for linkage purposes by this typedef declaration}}
73 
74 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
75   struct U {
76     void f(); // expected-note {{type is not C-compatible due to this member declaration}}
77   };
78 } Nested; // expected-note {{type is given name 'Nested' for linkage purposes by this typedef declaration}}
79 
80 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
f()81   friend void f() {} // expected-note {{type is not C-compatible due to this friend declaration}}
82 } Friend; // expected-note {{type is given name 'Friend' for linkage purposes by this typedef declaration}}
83 
84 typedef struct { // expected-warning {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration; add a tag name here}}
f()85   template<typename T> friend void f() {} // expected-note {{type is not C-compatible due to this friend declaration}}
86 } FriendTemplate; // expected-note {{type is given name 'FriendTemplate' for linkage purposes by this typedef declaration}}
87 
88 // Check that we don't diagnose the permitted cases:
89 typedef struct {
90   // (non-members)
91   _Static_assert(true, "");
92   int : 0;
93   /*empty-declaration*/;
94 
95   // non-static data members
96   int a;
97   // member enumerations
98   enum E { x, y, z };
99   // member classes
100   struct S {};
101 
102   // recursively
103   struct T { int a; };
104 } OK;
105 
106 // There are still some known permitted cases that require an early linkage
107 // computation. Ensure we diagnose those too.
108 namespace ValidButUnsupported {
109 #if __cplusplus >= 201402L
compute_linkage()110   template<typename T> auto compute_linkage() {
111     static int n;
112     return &n;
113   }
114 
115   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}}
116     struct X {};
117     decltype(compute_linkage<X>()) a;
118   } A; // expected-note {{by this typedef declaration}}
119 #endif
120 
121   // This fails in some language modes but not others.
122   template<typename T> struct Y {
123     static const int value = 10;
124   };
125   typedef struct { // expected-error 0-1{{unsupported}}
126     enum X {};
127     int arr[Y<X>::value];
128   } B; // expected-note 0-1{{by this typedef}}
129 
f()130   template<typename T> void f() {}
131   typedef struct { // expected-error {{unsupported}}
132     enum X {};
133     int arr[&f<X> ? 1 : 2];
134 #if __cplusplus < 201103L
135     // expected-warning@-2 {{folded to constant}}
136     // expected-warning@-3 {{variable length arrays in C++ are a Clang extension}}
137 #endif
138   } C; // expected-note {{by this typedef}}
139 }
140 
141 namespace ImplicitDecls {
142 struct Destructor {
~DestructorImplicitDecls::Destructor143   ~Destructor() {}
144 };
145 typedef struct {
146 } Empty;
147 
148 typedef struct {
149   Destructor x;
150 } A;
151 
152 typedef struct {
153   Empty E;
154 } B;
155 
156 typedef struct {
157   const Empty E;
158 } C;
159 } // namespace ImplicitDecls
160 
161 struct {
162   static int x; // expected-error {{static data member 'x' not allowed in anonymous struct}}
163 } static_member_1;
164 
165 class {
166   struct A {
167     static int x; // expected-error {{static data member 'x' not allowed in anonymous class}}
168   } x;
169 } static_member_2;
170 
171 union {
172   struct A {
173     struct B {
174       static int x; // expected-error {{static data member 'x' not allowed in anonymous union}}
175     } x;
176   } x;
177 } static_member_3;
178 
179 // Ensure we don't compute the linkage of a member function just because it
180 // happens to have the same name as a builtin.
181 namespace BuiltinName {
182   // Note that this is not an error: we didn't trigger linkage computation in this example.
183   typedef struct { // expected-warning {{anonymous non-C-compatible type}}
184     void memcpy(); // expected-note {{due to this member}}
185   } A; // expected-note {{given name 'A' for linkage purposes by this typedef}}
186 }
187 namespace inline_defined_static_member {
188 typedef struct { // expected-warning {{anonymous non-C-compatible type}}
finline_defined_static_member::__anon6c2017791e08189   static void f() { // expected-note {{due to this member}}
190   }
191 } A; // expected-note {{given name 'A' for linkage purposes by this typedef}}
192 }
193 
194 #if __cplusplus > 201103L
195 namespace GH58800 {
196 struct A {
197   union {
198     struct {
199       float red = 0.0f;
200     };
201   };
202 };
203 
GetA()204 A GetA() {
205   A result{};
206   return result;
207 }
208 }
209 #endif
210