xref: /llvm-project/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp (revision 20219106060208f0c2f5d096eb3aed7b712f5067)
1 // RUN: %clang_cc1 -std=c++1z -verify %s
2 // RUN: %clang_cc1 -std=c++1z -verify %s -DUNDEFINED
3 
4 #ifdef UNDEFINED
5 // "used but not defined" errors don't get produced if we have more interesting
6 // errors.
7 namespace std_example {
g(T && p,Rest &&...rs)8   template <typename T, typename... Rest> void g(T &&p, Rest &&... rs) {
9     // use p
10     if constexpr(sizeof...(rs) > 0)
11       g(rs...);
12   }
use_g()13   void use_g() {
14     g(1, 2, 3);
15   }
16 
17   static int x(); // no definition of x required
f()18   int f() {
19     if constexpr (true)
20       return 0;
21     else if (x())
22       return x();
23     else
24       return -x();
25   }
26 }
27 
28 namespace odr_use_in_selected_arm {
29   static int x(); // expected-warning {{is not defined}}
f()30   int f() {
31     if constexpr (false)
32       return 0;
33     else if (x()) // expected-note {{here}}
34       return x();
35     else
36       return -x();
37   }
38 }
39 #else
40 namespace ccce {
41 
42   struct S {
43   };
f()44   void f() {
45     if (5) {}
46     if constexpr (5) {
47     }
48   }
g()49   template<int N> void g() {
50     if constexpr (N) {
51     }
52   }
53   template void g<5>();
h()54   void h() {
55     if constexpr (4.3) { //expected-warning {{implicit conversion from 'double' to 'bool' changes value}}
56     }
57     constexpr void *p = nullptr;
58     if constexpr (p) {
59     }
60   }
61 
not_constant(int b,S s)62   void not_constant(int b, S s) { //  expected-note 2{{declared here}}
63     if constexpr (bool(b)) {      // expected-error {{constexpr if condition is not a constant expression}} expected-note {{cannot be used in a constant expression}}
64     }
65     if constexpr (b) { // expected-error {{constexpr if condition is not a constant expression}} expected-note {{cannot be used in a constant expression}}
66     }
67     if constexpr (s) { // expected-error {{value of type 'S' is not contextually convertible to 'bool'}}
68     }
69 
70     constexpr S constexprS;
71     if constexpr (constexprS) { // expected-error {{value of type 'const S' is not contextually convertible to 'bool'}}
72     }
73   }
74 }
75 
76 namespace generic_lambda {
77   // Substituting for T produces a hard error here, even if substituting for
78   // the type of x would remove the error.
f()79   template<typename T> void f() {
80     [](auto x) {
81       if constexpr (sizeof(T) == 1 && sizeof(x) == 1)
82         T::error(); // expected-error 2{{'::'}}
83                     // expected-note@-3 2{{while substituting into a lambda expression here}}
84     } (0);
85   }
86 
g()87   template<typename T> void g() {
88     [](auto x) {
89       if constexpr (sizeof(T) == 1)
90         if constexpr (sizeof(x) == 1)
91           T::error(); // expected-error {{'::'}}
92                       // expected-note@-4 {{while substituting into a lambda expression here}}
93     } (0);
94   }
95 
use()96   void use() {
97     f<int>(); // expected-note {{instantiation of}}
98     f<char>(); // expected-note {{instantiation of}}
99     g<int>(); // ok
100     g<char>(); // expected-note {{instantiation of}}
101   }
102 }
103 
104 namespace potentially_discarded_branch_target {
in_switch(int n)105   void in_switch(int n) {
106     switch (n)
107       case 4: if constexpr(sizeof(n) == 4) return;
108     if constexpr(sizeof(n) == 4)
109       switch (n) case 4: return;
110     switch (n) {
111       if constexpr (sizeof(n) == 4) // expected-note 2{{constexpr if}}
112         case 4: return; // expected-error {{cannot jump}}
113       else
114         default: break; // expected-error {{cannot jump}}
115     }
116   }
117 
118   template<typename T>
in_switch_tmpl(int n)119   void in_switch_tmpl(int n) {
120     switch (n) {
121       if constexpr (sizeof(T) == 4) // expected-note 2{{constexpr if}}
122         case 4: return; // expected-error {{cannot jump}}
123       else
124         default: break; // expected-error {{cannot jump}}
125     }
126   }
127 
goto_scope(int n)128   void goto_scope(int n) {
129     goto foo; // expected-error {{cannot jump}}
130     if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
131       foo: return;
132 bar:
133     if constexpr(sizeof(n) == 4)
134       goto bar; // ok
135   }
136 
137   template<typename T>
goto_scope(int n)138   void goto_scope(int n) {
139     goto foo; // expected-error {{cannot jump}}
140     if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
141       foo: return;
142 bar:
143     if constexpr(sizeof(n) == 4)
144       goto bar; // ok
145   }
146 
goto_redef(int n)147   void goto_redef(int n) {
148 a:  if constexpr(sizeof(n) == 4) // expected-error {{redefinition}} expected-note {{constexpr if}}
149       a: goto a; // expected-note 2{{previous}}
150     else
151       a: goto a; // expected-error {{redefinition}} expected-error {{cannot jump}}
152   }
153 
evil_things()154   void evil_things() {
155     goto evil_label; // expected-error {{cannot jump}}
156     if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}} \
157                                                      // expected-note {{jump enters a statement expression}}
158 
159     if constexpr (true) // expected-note {{constexpr if}}
160       goto surprise; // expected-error {{cannot jump}}
161     else
162       surprise: {}
163   }
164 }
165 
166 namespace deduced_return_type_in_discareded_statement {
167 
168 template <typename T>
a(const T & t)169 auto a(const T &t) {
170   return t;
171 }
172 
f()173 void f() {
174   if constexpr (false) {
175     a(a(0));
176   }
177 }
178 } // namespace deduced_return_type_in_discareded_statement
179 
180 #endif
181