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