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 { f()41 void f() { 42 if (5) {} 43 if constexpr (5) {} // expected-error {{cannot be narrowed}} 44 } g()45 template<int N> void g() { 46 if constexpr (N) {} // expected-error {{cannot be narrowed}} 47 } 48 template void g<5>(); // expected-note {{instantiation of}} 49 } 50 51 namespace generic_lambda { 52 // Substituting for T produces a hard error here, even if substituting for 53 // the type of x would remove the error. f()54 template<typename T> void f() { 55 [](auto x) { 56 if constexpr (sizeof(T) == 1 && sizeof(x) == 1) 57 T::error(); // expected-error 2{{'::'}} 58 } (0); 59 } 60 g()61 template<typename T> void g() { 62 [](auto x) { 63 if constexpr (sizeof(T) == 1) 64 if constexpr (sizeof(x) == 1) 65 T::error(); // expected-error {{'::'}} 66 } (0); 67 } 68 use()69 void use() { 70 f<int>(); // expected-note {{instantiation of}} 71 f<char>(); // expected-note {{instantiation of}} 72 g<int>(); // ok 73 g<char>(); // expected-note {{instantiation of}} 74 } 75 } 76 77 namespace potentially_discarded_branch_target { in_switch(int n)78 void in_switch(int n) { 79 switch (n) 80 case 4: if constexpr(sizeof(n) == 4) return; 81 if constexpr(sizeof(n) == 4) 82 switch (n) case 4: return; 83 switch (n) { 84 if constexpr (sizeof(n) == 4) // expected-note 2{{constexpr if}} 85 case 4: return; // expected-error {{cannot jump}} 86 else 87 default: break; // expected-error {{cannot jump}} 88 } 89 } 90 91 template<typename T> in_switch_tmpl(int n)92 void in_switch_tmpl(int n) { 93 switch (n) { 94 if constexpr (sizeof(T) == 4) // expected-note 2{{constexpr if}} 95 case 4: return; // expected-error {{cannot jump}} 96 else 97 default: break; // expected-error {{cannot jump}} 98 } 99 } 100 goto_scope(int n)101 void goto_scope(int n) { 102 goto foo; // expected-error {{cannot jump}} 103 if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}} 104 foo: return; 105 bar: 106 if constexpr(sizeof(n) == 4) 107 goto bar; // ok 108 } 109 110 template<typename T> goto_scope(int n)111 void goto_scope(int n) { 112 goto foo; // expected-error {{cannot jump}} 113 if constexpr(sizeof(n) == 4) // expected-note {{constexpr if}} 114 foo: return; 115 bar: 116 if constexpr(sizeof(n) == 4) 117 goto bar; // ok 118 } 119 goto_redef(int n)120 void goto_redef(int n) { 121 a: if constexpr(sizeof(n) == 4) // expected-error {{redefinition}} expected-note {{constexpr if}} 122 a: goto a; // expected-note 2{{previous}} 123 else 124 a: goto a; // expected-error {{redefinition}} expected-error {{cannot jump}} 125 } 126 evil_things()127 void evil_things() { 128 goto evil_label; // expected-error {{cannot jump}} 129 if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}} 130 131 if constexpr (true) // expected-note {{constexpr if}} 132 goto surprise; // expected-error {{cannot jump}} 133 else 134 surprise: {} 135 } 136 } 137 #endif 138