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