[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Parser / ms-square-bracket-attributes.mm
blobc1fc14cec563d3c6df40a39209b7a1c48a2a0e6e
1 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s -Wno-deprecated-declarations
3 typedef struct _GUID {
4   unsigned long Data1;
5   unsigned short Data2;
6   unsigned short Data3;
7   unsigned char Data4[8];
8 } GUID;
10 namespace {
11 // cl.exe supports [] attributes on decls like so:
12 [uuid( "000000A0-0000-0000-C000-000000000049" )] struct struct_with_uuid;
14 // Optionally, the uuid can be surrounded by one set of braces.
15 [uuid(
16   "{000000A0-0000-0000-C000-000000000049}"
17 )] struct struct_with_uuid_brace;
19 // uuids must be ascii string literals.
20 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
21 [uuid(u8"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_u8;
22 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
23 [uuid(L"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_L;
25 // cl.exe doesn't allow raw string literals in []-style attributes, but does
26 // allow it for __declspec(uuid()) (u8 literals etc are not allowed there
27 // either).  Since raw string literals not being allowed seems like an
28 // implementation artifact in cl and not allowing them makes the parse code
29 // a bit unnatural, do allow this.
30 [uuid(R"(000000A0-0000-0000-C000-000000000049)")] struct struct_with_uuid_raw;
32 // Likewise, cl supports UCNs in declspec uuid, but not in []-style uuid.
33 // clang-cl allows them in both.
34 [uuid("000000A0-0000\u002D0000-C000-000000000049")] struct struct_with_uuid_ucn;
36 // cl doesn't allow string concatenation in []-style attributes, for no good
37 // reason.  clang-cl allows them.
38 [uuid("000000A0-00" "00-0000-C000-000000000049")] struct struct_with_uuid_split;
40 // expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
41 [uuid("{000000A0-0000-0000-C000-000000000049}", "1")] struct S {};
42 // expected-error@+1 {{expected '('}}
43 [uuid{"000000A0-0000-0000-C000-000000000049"}] struct T {};
44 // expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
45 [uuid("000000A0-0000-0000-C000-000000000049"}] struct U {};
48 // In addition to uuids in string literals, cl also allows uuids that are not
49 // in a string literal, only delimited by ().  The contents of () are almost
50 // treated like a literal (spaces there aren't ignored), but macro substitution,
51 // \ newline escapes, and so on are performed.
53 [ uuid (000000A0-0000-0000-C000-000000000049) ] struct struct_with_uuid2;
54 [uuid({000000A0-0000-0000-C000-000000000049})] struct struct_with_uuid2_brace;
56 // The non-quoted form doesn't allow any whitespace inside the parens:
57 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
58 [uuid( 000000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2;
59 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
60 [uuid(000000A0-0000 -0000-C000-000000000049)] struct struct_with_uuid2;
61 // expected-error@+2 {{uuid attribute contains a malformed GUID}}
62 [uuid(000000A0-0000
63 -0000-C000-000000000049)] struct struct_with_uuid2;
64 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
65 [uuid(000000A0-0000/**/-0000-C000-000000000049)] struct struct_with_uuid2;
66 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
67 [uuid(000000A0-0000-0000-C000-000000000049 )] struct struct_with_uuid2;
68 // expected-error@+2 {{uuid attribute contains a malformed GUID}}
69 [uuid(000000A0-0000-0000-C000-000000000049
71 ] struct struct_with_uuid2;
72 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
73 [uuid({000000A0-0000-""0000-C000-000000000049})] struct struct_with_uuid2;
75 // Line continuations and macro substitution are fine though:
76 [uuid(000000A0-0000-0000-\
77 C000-000000000049)] struct struct_with_uuid2_cont;
78 #define UUID 000000A0-0000-0000-C000-000000000049
79 #define UUID_PART 000000A0-0000
80 [uuid(UUID)] struct struct_with_uuid2_macro;
81 [uuid(UUID_PART-0000-C000-000000000049)] struct struct_with_uuid2_macro_part;
83 // Both cl and clang-cl accept trigraphs here (with /Zc:trigraphs, off by
84 // default)
85 // expected-warning@+1 2{{trigraph converted}}
86 [uuid(??<000000A0-0000-0000-C000-000000000049??>)]
87 struct struct_with_uuid2_trigraph;
89 // UCNs cannot be used in this form because they're prohibited by C99.
90 // expected-error@+1 {{character '-' cannot be specified by a universal character name}}
91 [uuid(000000A0-0000\u002D0000-C000-000000000049)] struct struct_with_uuid2_ucn;
93 // Invalid digits.
94 // expected-error@+1 {{uuid attribute contains a malformed GUID}}
95 [uuid(0Z0000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2;
97 struct OuterClass {
98   // [] uuids and inner classes are weird in cl.exe: It warns that uuid on
99   // nested types has undefined behavior, and errors out __uuidof() claiming
100   // that the inner type has no assigned uuid.  Things work fine if __declspec()
101   // is used instead.  clang-cl handles this fine.
102   [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass1;
103   [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass2 {} ic;
104   [uuid(10000000-0000-0000-0000-000000000000)] static class InnerClass3 {} sic;
105   // Putting `static` in front of [...] causes parse errors in both cl and clang
107   // This is the only syntax to declare an inner class with []-style attributes
108   // that works in cl: Declare the inner class without an attribute, and then
109   // have the []-style attribute on the definition.
110   class InnerClass;
112 [uuid(10000000-0000-0000-0000-000000000000)] class OuterClass::InnerClass {};
114 void use_it() {
115   (void)__uuidof(struct_with_uuid);
116   (void)__uuidof(struct_with_uuid_brace);
117   (void)__uuidof(struct_with_uuid_raw);
118   (void)__uuidof(struct_with_uuid_ucn);
119   (void)__uuidof(struct_with_uuid_split);
121   (void)__uuidof(struct_with_uuid2);
122   (void)__uuidof(struct_with_uuid2_brace);
123   (void)__uuidof(struct_with_uuid2_cont);
124   (void)__uuidof(struct_with_uuid2_macro);
125   (void)__uuidof(struct_with_uuid2_macro_part);
126   (void)__uuidof(struct_with_uuid2_trigraph);
128   (void)__uuidof(OuterClass::InnerClass);
129   (void)__uuidof(OuterClass::InnerClass1);
130   (void)__uuidof(OuterClass::InnerClass2);
131   (void)__uuidof(OuterClass::InnerClass3);
132   (void)__uuidof(OuterClass().ic);
133   (void)__uuidof(OuterClass::sic);
136 // expected-warning@+1 {{'uuid' attribute only applies to structs, unions, classes, and enums}}
137 [uuid("000000A0-0000-0000-C000-000000000049")] void f();
140 // clang supports these on toplevel decls, but not on local decls since this
141 // syntax is ambiguous with lambdas and Objective-C message send expressions.
142 // This file documents clang's shortcomings and lists a few constructs that
143 // one has to keep in mind when trying to fix this.  System headers only seem
144 // to use these attributes on toplevel decls, so supporting this is not very
145 // important.
147 void local_class() {
148   // FIXME: MSVC accepts, but we reject due to ambiguity.
149   // expected-error@+1 {{expected body of lambda expression}}
150   [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd")] struct Local {
151     int x;
152   };
155 void useit(int);
156 int lambda() {
157   int uuid = 42;
158   [uuid]() { useit(uuid); }();
160   // C++14 lambda init captures:
161   [uuid(00000000-0000-0000-0000-000000000000)] { return uuid; }();
162   [uuid("00000000-0000-0000-0000-000000000000")](int n) { return uuid[n]; }(3);
165 @interface NSObject
166 - (void)retain;
167 @end
168 int message_send(id uuid) {
169   [uuid retain]; 
171 NSObject* uuid(const char*);
172 int message_send2() {
173   [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd") retain];