137 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations2// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter3// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations4// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter5 6typedef struct _GUID {7 __UINT32_TYPE__ Data1;8 __UINT16_TYPE__ Data2;9 __UINT16_TYPE__ Data3;10 __UINT8_TYPE__ Data4[8];11} GUID;12 13namespace {14// cl.exe's behavior with merging uuid attributes is a bit erratic:15// * In []-style attributes, a single [] list must not list a duplicate uuid16// (even if it's the same uuid), and only a single declaration of a class17// must have a uuid else the compiler errors out (even if two declarations of18// a class have the same uuid).19// * For __declspec(uuid(...)), it's ok if several declarations of a class have20// an uuid, as long as it's the same uuid each time. If uuids on declarations21// don't match, the compiler errors out.22// * If there are several __declspec(uuid(...))s on one declaration, the23// compiler only warns about this and uses the last uuid. It even warns if24// the uuids are the same.25 26// clang-cl implements the following simpler (but largely compatible) behavior27// instead:28// * [] and __declspec uuids have the same behavior.29// * If there are several uuids on a class (no matter if on the same decl or30// on several decls), it is an error if they don't match.31// * Having several uuids that match is ok.32 33// Both cl and clang-cl accept this:34class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1;35class __declspec(uuid("000000a0-0000-0000-c000-000000000049")) C1;36class __declspec(uuid("{000000a0-0000-0000-C000-000000000049}")) C1;37class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1 {};38 39// Both cl and clang-cl error out on this:40// expected-note@+1 2{{previous uuid specified here}}41class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2;42// expected-error@+1 {{uuid does not match previous declaration}}43class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2;44// expected-error@+1 {{uuid does not match previous declaration}}45class __declspec(uuid("220000A0-0000-0000-C000-000000000049")) C2 {};46 47// expected-note@+1 {{previous uuid specified here}}48class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2_2;49class C2_2;50// expected-error@+1 {{uuid does not match previous declaration}}51class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2;52 53// clang-cl accepts this, but cl errors out:54[uuid("000000A0-0000-0000-C000-000000000049")] class C3;55[uuid("000000A0-0000-0000-C000-000000000049")] class C3;56[uuid("000000A0-0000-0000-C000-000000000049")] class C3 {};57 58// Both cl and clang-cl error out on this (but for different reasons):59// expected-note@+1 2{{previous uuid specified here}}60[uuid("000000A0-0000-0000-C000-000000000049")] class C4;61// expected-error@+1 {{uuid does not match previous declaration}}62[uuid("110000A0-0000-0000-C000-000000000049")] class C4;63// expected-error@+1 {{uuid does not match previous declaration}}64[uuid("220000A0-0000-0000-C000-000000000049")] class C4 {};65 66// Both cl and clang-cl error out on this:67// expected-error@+1 {{uuid does not match previous declaration}}68class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))69// expected-note@+1 {{previous uuid specified here}}70 __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5;71 72// expected-error@+1 {{uuid does not match previous declaration}}73[uuid("000000A0-0000-0000-C000-000000000049"),74// expected-note@+1 {{previous uuid specified here}}75 uuid("110000A0-0000-0000-C000-000000000049")] class C6;76 77// cl doesn't diagnose having one uuid each as []-style attributes and as78// __declspec, even if the uuids differ. clang-cl errors if they differ.79[uuid("000000A0-0000-0000-C000-000000000049")]80class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C7;81 82// expected-note@+1 {{previous uuid specified here}}83[uuid("000000A0-0000-0000-C000-000000000049")]84// expected-error@+1 {{uuid does not match previous declaration}}85class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C8;86 87 88// cl warns on this, but clang-cl is fine with it (which is consistent with89// e.g. specifying __multiple_inheritance several times, which cl accepts90// without warning too).91class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))92 __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C9;93 94// cl errors out on this, but clang-cl is fine with it (to be consistent with95// the previous case).96[uuid("000000A0-0000-0000-C000-000000000049"),97 uuid("000000A0-0000-0000-C000-000000000049")] class C10;98 99template <const GUID* p>100void F1() {101 // Regression test for PR24986. The given GUID should just work as a pointer.102 const GUID* q = p;103}104 105void F2() {106 // The UUID should work for a non-type template parameter.107 F1<&__uuidof(C1)>();108}109 110}111 112// Test class/struct redeclaration where the subsequent113// declaration has a uuid attribute114struct X{};115 116struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) X;117 118namespace ConstantEvaluation {119 class __declspec(uuid("1babb1ed-feed-c01d-1ced-decafc0ffee5")) Request;120 constexpr GUID a = __uuidof(Request);121 static_assert(a.Data1 == 0x1babb1ed, "");122 static_assert(__uuidof(Request).Data1 == 0x1babb1ed, "");123 static_assert(a.Data2 == 0xfeed, "");124 static_assert(__uuidof(Request).Data2 == 0xfeed, "");125 static_assert(a.Data3 == 0xc01d, "");126 static_assert(__uuidof(Request).Data3 == 0xc01d, "");127 static_assert(a.Data4[0] == 0x1c, "");128 static_assert(__uuidof(Request).Data4[0] == 0x1c, "");129 static_assert(a.Data4[1] == 0xed, "");130 static_assert(__uuidof(Request).Data4[1] == 0xed, "");131 static_assert(a.Data4[2] == 0xde, "");132 static_assert(__uuidof(Request).Data4[2] == 0xde, "");133 static_assert(a.Data4[7] == 0xe5, "");134 static_assert(__uuidof(Request).Data4[7] == 0xe5, "");135 constexpr int k = __uuidof(Request).Data4[8]; // expected-error {{constant expression}} expected-note {{past-the-end}}136}137