brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · 6c4923d Raw
175 lines · plain
1// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s -Wno-deprecated-declarations2 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-warning@+1 {{encoding prefix 'u8' on an unevaluated string literal has no effect and is incompatible with c++2c}}21[uuid(u8"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_u8;22// expected-warning@+1 {{encoding prefix 'L' on an unevaluated string literal has no effect and is incompatible with c++2c}}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 does26// allow it for __declspec(uuid()) (u8 literals etc are not allowed there27// either).  Since raw string literals not being allowed seems like an28// implementation artifact in cl and not allowing them makes the parse code29// 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 good37// 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 not49// in a string literal, only delimited by ().  The contents of () are almost50// 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-000063-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-00000000004970)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-00000000004979#define UUID_PART 000000A0-000080[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 by84// 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 on99  // nested types has undefined behavior, and errors out __uuidof() claiming100  // 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 clang106 107  // This is the only syntax to declare an inner class with []-style attributes108  // that works in cl: Declare the inner class without an attribute, and then109  // 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 this141// syntax is ambiguous with lambdas and Objective-C message send expressions.142// This file documents clang's shortcomings and lists a few constructs that143// one has to keep in mind when trying to fix this.  System headers only seem144// to use these attributes on toplevel decls, so supporting this is not very145// 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 NSObject166- (void)retain;167@end168int 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