1*50c81128SAaron Ballman // RUN: %clang_cc1 -verify -ffreestanding -Wno-unused -std=c2x %s
2*50c81128SAaron Ballman
3*50c81128SAaron Ballman /* WG14 N3042: full
4*50c81128SAaron Ballman * Introduce the nullptr constant
5*50c81128SAaron Ballman */
6*50c81128SAaron Ballman
7*50c81128SAaron Ballman #include <stddef.h>
8*50c81128SAaron Ballman
9*50c81128SAaron Ballman // FIXME: The paper calls for a feature testing macro to be added to stddef.h
10*50c81128SAaron Ballman // which we do not implement. This should be addressed after WG14 has processed
11*50c81128SAaron Ballman // national body comments for C2x as we've asked for the feature test macros to
12*50c81128SAaron Ballman // be removed.
13*50c81128SAaron Ballman #ifndef __STDC_VERSION_STDDEF_H__
14*50c81128SAaron Ballman #error "no version macro for stddef.h"
15*50c81128SAaron Ballman #endif
16*50c81128SAaron Ballman // expected-error@-2 {{"no version macro for stddef.h"}}
17*50c81128SAaron Ballman
questionable_behaviors()18*50c81128SAaron Ballman void questionable_behaviors() {
19*50c81128SAaron Ballman nullptr_t val;
20*50c81128SAaron Ballman
21*50c81128SAaron Ballman // This code is intended to be rejected by C and is accepted by C++. We filed
22*50c81128SAaron Ballman // an NB comment asking for this to be changed, but WG14 declined.
23*50c81128SAaron Ballman (void)(1 ? val : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}}
24*50c81128SAaron Ballman (void)(1 ? nullptr : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}}
25*50c81128SAaron Ballman
26*50c81128SAaron Ballman // This code is intended to be accepted by C and is rejected by C++. We filed
27*50c81128SAaron Ballman // an NB comment asking for this to be changed, but WG14 declined.
28*50c81128SAaron Ballman _Bool another = val; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
29*50c81128SAaron Ballman another = val; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
30*50c81128SAaron Ballman _Bool again = nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
31*50c81128SAaron Ballman again = nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
32*50c81128SAaron Ballman }
33*50c81128SAaron Ballman
test()34*50c81128SAaron Ballman void test() {
35*50c81128SAaron Ballman // Can we declare the type?
36*50c81128SAaron Ballman nullptr_t null_val;
37*50c81128SAaron Ballman
38*50c81128SAaron Ballman // Can we use the keyword?
39*50c81128SAaron Ballman int *typed_ptr = nullptr;
40*50c81128SAaron Ballman typed_ptr = nullptr;
41*50c81128SAaron Ballman
42*50c81128SAaron Ballman // Can we use the keyword with the type?
43*50c81128SAaron Ballman null_val = nullptr;
44*50c81128SAaron Ballman // Even initialize with it?
45*50c81128SAaron Ballman nullptr_t ignore = nullptr;
46*50c81128SAaron Ballman
47*50c81128SAaron Ballman // Can we assign an object of the type to another object of the same type?
48*50c81128SAaron Ballman null_val = null_val;
49*50c81128SAaron Ballman
50*50c81128SAaron Ballman // Can we assign nullptr_t objects to pointer objects?
51*50c81128SAaron Ballman typed_ptr = null_val;
52*50c81128SAaron Ballman
53*50c81128SAaron Ballman // Can we take the address of an object of type nullptr_t?
54*50c81128SAaron Ballman &null_val;
55*50c81128SAaron Ballman
56*50c81128SAaron Ballman // How about the null pointer named constant?
57*50c81128SAaron Ballman &nullptr; // expected-error {{cannot take the address of an rvalue of type 'nullptr_t'}}
58*50c81128SAaron Ballman
59*50c81128SAaron Ballman // Assignment from a null pointer constant to a nullptr_t is valid.
60*50c81128SAaron Ballman null_val = 0;
61*50c81128SAaron Ballman null_val = (void *)0;
62*50c81128SAaron Ballman
63*50c81128SAaron Ballman // Assignment from a nullptr_t to a pointer is also valid.
64*50c81128SAaron Ballman typed_ptr = null_val;
65*50c81128SAaron Ballman void *other_ptr = null_val;
66*50c81128SAaron Ballman
67*50c81128SAaron Ballman // Can it be used in all the places a scalar can be used?
68*50c81128SAaron Ballman if (null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
69*50c81128SAaron Ballman if (!null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
70*50c81128SAaron Ballman for (;null_val;) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
71*50c81128SAaron Ballman while (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
72*50c81128SAaron Ballman null_val && nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \
73*50c81128SAaron Ballman expected-warning {{implicit conversion of nullptr constant to 'bool'}}
74*50c81128SAaron Ballman nullptr || null_val; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \
75*50c81128SAaron Ballman expected-warning {{implicit conversion of nullptr constant to 'bool'}}
76*50c81128SAaron Ballman null_val ? 0 : 1; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
77*50c81128SAaron Ballman sizeof(null_val);
78*50c81128SAaron Ballman alignas(nullptr_t) int aligned;
79*50c81128SAaron Ballman
80*50c81128SAaron Ballman // Cast expressions have special handling for nullptr_t despite allowing
81*50c81128SAaron Ballman // casts of scalar types.
82*50c81128SAaron Ballman (nullptr_t)12; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
83*50c81128SAaron Ballman (float)null_val; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
84*50c81128SAaron Ballman (float)nullptr; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
85*50c81128SAaron Ballman (nullptr_t)0; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
86*50c81128SAaron Ballman (nullptr_t)(void *)0; // expected-error {{cannot cast an object of type 'void *' to 'nullptr_t'}}
87*50c81128SAaron Ballman (nullptr_t)(int *)12; // expected-error {{cannot cast an object of type 'int *' to 'nullptr_t'}}
88*50c81128SAaron Ballman
89*50c81128SAaron Ballman (void)null_val; // ok
90*50c81128SAaron Ballman (void)nullptr; // ok
91*50c81128SAaron Ballman (bool)null_val; // ok
92*50c81128SAaron Ballman (bool)nullptr; // ok
93*50c81128SAaron Ballman (int *)null_val; // ok
94*50c81128SAaron Ballman (int *)nullptr; // ok
95*50c81128SAaron Ballman (nullptr_t)nullptr; // ok
96*50c81128SAaron Ballman
97*50c81128SAaron Ballman // Can it be converted to bool with the result false (this relies on Clang
98*50c81128SAaron Ballman // accepting additional kinds of constant expressions where an ICE is
99*50c81128SAaron Ballman // required)?
100*50c81128SAaron Ballman static_assert(!nullptr); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
101*50c81128SAaron Ballman static_assert(!null_val); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
102*50c81128SAaron Ballman static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \
103*50c81128SAaron Ballman expected-warning {{implicit conversion of nullptr constant to 'bool'}}
104*50c81128SAaron Ballman static_assert(null_val); // expected-error {{static assertion failed due to requirement 'null_val'}} \
105*50c81128SAaron Ballman expected-warning {{implicit conversion of nullptr constant to 'bool'}}
106*50c81128SAaron Ballman
107*50c81128SAaron Ballman // Do equality operators work as expected with it?
108*50c81128SAaron Ballman static_assert(nullptr == nullptr);
109*50c81128SAaron Ballman static_assert(null_val == null_val);
110*50c81128SAaron Ballman static_assert(nullptr != (int*)1);
111*50c81128SAaron Ballman static_assert(null_val != (int*)1);
112*50c81128SAaron Ballman static_assert(nullptr == null_val);
113*50c81128SAaron Ballman static_assert(nullptr == 0);
114*50c81128SAaron Ballman static_assert(null_val == (void *)0);
115*50c81128SAaron Ballman
116*50c81128SAaron Ballman // None of the relational operators should succeed.
117*50c81128SAaron Ballman (void)(null_val <= 0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
118*50c81128SAaron Ballman (void)(null_val >= (void *)0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
119*50c81128SAaron Ballman (void)(!(null_val < (void *)0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
120*50c81128SAaron Ballman (void)(!(null_val > 0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
121*50c81128SAaron Ballman (void)(nullptr <= 0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
122*50c81128SAaron Ballman (void)(nullptr >= (void *)0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
123*50c81128SAaron Ballman (void)(!(nullptr < (void *)0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
124*50c81128SAaron Ballman (void)(!(nullptr > 0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
125*50c81128SAaron Ballman (void)(null_val <= null_val); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
126*50c81128SAaron Ballman (void)(null_val >= null_val); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
127*50c81128SAaron Ballman (void)(!(null_val < null_val)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
128*50c81128SAaron Ballman (void)(!(null_val > null_val)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
129*50c81128SAaron Ballman (void)(null_val <= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
130*50c81128SAaron Ballman (void)(null_val >= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
131*50c81128SAaron Ballman (void)(!(null_val < nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
132*50c81128SAaron Ballman (void)(!(null_val > nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
133*50c81128SAaron Ballman (void)(nullptr <= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
134*50c81128SAaron Ballman (void)(nullptr >= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
135*50c81128SAaron Ballman (void)(!(nullptr < nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
136*50c81128SAaron Ballman (void)(!(nullptr > nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
137*50c81128SAaron Ballman
138*50c81128SAaron Ballman // Do we pick the correct common type for conditional operators?
139*50c81128SAaron Ballman _Generic(1 ? nullptr : nullptr, nullptr_t : 0);
140*50c81128SAaron Ballman _Generic(1 ? null_val : null_val, nullptr_t : 0);
141*50c81128SAaron Ballman _Generic(1 ? typed_ptr : null_val, typeof(typed_ptr) : 0);
142*50c81128SAaron Ballman _Generic(1 ? null_val : typed_ptr, typeof(typed_ptr) : 0);
143*50c81128SAaron Ballman _Generic(1 ? nullptr : typed_ptr, typeof(typed_ptr) : 0);
144*50c81128SAaron Ballman _Generic(1 ? typed_ptr : nullptr, typeof(typed_ptr) : 0);
145*50c81128SAaron Ballman
146*50c81128SAaron Ballman // Same for GNU conditional operators?
147*50c81128SAaron Ballman _Generic(nullptr ?: nullptr, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
148*50c81128SAaron Ballman _Generic(null_val ?: null_val, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
149*50c81128SAaron Ballman _Generic(typed_ptr ?: null_val, typeof(typed_ptr) : 0);
150*50c81128SAaron Ballman _Generic(null_val ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
151*50c81128SAaron Ballman _Generic(nullptr ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
152*50c81128SAaron Ballman _Generic(typed_ptr ?: nullptr, typeof(typed_ptr) : 0);
153*50c81128SAaron Ballman
154*50c81128SAaron Ballman // Do we correctly issue type incompatibility diagnostics?
155*50c81128SAaron Ballman int i = nullptr; // expected-error {{initializing 'int' with an expression of incompatible type 'nullptr_t'}}
156*50c81128SAaron Ballman float f = nullptr; // expected-error {{initializing 'float' with an expression of incompatible type 'nullptr_t'}}
157*50c81128SAaron Ballman i = null_val; // expected-error {{assigning to 'int' from incompatible type 'nullptr_t'}}
158*50c81128SAaron Ballman f = null_val; // expected-error {{assigning to 'float' from incompatible type 'nullptr_t'}}
159*50c81128SAaron Ballman null_val = i; // expected-error {{assigning to 'nullptr_t' from incompatible type 'int'}}
160*50c81128SAaron Ballman null_val = f; // expected-error {{assigning to 'nullptr_t' from incompatible type 'float'}}
161*50c81128SAaron Ballman }
162*50c81128SAaron Ballman
163*50c81128SAaron Ballman // Can we use it as a function parameter?
164*50c81128SAaron Ballman void null_param(nullptr_t);
165*50c81128SAaron Ballman
other_test()166*50c81128SAaron Ballman void other_test() {
167*50c81128SAaron Ballman // Can we call the function properly?
168*50c81128SAaron Ballman null_param(nullptr);
169*50c81128SAaron Ballman
170*50c81128SAaron Ballman // We can pass any kind of null pointer constant.
171*50c81128SAaron Ballman null_param((void *)0);
172*50c81128SAaron Ballman null_param(0);
173*50c81128SAaron Ballman }
174*50c81128SAaron Ballman
175*50c81128SAaron Ballman
176*50c81128SAaron Ballman void printf(const char*, ...) __attribute__((format(printf, 1, 2)));
format_specifiers()177*50c81128SAaron Ballman void format_specifiers() {
178*50c81128SAaron Ballman // Don't warn when using nullptr with %p.
179*50c81128SAaron Ballman printf("%p", nullptr);
180*50c81128SAaron Ballman }
181*50c81128SAaron Ballman
182*50c81128SAaron Ballman // Ensure that conversion from a null pointer constant to nullptr_t is
183*50c81128SAaron Ballman // valid in a constant expression.
184*50c81128SAaron Ballman static_assert((nullptr_t){} == 0);
185