1 // RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -verify
2 // RUN: %clang_cc1 %s -DPEDANTIC -pedantic -fsyntax-only -verify
3 
4 #if PEDANTIC
g()5 void g() {
6   if (true)
7     [[likely]] {} // expected-warning {{use of the 'likely' attribute is a C++20 extension}}
8   else
9     [[unlikely]] {} // expected-warning {{use of the 'unlikely' attribute is a C++20 extension}}
10 }
11 #else
a()12 void a() {
13   if (true)
14     [[likely]]; // expected-warning {{conflicting attributes 'likely' are ignored}}
15   else
16     [[likely]]; // expected-note {{conflicting attribute is here}}
17 }
18 
b()19 void b() {
20   if (true)
21     [[unlikely]]; // expected-warning {{conflicting attributes 'unlikely' are ignored}}
22   else
23     [[unlikely]]; // expected-note {{conflicting attribute is here}}
24 }
25 
c()26 void c() {
27   if (true)
28     [[likely]];
29 }
30 
d()31 void d() {
32   if (true)
33     [[unlikely]];
34 }
35 
g()36 void g() {
37   if (true)
38     [[likely]] {}
39   else
40     [[unlikely]] {}
41 }
42 
h()43 void h() {
44   if (true)
45     [[likely]] {}
46   else {
47   }
48 }
49 
i()50 void i() {
51   if (true)
52     [[unlikely]] {}
53   else {
54   }
55 }
56 
j()57 void j() {
58   if (true) {
59   } else
60     [[likely]] {}
61 }
62 
k()63 void k() {
64   if (true) {
65   } else
66     [[likely]] {}
67 }
68 
l()69 void l() {
70   if (true)
71     [[likely]] {}
72   else
73     [[unlikely]] if (false) [[likely]] {}
74 }
75 
m()76 void m() {
77   [[likely]] int x = 42; // expected-error {{'likely' attribute cannot be applied to a declaration}}
78 
79   if (x)
80     [[unlikely]] {}
81   if (x) {
82     [[unlikely]];
83   }
84   switch (x) {
85   case 1:
86     [[likely]] {}
87     break;
88     [[likely]] case 2 : case 3 : {}
89     break;
90   }
91 
92   do {
93     [[unlikely]];
94   } while (x);
95   do
96     [[unlikely]] {}
97   while (x);
98   do { // expected-note {{to match this 'do'}}
99   }
100   [[unlikely]] while (x); // expected-error {{expected 'while' in do/while loop}}
101   for (;;)
102     [[unlikely]] {}
103   for (;;) {
104     [[unlikely]];
105   }
106   while (x)
107     [[unlikely]] {}
108   while (x) {
109     [[unlikely]];
110   }
111 
112   switch (x)
113     [[unlikely]] {}
114 
115   if (x)
116     goto lbl;
117 
118   // FIXME: allow the attribute on the label
119   [[unlikely]] lbl : // expected-error {{'unlikely' attribute cannot be applied to a declaration}}
120                      [[likely]] x = x + 1;
121 
122   [[likely]]++ x;
123 }
124 
n()125 void n() [[likely]] // expected-error {{'likely' attribute cannot be applied to types}}
126 {
127   try
128     [[likely]] {} // expected-error {{expected '{'}}
129   catch (...) [[likely]] { // expected-error {{expected expression}}
130   }
131 }
132 
o()133 void o()
134 {
135   // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}}
136   // expected-note@+1 {{annotating the 'if constexpr' statement here}}
137   if constexpr (true) [[likely]];
138 
139   // expected-note@+1 {{annotating the 'if constexpr' statement here}}
140   if constexpr (true) {
141   // expected-warning@+1 {{attribute 'unlikely' has no effect when annotating an 'if constexpr' statement}}
142   } else [[unlikely]];
143 
144   // Annotating both branches with conflicting likelihoods generates no diagnostic regarding the conflict.
145   // expected-warning@+2 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}}
146   // expected-note@+1 2 {{annotating the 'if constexpr' statement here}}
147   if constexpr (true) [[likely]] {
148   // expected-warning@+1 {{attribute 'likely' has no effect when annotating an 'if constexpr' statement}}
149   } else [[likely]];
150 
151   if (1) [[likely, unlikely]] { // expected-error {{'unlikely' and 'likely' attributes are not compatible}} \
152                                 // expected-note {{conflicting attribute is here}}
153   } else [[unlikely]][[likely]] { // expected-error {{'likely' and 'unlikely' attributes are not compatible}} \
154                                   // expected-note {{conflicting attribute is here}}
155   }
156 }
157 #endif
158