|
1 | | -// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++11 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s |
2 | | -// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++11 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s |
| 1 | +// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s |
| 2 | +// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s |
3 | 3 |
|
4 | 4 | #define AQ __ptrauth(1,1,50) |
5 | 5 | #define AQ2 __ptrauth(1,1,51) |
@@ -140,3 +140,57 @@ int test_call_diag() { |
140 | 140 | test_bad_call_diag(&ptr3); // expected-error {{no matching function for call to 'test_bad_call_diag'}} |
141 | 141 | test_bad_call_diag2(&ptr1); // expected-error {{no matching function for call to 'test_bad_call_diag2'}} |
142 | 142 | } |
| 143 | + |
| 144 | +namespace test_constexpr { |
| 145 | + constexpr int i = 100; |
| 146 | + constexpr const int * AQ p = &i; |
| 147 | + constexpr const int * const AQ *pp = &p; |
| 148 | + constexpr int i1 = **((const int * const AQ *)pp); |
| 149 | + constexpr int i2 = **((const int * const AQ2 *)pp); |
| 150 | + // expected-error@-1 {{constexpr variable 'i2' must be initialized by a constant expression}} |
| 151 | + // expected-note@-2 {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} |
| 152 | +} |
| 153 | + |
| 154 | +namespace test_lambda { |
| 155 | + void test() { |
| 156 | + int * AQ v0; |
| 157 | + int * AQ *v1; |
| 158 | + |
| 159 | + [v0, v1]() { |
| 160 | + static_assert(__is_same(decltype(v0), int * AQ)); |
| 161 | + static_assert(__is_same(decltype(v1), int * AQ *)); |
| 162 | + }(); |
| 163 | + |
| 164 | + [v2 = v0, v3 = v1]() { |
| 165 | + static_assert(__is_same(decltype(v2), int *)); |
| 166 | + static_assert(__is_same(decltype(v3), int * AQ *)); |
| 167 | + }(); |
| 168 | + } |
| 169 | +} |
| 170 | + |
| 171 | +namespace test_concept { |
| 172 | + template <typename T> struct is_qualified { |
| 173 | + static constexpr bool value = false; |
| 174 | + }; |
| 175 | + |
| 176 | + template <typename T> struct is_qualified<T * AQ> { |
| 177 | + static constexpr bool value = true; |
| 178 | + }; |
| 179 | + |
| 180 | + template <typename T> |
| 181 | + concept Ptrauthable = is_qualified<T>::value; |
| 182 | + // expected-note@-1 {{because 'is_qualified<int *>::value' evaluated to false}} |
| 183 | + // expected-note@-2 {{because 'is_qualified<int *__ptrauth(1,1,51)>::value' evaluated to false}} |
| 184 | + |
| 185 | + template <typename T> |
| 186 | + requires(Ptrauthable<T>) |
| 187 | + struct S {}; |
| 188 | + // expected-note@-2 {{because 'int *' does not satisfy 'Ptrauthable'}} |
| 189 | + // expected-note@-3 {{because 'int *__ptrauth(1,1,51)' does not satisfy 'Ptrauthable'}} |
| 190 | + |
| 191 | + S<int * AQ> s0; |
| 192 | + S<int *> s1; |
| 193 | + // expected-error@-1 {{constraints not satisfied for class template 'S' [with T = int *]}} |
| 194 | + S<int * AQ2> s1; |
| 195 | + // expected-error@-1 {{constraints not satisfied for class template 'S' [with T = int *__ptrauth(1,1,51)]}} |
| 196 | +} |
0 commit comments