blob: c177570682f6b5ce5ed74bb8743bd98cf278e4ee [file] [log] [blame]
Nico Weber469891e2017-05-05 17:05:56 +00001// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations
Nico Weberd60bbce2018-05-17 15:26:37 +00002// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations
Nico Weber88f5ed92016-09-13 18:55:26 +00003
4typedef struct _GUID {
5 unsigned long Data1;
6 unsigned short Data2;
7 unsigned short Data3;
8 unsigned char Data4[8];
9} GUID;
10
11namespace {
12// cl.exe's behavior with merging uuid attributes is a bit erratic:
13// * In []-style attributes, a single [] list must not list a duplicate uuid
14// (even if it's the same uuid), and only a single declaration of a class
15// must have a uuid else the compiler errors out (even if two declarations of
16// a class have the same uuid).
17// * For __declspec(uuid(...)), it's ok if several declarations of a class have
18// an uuid, as long as it's the same uuid each time. If uuids on declarations
19// don't match, the compiler errors out.
20// * If there are several __declspec(uuid(...))s on one declaration, the
21// compiler only warns about this and uses the last uuid. It even warns if
22// the uuids are the same.
23
24// clang-cl implements the following simpler (but largely compatible) behavior
25// instead:
26// * [] and __declspec uuids have the same behavior.
Hiroshi Inoue971514d2018-02-22 07:49:13 +000027// * If there are several uuids on a class (no matter if on the same decl or
Nico Weber88f5ed92016-09-13 18:55:26 +000028// on several decls), it is an error if they don't match.
29// * Having several uuids that match is ok.
30
31// Both cl and clang-cl accept this:
32class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1;
Nico Weberd58c2602016-09-14 01:16:54 +000033class __declspec(uuid("000000a0-0000-0000-c000-000000000049")) C1;
34class __declspec(uuid("{000000a0-0000-0000-C000-000000000049}")) C1;
Nico Weber88f5ed92016-09-13 18:55:26 +000035class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1 {};
36
37// Both cl and clang-cl error out on this:
38// expected-note@+1 2{{previous uuid specified here}}
39class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2;
40// expected-error@+1 {{uuid does not match previous declaration}}
41class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2;
42// expected-error@+1 {{uuid does not match previous declaration}}
43class __declspec(uuid("220000A0-0000-0000-C000-000000000049")) C2 {};
44
45// expected-note@+1 {{previous uuid specified here}}
46class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2_2;
47class C2_2;
48// expected-error@+1 {{uuid does not match previous declaration}}
49class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2;
50
51// clang-cl accepts this, but cl errors out:
52[uuid("000000A0-0000-0000-C000-000000000049")] class C3;
53[uuid("000000A0-0000-0000-C000-000000000049")] class C3;
54[uuid("000000A0-0000-0000-C000-000000000049")] class C3 {};
55
56// Both cl and clang-cl error out on this (but for different reasons):
57// expected-note@+1 2{{previous uuid specified here}}
58[uuid("000000A0-0000-0000-C000-000000000049")] class C4;
59// expected-error@+1 {{uuid does not match previous declaration}}
60[uuid("110000A0-0000-0000-C000-000000000049")] class C4;
61// expected-error@+1 {{uuid does not match previous declaration}}
62[uuid("220000A0-0000-0000-C000-000000000049")] class C4 {};
63
64// Both cl and clang-cl error out on this:
Michael Kruse41dd6ce2018-06-25 20:06:13 +000065// expected-error@+1 {{uuid does not match previous declaration}}
Michael Krusedc5ce722018-08-03 01:21:16 +000066class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
67// expected-note@+1 {{previous uuid specified here}}
Nico Weber88f5ed92016-09-13 18:55:26 +000068 __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5;
69
Michael Kruse41dd6ce2018-06-25 20:06:13 +000070// expected-error@+1 {{uuid does not match previous declaration}}
Michael Krusedc5ce722018-08-03 01:21:16 +000071[uuid("000000A0-0000-0000-C000-000000000049"),
72// expected-note@+1 {{previous uuid specified here}}
Nico Weber88f5ed92016-09-13 18:55:26 +000073 uuid("110000A0-0000-0000-C000-000000000049")] class C6;
74
75// cl doesn't diagnose having one uuid each as []-style attributes and as
76// __declspec, even if the uuids differ. clang-cl errors if they differ.
77[uuid("000000A0-0000-0000-C000-000000000049")]
78class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C7;
79
80// expected-note@+1 {{previous uuid specified here}}
81[uuid("000000A0-0000-0000-C000-000000000049")]
82// expected-error@+1 {{uuid does not match previous declaration}}
83class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C8;
84
85
86// cl warns on this, but clang-cl is fine with it (which is consistent with
87// e.g. specifying __multiple_inheritance several times, which cl accepts
88// without warning too).
89class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
90 __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C9;
91
92// cl errors out on this, but clang-cl is fine with it (to be consistent with
93// the previous case).
94[uuid("000000A0-0000-0000-C000-000000000049"),
95 uuid("000000A0-0000-0000-C000-000000000049")] class C10;
Nico Weberd60bbce2018-05-17 15:26:37 +000096
97template <const GUID* p>
98void F1() {
99 // Regression test for PR24986. The given GUID should just work as a pointer.
100 const GUID* q = p;
101}
102
103void F2() {
104 // The UUID should work for a non-type template parameter.
105 F1<&__uuidof(C1)>();
106}
107
Nico Weber88f5ed92016-09-13 18:55:26 +0000108}