232 lines · cpp
1// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s2// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c++20 -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s3 4#define AQ __ptrauth(1,1,50)5#define AQ2 __ptrauth(1,1,51)6#define IQ __ptrauth(1,0,50)7 8struct __attribute__((trivial_abi)) AddrDisc { // expected-warning {{'trivial_abi' cannot be applied to 'AddrDisc'}} expected-note {{'trivial_abi' is disallowed on 'AddrDisc' because it has an address-discriminated '__ptrauth' field}}9 int * AQ m0;10};11 12struct __attribute__((trivial_abi)) NoAddrDisc {13 int * IQ m0;14};15 16namespace test_union {17 18 union U0 {19 int * AQ f0; // expected-note 4 {{'U0' is implicitly deleted because variant field 'f0' has an address-discriminated '__ptrauth' qualifier}}20 21 // ptrauth fields that don't have an address-discriminated qualifier don't22 // delete the special functions.23 int * IQ f1;24 };25 26 union U1 {27 int * AQ f0; // expected-note 8 {{'U1' is implicitly deleted because variant field 'f0' has an address-discriminated '__ptrauth' qualifier}}28 U1() = default;29 ~U1() = default;30 U1(const U1 &) = default; // expected-warning {{explicitly defaulted copy constructor is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}31 U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}} expected-note{{replace 'default'}}32 U1 & operator=(const U1 &) = default; // expected-warning {{explicitly defaulted copy assignment operator is implicitly deleted}} expected-note 2 {{explicitly defaulted function was implicitly deleted here}} expected-note{{replace 'default'}}33 U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}} expected-note{{replace 'default'}}34 };35 36 // It's fine if the user has explicitly defined the special functions.37 union U2 {38 int * AQ f0;39 U2() = default;40 ~U2() = default;41 U2(const U2 &);42 U2(U2 &&);43 U2 & operator=(const U2 &);44 U2 & operator=(U2 &&);45 };46 47 // Address-discriminated ptrauth fields in anonymous union fields delete the48 // defaulted copy/move constructors/assignment operators of the containing49 // class.50 struct S0 {51 union {52 int * AQ f0; // expected-note 4 {{' is implicitly deleted because variant field 'f0' has an address-discriminated '__ptrauth' qualifier}}53 char f1;54 };55 };56 57 struct S1 {58 union {59 union {60 int * AQ f0; // expected-note 4 {{implicitly deleted because variant field 'f0' has an address-discriminated '__ptrauth' qualifier}}61 char f1;62 } u; // expected-note 4 {{'S1' is implicitly deleted because field 'u' has a deleted}}63 int f2;64 };65 };66 67 U0 *x0;68 U1 *x1;69 U2 *x2;70 S0 *x3;71 S1 *x4;72 73 // No diagnostics since constructors/destructors of the unions aren't deleted by default.74 void testDefaultConstructor() {75 U0 u0;76 U1 u1;77 U2 u2;78 S0 s0;79 S1 s1;80 }81 82 // No diagnostics since destructors of the unions aren't deleted by default.83 void testDestructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {84 delete u0;85 delete u1;86 delete u2;87 delete s0;88 delete s1;89 }90 91 void testCopyConstructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {92 U0 t0(*u0); // expected-error {{call to implicitly-deleted copy constructor}}93 U1 t1(*u1); // expected-error {{call to implicitly-deleted copy constructor}}94 U2 t2(*u2);95 S0 t3(*s0); // expected-error {{call to implicitly-deleted copy constructor}}96 S1 t4(*s1); // expected-error {{call to implicitly-deleted copy constructor}}97 }98 99 void testCopyAssignment(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {100 *x0 = *u0; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}101 *x1 = *u1; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}102 *x2 = *u2;103 *x3 = *s0; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}104 *x4 = *s1; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}105 }106 107 void testMoveConstructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {108 U0 t0(static_cast<U0 &&>(*u0)); // expected-error {{call to implicitly-deleted copy constructor}}109 U1 t1(static_cast<U1 &&>(*u1)); // expected-error {{call to implicitly-deleted copy constructor}}110 U2 t2(static_cast<U2 &&>(*u2));111 S0 t3(static_cast<S0 &&>(*s0)); // expected-error {{call to implicitly-deleted copy constructor}}112 S1 t4(static_cast<S1 &&>(*s1)); // expected-error {{call to implicitly-deleted copy constructor}}113 }114 115 void testMoveAssignment(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {116 *x0 = static_cast<U0 &&>(*u0); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}117 *x1 = static_cast<U1 &&>(*u1); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}118 *x2 = static_cast<U2 &&>(*u2);119 *x3 = static_cast<S0 &&>(*s0); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}120 *x4 = static_cast<S1 &&>(*s1); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}121 }122}123 124bool test_composite_type0(bool c, int * AQ * a0, int * AQ * a1) {125 auto t = c ? a0 : a1;126 return a0 == a1;127}128 129bool test_composite_type1(bool c, int * AQ * a0, int * AQ2 * a1) {130 auto t = c ? a0 : a1; // expected-error {{incompatible operand types ('int *__ptrauth(1,1,50) *' and 'int *__ptrauth(1,1,51) *')}}131 return a0 == a1; // expected-error {{comparison of distinct pointer types ('int *__ptrauth(1,1,50) *' and 'int *__ptrauth(1,1,51) *')}}132}133 134void test_bad_call_diag(void *AQ *ptr); // expected-note{{candidate function not viable: 1st argument ('void *__ptrauth(1,1,51) *') has __ptrauth(1,1,51) qualifier, but parameter has __ptrauth(1,1,50) qualifier}} expected-note {{candidate function not viable: 1st argument ('void **') has no '__ptrauth' qualifier, but parameter has __ptrauth(1,1,50) qualifier}}135void test_bad_call_diag2(void **ptr); // expected-note {{candidate function not viable: 1st argument ('void *__ptrauth(1,1,50) *') has __ptrauth(1,1,50) qualifier, but parameter has no '__ptrauth' qualifier}}136 137int test_call_diag() {138 void *AQ ptr1, *AQ2 ptr2, *ptr3;139 test_bad_call_diag(&ptr2); // expected-error {{no matching function for call to 'test_bad_call_diag'}}140 test_bad_call_diag(&ptr3); // expected-error {{no matching function for call to 'test_bad_call_diag'}}141 test_bad_call_diag2(&ptr1); // expected-error {{no matching function for call to 'test_bad_call_diag2'}}142}143 144namespace 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 154namespace 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 171namespace 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 2 {{because 'is_qualified<int *>::value' evaluated to false}}183 // expected-note@-2 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 197 template <typename T>198 requires(Ptrauthable<T>)199 void func(T *);200 // expected-note@-1 {{candidate template ignored: constraints not satisfied [with T = int *]}}201 // expected-note@-3 {{because 'int *' does not satisfy 'Ptrauthable'}}202 // expected-note@-3 {{candidate template ignored: constraints not satisfied [with T = int *__ptrauth(1,1,51)]}}203 // expected-note@-5 {{because 'int *__ptrauth(1,1,51)' does not satisfy 'Ptrauthable'}}204 205 void test() {206 int * AQ p0;207 int *p1;208 int * AQ2 p2;209 func(&p0);210 func(&p1); // expected-error {{no matching function for call to 'func'}}211 func(&p2); // expected-error {{no matching function for call to 'func'}}212 }213}214 215template <class A, class B> constexpr int test_ptrauth_conflict() {216 A *a = nullptr;217 B *b = nullptr;218 a = b; // #BtoA219 b = a; // #AtoB220 return 0;221}222 223constexpr int no_ptrauth = test_ptrauth_conflict<int *, int *>();224constexpr int matching_ptrauth =225 test_ptrauth_conflict<int * __ptrauth(1,1,123), int * __ptrauth(1,1,123)>();226constexpr int mismatching_ptrauth =227 test_ptrauth_conflict<int * __ptrauth(2,1,1024), int * __ptrauth(1,1,123)>(); // #FailedConstExpr228// expected-error@#FailedConstExpr {{constexpr variable 'mismatching_ptrauth' must be initialized by a constant expression}}229// expected-note@#FailedConstExpr {{in instantiation of function template specialization 'test_ptrauth_conflict<int *__ptrauth(2,1,1024), int *__ptrauth(1,1,123)>' requested here}}230// expected-error@#BtoA {{assigning 'int *__ptrauth(1,1,123) *' to 'int *__ptrauth(2,1,1024) *' changes pointer authentication of pointee type}}231// expected-error@#AtoB {{assigning 'int *__ptrauth(2,1,1024) *' to 'int *__ptrauth(1,1,123) *' changes pointer authentication of pointee type}}232