1 // RUN: %clang_cc1 %s -fopenacc -verify
2
3 struct NoBoolConversion{};
4 struct BoolConversion{
5 operator bool();
6 };
7
8 template <typename T, typename U>
BoolExpr()9 void BoolExpr() {
10 // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}}
11 #pragma acc parallel self (NoBoolConversion{})
12 while(0);
13 // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}}
14 // expected-note@#INST{{in instantiation of function template specialization}}
15 #pragma acc parallel self (T::NotValid)
16 while(0);
17
18 #pragma acc parallel self (BoolConversion{})
19 while(0);
20
21 // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}}
22 #pragma acc parallel self (T{})
23 while(0);
24
25 #pragma acc parallel self (U{})
26 while(0);
27 }
28
29 struct HasBool {
30 static constexpr bool B = true;
31 };
32
33 template<typename T>
WarnMaybeNotUsed()34 void WarnMaybeNotUsed() {
35 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
36 // expected-note@+1{{previous clause is here}}
37 #pragma acc parallel self if(T::B)
38 while(0);
39
40 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
41 // expected-note@+1{{previous clause is here}}
42 #pragma acc parallel self(T::B) if(T::B)
43 while(0);
44
45 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
46 // expected-note@+1{{previous clause is here}}
47 #pragma acc parallel if(T::B) self
48 while(0);
49
50 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
51 // expected-note@+1{{previous clause is here}}
52 #pragma acc parallel if(T::B) self(T::B)
53 while(0);
54
55 // We still warn in the cases of dependent failures, since the diagnostic
56 // happens immediately rather than during instantiation.
57
58 // expected-error@+4{{no member named 'Invalid' in 'HasBool'}}
59 // expected-note@#NOT_USED_INST{{in instantiation of function template specialization 'WarnMaybeNotUsed<HasBool>' requested here}}
60 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
61 // expected-note@+1{{previous clause is here}}
62 #pragma acc parallel self if(T::Invalid)
63 while(0);
64
65 // expected-error@+3{{no member named 'Invalid' in 'HasBool'}}
66 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
67 // expected-note@+1{{previous clause is here}}
68 #pragma acc parallel self(T::Invalid) if(T::B)
69 while(0);
70
71 // expected-error@+3{{no member named 'Invalid' in 'HasBool'}}
72 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
73 // expected-note@+1{{previous clause is here}}
74 #pragma acc parallel self(T::B) if(T::Invalid)
75 while(0);
76
77 // expected-error@+3{{no member named 'Invalid' in 'HasBool'}}
78 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
79 // expected-note@+1{{previous clause is here}}
80 #pragma acc parallel if(T::Invalid) self
81 while(0);
82
83 // expected-error@+3{{no member named 'Invalid' in 'HasBool'}}
84 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
85 // expected-note@+1{{previous clause is here}}
86 #pragma acc parallel if(T::Invalid) self(T::B)
87 while(0);
88
89 // expected-error@+3{{no member named 'Invalid' in 'HasBool'}}
90 // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}}
91 // expected-note@+1{{previous clause is here}}
92 #pragma acc parallel if(T::B) self(T::Invalid)
93 while(0);
94 }
95
Instantiate()96 void Instantiate() {
97 BoolExpr<NoBoolConversion, BoolConversion>(); // #INST
98 WarnMaybeNotUsed<HasBool>(); // #NOT_USED_INST
99 }
100