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