1 // RUN: %clang_cc1 -triple x86_64-linux-gnu  -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14
2 
3 // expected-error@+1{{invalid option 'invalid' for cpu_dispatch}}
4 void __attribute__((cpu_dispatch(atom, invalid))) invalid_cpu();
5 
6 void __attribute__((cpu_specific(atom))) no_default(void);
7 void __attribute__((cpu_specific(sandybridge)))  no_default(void);
8 
9 struct MVReference {
10   int __attribute__((cpu_specific(sandybridge))) bar(void);
11   int __attribute__((cpu_specific(ivybridge))) bar(void);
12   int __attribute__((cpu_specific(sandybridge))) foo(void);
13 };
14 
use1(void)15 void use1(void){
16   // OK, will fail in the linker, unless another TU provides the cpu_dispatch.
17   no_default();
18 
19   // expected-error@+1 {{call to non-static member function without an object argument}}
20   +MVReference::bar;
21   // expected-error@+1 {{call to non-static member function without an object argument}}
22   +MVReference::foo;
23   // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}}
24   &MVReference::bar;
25   // expected-error@+1 {{reference to multiversioned function could not be resolved; did you mean to call it?}}
26   &MVReference::foo;
27 }
28 
29 //expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}}
30 constexpr int __attribute__((cpu_specific(sandybridge))) foo(void);
31 
32 int __attribute__((cpu_specific(sandybridge))) foo2(void);
33 //expected-error@+1 {{attribute 'cpu_specific' multiversioned functions do not yet support constexpr functions}}
34 constexpr int __attribute__((cpu_specific(ivybridge))) foo2(void);
35 
36 static int __attribute__((cpu_specific(sandybridge))) bar(void);
37 //expected-error@+1 {{multiversioned function declaration has a different linkage}}
bar(void)38 int __attribute__((cpu_dispatch(ivybridge))) bar(void) {}
39 
40 // OK
41 extern int __attribute__((cpu_specific(sandybridge))) bar2(void);
bar2(void)42 int __attribute__((cpu_dispatch(ivybridge))) bar2(void) {}
43 
44 namespace {
45 int __attribute__((cpu_specific(sandybridge))) bar3(void);
bar3(void)46 static int __attribute__((cpu_dispatch(ivybridge))) bar3(void) {}
47 }
48 
49 
50 inline int __attribute__((cpu_specific(sandybridge))) baz(void);
51 //expected-error@+1 {{multiversioned function declaration has a different inline specification}}
baz(void)52 int __attribute__((cpu_specific(ivybridge))) baz(void) {return 1;}
53 
54 void __attribute__((cpu_specific(atom))) diff_return(void);
55 //expected-error@+1 {{multiversioned function declaration has a different return type}}
56 int __attribute__((cpu_specific(sandybridge))) diff_return(void);
57 
58 int __attribute__((cpu_specific(atom))) diff_noexcept(void) noexcept(true);
59 //expected-error@+2 {{exception specification in declaration does not match previous declaration}}
60 //expected-note@-2 {{previous declaration is here}}
61 int __attribute__((cpu_specific(sandybridge))) diff_noexcept(void) noexcept(false);
62 
63 // FIXME: Add support for templates and virtual functions!
64 // expected-error@+2 {{multiversioned functions do not yet support function templates}}
65 template<typename T>
foo(T)66 int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
67 // expected-error@+2 {{multiversioned functions do not yet support function templates}}
68 template<typename T>
69 int __attribute__((cpu_specific(sandybridge))) foo2(T);
70 
71 struct S {
72   // expected-error@+2 {{multiversioned functions do not yet support function templates}}
73   template<typename T>
fooS74   int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
75 
76   // expected-error@+2 {{multiversioned functions do not yet support function templates}}
77   template<typename T>
foo2S78   int __attribute__((cpu_dispatch(ivybridge))) foo2(T) {}
79 
80   // expected-error@+1 {{multiversioned functions do not yet support virtual functions}}
81   virtual void __attribute__((cpu_specific(atom))) virt();
82 };
83 
84 extern "C" {
diff_mangle(void)85 int __attribute__((cpu_specific(atom))) diff_mangle(void) { return 0; }
86 }
87 //expected-error@+1 {{multiversioned function declaration has a different language linkage}}
diff_mangle(void)88 int __attribute__((cpu_specific(sandybridge))) diff_mangle(void) { return 0; }
89 
90 __attribute__((cpu_specific(atom))) void DiffDecl();
91 namespace N {
92 using ::DiffDecl;
93 // expected-error@+3 {{declaration conflicts with target of using declaration already in scope}}
94 // expected-note@-4 {{target of using declaration}}
95 // expected-note@-3 {{using declaration}}
96 __attribute__((cpu_dispatch(atom))) void DiffDecl();
97 } // namespace N
98 
99 struct SpecialFuncs {
100   // expected-error@+1 {{multiversioned functions do not yet support constructors}}
101   __attribute__((cpu_specific(atom))) SpecialFuncs();
102   // expected-error@+1 {{multiversioned functions do not yet support destructors}}
103   __attribute__((cpu_specific(atom))) ~SpecialFuncs();
104 
105   // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}}
106   SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(const SpecialFuncs&) = default;
107   // expected-error@+1 {{multiversioned functions do not yet support deleted functions}}
108   SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(SpecialFuncs&&) = delete;
109 };
110 
111 struct OutOfLine {
112   int __attribute__((cpu_specific(atom, ivybridge))) foo(int);
113 };
114 
foo(int)115 int __attribute__((cpu_specific(atom, ivybridge))) OutOfLine::foo(int) { return 0; }
foo(int)116 int __attribute__((cpu_specific(sandybridge))) OutOfLine::foo(int) { return 1; }
117 
118 // Ensure Cpp Spelling works.
CppSpelling()119 [[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){}
120 
121 // expected-error@+1 {{lambda cannot be declared 'cpu_dispatch'}}
__anon89a9bcda0202() 122 auto x = []() __attribute__((cpu_dispatch(atom))) {};
123