1// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s -Wno-deprecated-declarations
2
3typedef struct _GUID {
4  unsigned long Data1;
5  unsigned short Data2;
6  unsigned short Data3;
7  unsigned char Data4[8];
8} GUID;
9
10namespace {
11// cl.exe supports [] attributes on decls like so:
12[uuid( "000000A0-0000-0000-C000-000000000049" )] struct struct_with_uuid;
13
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;
18
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;
24
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;
31
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;
35
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;
39
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 {};
46
47
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.
52
53[ uuid (000000A0-0000-0000-C000-000000000049) ] struct struct_with_uuid2;
54[uuid({000000A0-0000-0000-C000-000000000049})] struct struct_with_uuid2_brace;
55
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
70)
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;
74
75// Line continuations and macro substitution are fine though:
76[uuid(000000A0-0000-0000-\
77C000-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;
82
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??>)]
87struct struct_with_uuid2_trigraph;
88
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;
92
93// Invalid digits.
94// expected-error@+1 {{uuid attribute contains a malformed GUID}}
95[uuid(0Z0000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2;
96
97struct 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
106
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;
111};
112[uuid(10000000-0000-0000-0000-000000000000)] class OuterClass::InnerClass {};
113
114void 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);
120
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);
127
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);
134}
135
136// expected-warning@+1 {{'uuid' attribute only applies to structs, unions, classes, and enums}}
137[uuid("000000A0-0000-0000-C000-000000000049")] void f();
138}
139
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.
146
147void 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  };
153}
154
155void useit(int);
156int lambda() {
157  int uuid = 42;
158  [uuid]() { useit(uuid); }();
159
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);
163}
164
165@interface NSObject
166- (void)retain;
167@end
168int message_send(id uuid) {
169  [uuid retain];
170}
171NSObject* uuid(const char*);
172int message_send2() {
173  [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd") retain];
174}
175