1 // RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -fcxx-exceptions -verify
2 
3 struct S1 {
4   void f() [[clang::annotate_type("foo")]];
5   // FIXME: We would want to prohibit the attribute in the following location.
6   // However, Clang currently generally doesn't prohibit type-only C++11
7   // attributes on declarations. This should be fixed more generally.
8   [[clang::annotate_type("foo")]] void g();
9 };
10 
11 template <typename T1, typename T2> struct is_same {
12   static constexpr bool value = false;
13 };
14 
15 template <typename T1> struct is_same<T1, T1> {
16   static constexpr bool value = true;
17 };
18 
19 static_assert(is_same<int, int [[clang::annotate_type("foo")]]>::value);
20 static_assert(is_same<int [[clang::annotate_type("foo")]],
21                       int [[clang::annotate_type("bar")]]>::value);
22 static_assert(is_same<int *, int *[[clang::annotate_type("foo")]]>::value);
23 
24 // Cannot overload on types that only differ by `annotate_type` attribute.
25 void f(int) {} // expected-note {{previous definition is here}}
26 void f(int [[clang::annotate_type("foo")]]) {} // expected-error {{redefinition of 'f'}}
27 
28 // Cannot specialize on types that only differ by `annotate_type` attribute.
29 template <class T> struct S2 {};
30 
31 template <> struct S2<int> {}; // expected-note {{previous definition is here}}
32 
33 template <>
34 struct S2<int [[clang::annotate_type("foo")]]> {}; // expected-error {{redefinition of 'S2<int>'}}
35 
36 // Test that the attribute supports parameter pack expansion.
37 template <int... Is> void variadic_func_template() {
38   int [[clang::annotate_type("foo", Is...)]] val;
39 }
40 int f2() { variadic_func_template<1, 2, 3>(); }
41 
42 // Make sure we correctly diagnose wrong number of arguments for
43 // [[clang::annotate_type]] inside a template argument.
44 template <typename Ty> void func_template();
45 void f3() {
46   func_template<int [[clang::annotate_type()]]>(); // expected-error {{'annotate_type' attribute takes at least 1 argument}}
47 }
48 
49 // More error cases: Prohibit adding the attribute to declarations.
50 // Different declarations hit different code paths, so they need separate tests.
51 // FIXME: Clang currently generally doesn't prohibit type-only C++11
52 // attributes on declarations.
53 namespace [[clang::annotate_type("foo")]] my_namespace {}
54 struct [[clang::annotate_type("foo")]] S3;
55 struct [[clang::annotate_type("foo")]] S3{
56   [[clang::annotate_type("foo")]] int member;
57 };
58 void f4() {
59   for ([[clang::annotate_type("foo")]] int i = 0; i < 42; ++i) {}
60   for (; [[clang::annotate_type("foo")]] bool b = false;) {}
61   while ([[clang::annotate_type("foo")]] bool b = false) {}
62   if ([[clang::annotate_type("foo")]] bool b = false) {}
63   try {
64   } catch ([[clang::annotate_type("foo")]] int i) {
65   }
66 }
67 template <class T>
68 [[clang::annotate_type("foo")]] T var_template;
69 [[clang::annotate_type("foo")]] extern "C" int extern_c_func();
70 extern "C" [[clang::annotate_type("foo")]] int extern_c_func();
71