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)169auto a(const T &t) { 170 return t; 171 } 172 f()173void f() { 174 if constexpr (false) { 175 a(a(0)); 176 } 177 } 178 } // namespace deduced_return_type_in_discareded_statement 179 180 #endif 181