|  | // RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s -Wno-deprecated-declarations | 
|  |  | 
|  | typedef struct _GUID { | 
|  | unsigned long Data1; | 
|  | unsigned short Data2; | 
|  | unsigned short Data3; | 
|  | unsigned char Data4[8]; | 
|  | } GUID; | 
|  |  | 
|  | namespace { | 
|  | // cl.exe supports [] attributes on decls like so: | 
|  | [uuid( "000000A0-0000-0000-C000-000000000049" )] struct struct_with_uuid; | 
|  |  | 
|  | // Optionally, the uuid can be surrounded by one set of braces. | 
|  | [uuid( | 
|  | "{000000A0-0000-0000-C000-000000000049}" | 
|  | )] struct struct_with_uuid_brace; | 
|  |  | 
|  | // uuids must be ascii string literals. | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(u8"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_u8; | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(L"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_L; | 
|  |  | 
|  | // cl.exe doesn't allow raw string literals in []-style attributes, but does | 
|  | // allow it for __declspec(uuid()) (u8 literals etc are not allowed there | 
|  | // either).  Since raw string literals not being allowed seems like an | 
|  | // implementation artifact in cl and not allowing them makes the parse code | 
|  | // a bit unnatural, do allow this. | 
|  | [uuid(R"(000000A0-0000-0000-C000-000000000049)")] struct struct_with_uuid_raw; | 
|  |  | 
|  | // Likewise, cl supports UCNs in declspec uuid, but not in []-style uuid. | 
|  | // clang-cl allows them in both. | 
|  | [uuid("000000A0-0000\u002D0000-C000-000000000049")] struct struct_with_uuid_ucn; | 
|  |  | 
|  | // cl doesn't allow string concatenation in []-style attributes, for no good | 
|  | // reason.  clang-cl allows them. | 
|  | [uuid("000000A0-00" "00-0000-C000-000000000049")] struct struct_with_uuid_split; | 
|  |  | 
|  | // expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} | 
|  | [uuid("{000000A0-0000-0000-C000-000000000049}", "1")] struct S {}; | 
|  | // expected-error@+1 {{expected '('}} | 
|  | [uuid{"000000A0-0000-0000-C000-000000000049"}] struct T {}; | 
|  | // expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} | 
|  | [uuid("000000A0-0000-0000-C000-000000000049"}] struct U {}; | 
|  |  | 
|  |  | 
|  | // In addition to uuids in string literals, cl also allows uuids that are not | 
|  | // in a string literal, only delimited by ().  The contents of () are almost | 
|  | // treated like a literal (spaces there aren't ignored), but macro substitution, | 
|  | // \ newline escapes, and so on are performed. | 
|  |  | 
|  | [ uuid (000000A0-0000-0000-C000-000000000049) ] struct struct_with_uuid2; | 
|  | [uuid({000000A0-0000-0000-C000-000000000049})] struct struct_with_uuid2_brace; | 
|  |  | 
|  | // The non-quoted form doesn't allow any whitespace inside the parens: | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid( 000000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2; | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(000000A0-0000 -0000-C000-000000000049)] struct struct_with_uuid2; | 
|  | // expected-error@+2 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(000000A0-0000 | 
|  | -0000-C000-000000000049)] struct struct_with_uuid2; | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(000000A0-0000/**/-0000-C000-000000000049)] struct struct_with_uuid2; | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(000000A0-0000-0000-C000-000000000049 )] struct struct_with_uuid2; | 
|  | // expected-error@+2 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(000000A0-0000-0000-C000-000000000049 | 
|  | ) | 
|  | ] struct struct_with_uuid2; | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid({000000A0-0000-""0000-C000-000000000049})] struct struct_with_uuid2; | 
|  |  | 
|  | // Line continuations and macro substitution are fine though: | 
|  | [uuid(000000A0-0000-0000-\ | 
|  | C000-000000000049)] struct struct_with_uuid2_cont; | 
|  | #define UUID 000000A0-0000-0000-C000-000000000049 | 
|  | #define UUID_PART 000000A0-0000 | 
|  | [uuid(UUID)] struct struct_with_uuid2_macro; | 
|  | [uuid(UUID_PART-0000-C000-000000000049)] struct struct_with_uuid2_macro_part; | 
|  |  | 
|  | // Both cl and clang-cl accept trigraphs here (with /Zc:trigraphs, off by | 
|  | // default) | 
|  | // expected-warning@+1 2{{trigraph converted}} | 
|  | [uuid(??<000000A0-0000-0000-C000-000000000049??>)] | 
|  | struct struct_with_uuid2_trigraph; | 
|  |  | 
|  | // UCNs cannot be used in this form because they're prohibited by C99. | 
|  | // expected-error@+1 {{character '-' cannot be specified by a universal character name}} | 
|  | [uuid(000000A0-0000\u002D0000-C000-000000000049)] struct struct_with_uuid2_ucn; | 
|  |  | 
|  | // Invalid digits. | 
|  | // expected-error@+1 {{uuid attribute contains a malformed GUID}} | 
|  | [uuid(0Z0000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2; | 
|  |  | 
|  | struct OuterClass { | 
|  | // [] uuids and inner classes are weird in cl.exe: It warns that uuid on | 
|  | // nested types has undefined behavior, and errors out __uuidof() claiming | 
|  | // that the inner type has no assigned uuid.  Things work fine if __declspec() | 
|  | // is used instead.  clang-cl handles this fine. | 
|  | [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass1; | 
|  | [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass2 {} ic; | 
|  | [uuid(10000000-0000-0000-0000-000000000000)] static class InnerClass3 {} sic; | 
|  | // Putting `static` in front of [...] causes parse errors in both cl and clang | 
|  |  | 
|  | // This is the only syntax to declare an inner class with []-style attributes | 
|  | // that works in cl: Declare the inner class without an attribute, and then | 
|  | // have the []-style attribute on the definition. | 
|  | class InnerClass; | 
|  | }; | 
|  | [uuid(10000000-0000-0000-0000-000000000000)] class OuterClass::InnerClass {}; | 
|  |  | 
|  | void use_it() { | 
|  | (void)__uuidof(struct_with_uuid); | 
|  | (void)__uuidof(struct_with_uuid_brace); | 
|  | (void)__uuidof(struct_with_uuid_raw); | 
|  | (void)__uuidof(struct_with_uuid_ucn); | 
|  | (void)__uuidof(struct_with_uuid_split); | 
|  |  | 
|  | (void)__uuidof(struct_with_uuid2); | 
|  | (void)__uuidof(struct_with_uuid2_brace); | 
|  | (void)__uuidof(struct_with_uuid2_cont); | 
|  | (void)__uuidof(struct_with_uuid2_macro); | 
|  | (void)__uuidof(struct_with_uuid2_macro_part); | 
|  | (void)__uuidof(struct_with_uuid2_trigraph); | 
|  |  | 
|  | (void)__uuidof(OuterClass::InnerClass); | 
|  | (void)__uuidof(OuterClass::InnerClass1); | 
|  | (void)__uuidof(OuterClass::InnerClass2); | 
|  | (void)__uuidof(OuterClass::InnerClass3); | 
|  | (void)__uuidof(OuterClass().ic); | 
|  | (void)__uuidof(OuterClass::sic); | 
|  | } | 
|  |  | 
|  | // expected-warning@+1 {{'uuid' attribute only applies to structs, unions, classes, and enums}} | 
|  | [uuid("000000A0-0000-0000-C000-000000000049")] void f(); | 
|  | } | 
|  |  | 
|  | // clang supports these on toplevel decls, but not on local decls since this | 
|  | // syntax is ambiguous with lambdas and Objective-C message send expressions. | 
|  | // This file documents clang's shortcomings and lists a few constructs that | 
|  | // one has to keep in mind when trying to fix this.  System headers only seem | 
|  | // to use these attributes on toplevel decls, so supporting this is not very | 
|  | // important. | 
|  |  | 
|  | void local_class() { | 
|  | // FIXME: MSVC accepts, but we reject due to ambiguity. | 
|  | // expected-error@+1 {{expected body of lambda expression}} | 
|  | [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd")] struct Local { | 
|  | int x; | 
|  | }; | 
|  | } | 
|  |  | 
|  | void useit(int); | 
|  | int lambda() { | 
|  | int uuid = 42; | 
|  | [uuid]() { useit(uuid); }(); | 
|  |  | 
|  | // C++14 lambda init captures: | 
|  | [uuid(00000000-0000-0000-0000-000000000000)] { return uuid; }(); | 
|  | [uuid("00000000-0000-0000-0000-000000000000")](int n) { return uuid[n]; }(3); | 
|  | } | 
|  |  | 
|  | @interface NSObject | 
|  | - (void)retain; | 
|  | @end | 
|  | int message_send(id uuid) { | 
|  | [uuid retain]; | 
|  | } | 
|  | NSObject* uuid(const char*); | 
|  | int message_send2() { | 
|  | [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd") retain]; | 
|  | } |