1 // RUN: %clang_cc1 -verify -ffreestanding -Wno-unused -std=c2x %s
4 * Introduce the nullptr constant
6 * Claiming partial support for this feature until the WG14 NB comments can be
7 * resolved to know what the correct behavior really should be.
12 // FIXME: The paper calls for a feature testing macro to be added to stddef.h
13 // which we do not implement. This should be addressed after WG14 has processed
14 // national body comments for C2x as we've asked for the feature test macros to
16 #ifndef __STDC_VERSION_STDDEF_H__
17 #error "no version macro for stddef.h"
19 // expected-error@-2 {{"no version macro for stddef.h"}}
21 void questionable_behaviors() {
24 // FIXME: This code is intended to be rejected by C and is accepted by C++.
25 // We've filed an NB comment with WG14 about the incompatibility.
26 (void)(1 ? val
: 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}}
27 (void)(1 ? nullptr : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}}
29 // FIXME: This code is intended to be accepted by C and is rejected by C++.
30 // We're following the C++ semantics until WG14 has resolved the NB comments
31 // we've filed about the incompatibility.
32 _Bool another
= val
; // expected-error {{initializing 'bool' with an expression of incompatible type 'nullptr_t'}}
33 another
= val
; // expected-error {{assigning to 'bool' from incompatible type 'nullptr_t'}}
34 _Bool again
= nullptr; // expected-error {{initializing 'bool' with an expression of incompatible type 'nullptr_t'}}
35 again
= nullptr; // expected-error {{assigning to 'bool' from incompatible type 'nullptr_t'}}
37 // FIXME: This code is intended to be rejected by C and is accepted by C++.
38 // We've filed an NB comment with WG14 about the incompatibility.
39 val
= 0; // expected-error {{assigning to 'nullptr_t' from incompatible type 'int'}}
41 // Not accepted in C++ but might want to accept in C as a null pointer constant?
42 val
= (void *)0; // expected-error {{assigning to 'nullptr_t' from incompatible type 'void *'}}
46 // Can we declare the type?
49 // Can we use the keyword?
50 int *typed_ptr
= nullptr;
53 // Can we use the keyword with the type?
55 // Even initialize with it?
56 nullptr_t ignore
= nullptr;
58 // Can we assign an object of the type to another object of the same type?
61 // Can we assign nullptr_t objects to pointer objects?
64 // Can we take the address of an object of type nullptr_t?
67 // How about the null pointer named constant?
68 &nullptr; // expected-error {{cannot take the address of an rvalue of type 'nullptr_t'}}
70 // Can it be used in all the places a scalar can be used?
79 alignas(nullptr_t
) int aligned
;
81 // Cast expressions have special handling for nullptr_t despite allowing
82 // casts of scalar types.
83 (nullptr_t
)12; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
84 (float)null_val
; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
85 (float)nullptr; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
86 (nullptr_t
)0; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
87 (nullptr_t
)(void *)0; // expected-error {{cannot cast an object of type 'void *' to 'nullptr_t'}}
88 (nullptr_t
)(int *)12; // expected-error {{cannot cast an object of type 'int *' to 'nullptr_t'}}
94 (int *)null_val
; // ok
96 (nullptr_t
)nullptr; // ok
98 // Can it be converted to bool with the result false (this relies on Clang
99 // accepting additional kinds of constant expressions where an ICE is
101 static_assert(!nullptr);
102 static_assert(!null_val
);
103 static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \
104 expected
-warning
{{implicit conversion of
nullptr constant to
'bool'}}
105 static_assert(null_val
); // expected-error {{static assertion failed due to requirement 'null_val'}} \
106 expected
-warning
{{implicit conversion of
nullptr constant to
'bool'}}
108 // Do equality operators work as expected with it?
109 static_assert(nullptr == nullptr);
110 static_assert(null_val
== null_val
);
111 static_assert(nullptr != (int*)1);
112 static_assert(null_val
!= (int*)1);
113 static_assert(nullptr == null_val
);
114 static_assert(nullptr == 0);
115 static_assert(null_val
== (void *)0);
117 // None of the relational operators should succeed.
118 (void)(null_val
<= 0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
119 (void)(null_val
>= (void *)0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
120 (void)(!(null_val
< (void *)0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
121 (void)(!(null_val
> 0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
122 (void)(nullptr <= 0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
123 (void)(nullptr >= (void *)0); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
124 (void)(!(nullptr < (void *)0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'void *')}}
125 (void)(!(nullptr > 0)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}}
126 (void)(null_val
<= null_val
); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
127 (void)(null_val
>= null_val
); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
128 (void)(!(null_val
< null_val
)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
129 (void)(!(null_val
> null_val
)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
130 (void)(null_val
<= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
131 (void)(null_val
>= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
132 (void)(!(null_val
< nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
133 (void)(!(null_val
> nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
134 (void)(nullptr <= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
135 (void)(nullptr >= nullptr); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
136 (void)(!(nullptr < nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
137 (void)(!(nullptr > nullptr)); // expected-error {{invalid operands to binary expression ('nullptr_t' and 'nullptr_t')}}
139 // Do we pick the correct common type for conditional operators?
140 _Generic(1 ? nullptr : nullptr, nullptr_t
: 0);
141 _Generic(1 ? null_val
: null_val
, nullptr_t
: 0);
142 _Generic(1 ? typed_ptr
: null_val
, typeof(typed_ptr
) : 0);
143 _Generic(1 ? null_val
: typed_ptr
, typeof(typed_ptr
) : 0);
144 _Generic(1 ? nullptr : typed_ptr
, typeof(typed_ptr
) : 0);
145 _Generic(1 ? typed_ptr
: nullptr, typeof(typed_ptr
) : 0);
147 // Same for GNU conditional operators?
148 _Generic(nullptr ?: nullptr, nullptr_t
: 0);
149 _Generic(null_val
?: null_val
, nullptr_t
: 0);
150 _Generic(typed_ptr
?: null_val
, typeof(typed_ptr
) : 0);
151 _Generic(null_val
?: typed_ptr
, typeof(typed_ptr
) : 0);
152 _Generic(nullptr ?: typed_ptr
, typeof(typed_ptr
) : 0);
153 _Generic(typed_ptr
?: nullptr, typeof(typed_ptr
) : 0);
155 // Do we correctly issue type incompatibility diagnostics?
156 int i
= nullptr; // expected-error {{initializing 'int' with an expression of incompatible type 'nullptr_t'}}
157 float f
= nullptr; // expected-error {{initializing 'float' with an expression of incompatible type 'nullptr_t'}}
158 i
= null_val
; // expected-error {{assigning to 'int' from incompatible type 'nullptr_t'}}
159 f
= null_val
; // expected-error {{assigning to 'float' from incompatible type 'nullptr_t'}}
160 null_val
= i
; // expected-error {{assigning to 'nullptr_t' from incompatible type 'int'}}
161 null_val
= f
; // expected-error {{assigning to 'nullptr_t' from incompatible type 'float'}}
164 // Can we use it as a function parameter?
165 void null_param(nullptr_t
); // expected-note 2 {{passing argument to parameter here}}
168 // Can we call the function properly?
171 // Do we get reasonable diagnostics when we can't call the function?
172 null_param((void *)0); // expected-error {{passing 'void *' to parameter of incompatible type 'nullptr_t'}}
174 // FIXME: The paper requires this to be rejected, but it is accepted in C++.
175 // This should be addressed after WG14 has processed national body comments.
176 null_param(0); // expected-error {{passing 'int' to parameter of incompatible type 'nullptr_t'}}
180 void printf(const char*, ...) __attribute__((format(printf
, 1, 2)));
181 void format_specifiers() {
182 // Don't warn when using nullptr with %p.
183 printf("%p", nullptr);