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