ms-uuid.cpp
5.81 KB
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}}
}