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 storage class}}
bar(void)38 int __attribute__((cpu_dispatch(ivybridge))) bar(void) {}
39 
40 inline int __attribute__((cpu_specific(sandybridge))) baz(void);
41 //expected-error@+1 {{multiversioned function declaration has a different inline specification}}
baz(void)42 int __attribute__((cpu_specific(ivybridge))) baz(void) {return 1;}
43 
44 void __attribute__((cpu_specific(atom))) diff_return(void);
45 //expected-error@+1 {{multiversioned function declaration has a different return type}}
46 int __attribute__((cpu_specific(sandybridge))) diff_return(void);
47 
48 int __attribute__((cpu_specific(atom))) diff_noexcept(void) noexcept(true);
49 //expected-error@+2 {{exception specification in declaration does not match previous declaration}}
50 //expected-note@-2 {{previous declaration is here}}
51 int __attribute__((cpu_specific(sandybridge))) diff_noexcept(void) noexcept(false);
52 
53 // FIXME: Add support for templates and virtual functions!
54 // expected-error@+2 {{multiversioned functions do not yet support function templates}}
55 template<typename T>
foo(T)56 int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
57 // expected-error@+2 {{multiversioned functions do not yet support function templates}}
58 template<typename T>
59 int __attribute__((cpu_specific(sandybridge))) foo2(T);
60 
61 struct S {
62   // expected-error@+2 {{multiversioned functions do not yet support function templates}}
63   template<typename T>
fooS64   int __attribute__((cpu_specific(atom))) foo(T) { return 0; }
65 
66   // expected-error@+2 {{multiversioned functions do not yet support function templates}}
67   template<typename T>
foo2S68   int __attribute__((cpu_dispatch(ivybridge))) foo2(T) {}
69 
70   // expected-error@+1 {{multiversioned functions do not yet support virtual functions}}
71   virtual void __attribute__((cpu_specific(atom))) virt();
72 };
73 
74 extern "C" {
diff_mangle(void)75 int __attribute__((cpu_specific(atom))) diff_mangle(void) { return 0; }
76 }
77 //expected-error@+1 {{multiversioned function declaration has a different linkage}}
diff_mangle(void)78 int __attribute__((cpu_specific(sandybridge))) diff_mangle(void) { return 0; }
79 
80 __attribute__((cpu_specific(atom))) void DiffDecl();
81 namespace N {
82 using ::DiffDecl;
83 // expected-error@+3 {{declaration conflicts with target of using declaration already in scope}}
84 // expected-note@-4 {{target of using declaration}}
85 // expected-note@-3 {{using declaration}}
86 __attribute__((cpu_dispatch(atom))) void DiffDecl();
87 } // namespace N
88 
89 struct SpecialFuncs {
90   // expected-error@+1 {{multiversioned functions do not yet support constructors}}
91   __attribute__((cpu_specific(atom))) SpecialFuncs();
92   // expected-error@+1 {{multiversioned functions do not yet support destructors}}
93   __attribute__((cpu_specific(atom))) ~SpecialFuncs();
94 
95   // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}}
96   SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(const SpecialFuncs&) = default;
97   // expected-error@+1 {{multiversioned functions do not yet support deleted functions}}
98   SpecialFuncs& __attribute__((cpu_specific(atom))) operator=(SpecialFuncs&&) = delete;
99 };
100 
101 struct OutOfLine {
102   int __attribute__((cpu_specific(atom, ivybridge))) foo(int);
103 };
104 
foo(int)105 int __attribute__((cpu_specific(atom, ivybridge))) OutOfLine::foo(int) { return 0; }
foo(int)106 int __attribute__((cpu_specific(sandybridge))) OutOfLine::foo(int) { return 1; }
107 
108 // Ensure Cpp Spelling works.
CppSpelling()109 [[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){}
110 
111 // expected-error@+1 {{lambda cannot be declared 'cpu_dispatch'}}
__anon687a92af0102() 112 auto x = []() __attribute__((cpu_dispatch(atom))) {};
113