[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / C / C2x / n3042.c
blobe949890bf82f118e9ae850befeb322c173ac0ab9
1 // RUN: %clang_cc1 -verify -ffreestanding -Wno-unused -std=c2x %s
3 /* WG14 N3042: partial
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.
8 */
10 #include <stddef.h>
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
15 // be removed.
16 #ifndef __STDC_VERSION_STDDEF_H__
17 #error "no version macro for stddef.h"
18 #endif
19 // expected-error@-2 {{"no version macro for stddef.h"}}
21 void questionable_behaviors() {
22 nullptr_t val;
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 *'}}
45 void test() {
46 // Can we declare the type?
47 nullptr_t null_val;
49 // Can we use the keyword?
50 int *typed_ptr = nullptr;
51 typed_ptr = nullptr;
53 // Can we use the keyword with the type?
54 null_val = nullptr;
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?
59 null_val = null_val;
61 // Can we assign nullptr_t objects to pointer objects?
62 typed_ptr = null_val;
64 // Can we take the address of an object of type nullptr_t?
65 &null_val;
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?
71 if (null_val) {}
72 if (!null_val) {}
73 for (;null_val;) {}
74 while (nullptr) {}
75 null_val && nullptr;
76 nullptr || null_val;
77 null_val ? 0 : 1;
78 sizeof(null_val);
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'}}
90 (void)null_val; // ok
91 (void)nullptr; // ok
92 (bool)null_val; // ok
93 (bool)nullptr; // ok
94 (int *)null_val; // ok
95 (int *)nullptr; // 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
100 // required)?
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}}
167 void other_test() {
168 // Can we call the function properly?
169 null_param(nullptr);
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);