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 'ccce::S' is not contextually convertible to 'bool'}}
68     }
69 
70     constexpr S constexprS;
71     if constexpr (constexprS) { // expected-error {{value of type 'const ccce::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     } (0);
84   }
85 
g()86   template<typename T> void g() {
87     [](auto x) {
88       if constexpr (sizeof(T) == 1)
89         if constexpr (sizeof(x) == 1)
90           T::error(); // expected-error {{'::'}}
91     } (0);
92   }
93 
use()94   void use() {
95     f<int>(); // expected-note {{instantiation of}}
96     f<char>(); // expected-note {{instantiation of}}
97     g<int>(); // ok
98     g<char>(); // expected-note {{instantiation of}}
99   }
100 }
101 
102 namespace potentially_discarded_branch_target {
in_switch(int n)103   void in_switch(int n) {
104     switch (n)
105       case 4: if constexpr(sizeof(n) == 4) return;
106     if constexpr(sizeof(n) == 4)
107       switch (n) case 4: return;
108     switch (n) {
109       if constexpr (sizeof(n) == 4) // expected-note 2{{constexpr if}}
110         case 4: return; // expected-error {{cannot jump}}
111       else
112         default: break; // expected-error {{cannot jump}}
113     }
114   }
115 
116   template<typename T>
in_switch_tmpl(int n)117   void in_switch_tmpl(int n) {
118     switch (n) {
119       if constexpr (sizeof(T) == 4) // expected-note 2{{constexpr if}}
120         case 4: return; // expected-error {{cannot jump}}
121       else
122         default: break; // expected-error {{cannot jump}}
123     }
124   }
125 
goto_scope(int n)126   void goto_scope(int n) {
127     goto foo; // expected-error {{cannot jump}}
128     if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
129       foo: return;
130 bar:
131     if constexpr(sizeof(n) == 4)
132       goto bar; // ok
133   }
134 
135   template<typename T>
goto_scope(int n)136   void goto_scope(int n) {
137     goto foo; // expected-error {{cannot jump}}
138     if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}}
139       foo: return;
140 bar:
141     if constexpr(sizeof(n) == 4)
142       goto bar; // ok
143   }
144 
goto_redef(int n)145   void goto_redef(int n) {
146 a:  if constexpr(sizeof(n) == 4) // expected-error {{redefinition}} expected-note {{constexpr if}}
147       a: goto a; // expected-note 2{{previous}}
148     else
149       a: goto a; // expected-error {{redefinition}} expected-error {{cannot jump}}
150   }
151 
evil_things()152   void evil_things() {
153     goto evil_label; // expected-error {{cannot jump}}
154     if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}}
155 
156     if constexpr (true) // expected-note {{constexpr if}}
157       goto surprise; // expected-error {{cannot jump}}
158     else
159       surprise: {}
160   }
161 }
162 #endif
163