File: ptrauth-qualifier.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (141 lines) | stat: -rw-r--r-- 6,586 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// RUN: %clang_cc1 -triple arm64-apple-ios -std=c++11  -fptrauth-calls -fptrauth-intrinsics -verify -fsyntax-only %s

#define AQ __ptrauth(1,1,50)
#define AQ2 __ptrauth(1,1,51)
#define IQ __ptrauth(1,0,50)

struct __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}}
  int * AQ m0;
};

struct __attribute__((trivial_abi)) NoAddrDisc {
  int * IQ m0;
};

namespace test_union {

  union U0 {
    int * AQ f0; // expected-note 4 {{'U0' is implicitly deleted because variant field 'f0' has an address-discriminated ptrauth qualifier}}

    // ptrauth fields that don't have an address-discriminated qualifier don't
    // delete the special functions.
    int * IQ f1;
  };

  union U1 {
    int * AQ f0; // expected-note 8 {{'U1' is implicitly deleted because variant field 'f0' has an address-discriminated ptrauth qualifier}}
    U1() = default;
    ~U1() = default;
    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'}}
    U1(U1 &&) = default; // expected-warning {{explicitly defaulted move constructor is implicitly deleted}} expected-note{{replace 'default'}}
    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'}}
    U1 & operator=(U1 &&) = default; // expected-warning {{explicitly defaulted move assignment operator is implicitly deleted}} expected-note{{replace 'default'}}
  };

  // It's fine if the user has explicitly defined the special functions.
  union U2 {
    int * AQ f0;
    U2() = default;
    ~U2() = default;
    U2(const U2 &);
    U2(U2 &&);
    U2 & operator=(const U2 &);
    U2 & operator=(U2 &&);
  };

  // Address-discriminated ptrauth fields in anonymous union fields delete the
  // defaulted copy/move constructors/assignment operators of the containing
  // class.
  struct S0 {
    union {
      int * AQ f0; // expected-note 4 {{' is implicitly deleted because variant field 'f0' has an address-discriminated ptrauth qualifier}}
      char f1;
    };
  };

  struct S1 {
    union {
      union { // expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}}
        int * AQ f0;
        char f1;
      };
      int f2;
    };
  };

  U0 *x0;
  U1 *x1;
  U2 *x2;
  S0 *x3;
  S1 *x4;

  // No diagnostics since constructors/destructors of the unions aren't deleted by default.
  void testDefaultConstructor() {
    U0 u0;
    U1 u1;
    U2 u2;
    S0 s0;
    S1 s1;
  }

  // No diagnostics since destructors of the unions aren't deleted by default.
  void testDestructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {
    delete u0;
    delete u1;
    delete u2;
    delete s0;
    delete s1;
  }

  void testCopyConstructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {
    U0 t0(*u0); // expected-error {{call to implicitly-deleted copy constructor}}
    U1 t1(*u1); // expected-error {{call to implicitly-deleted copy constructor}}
    U2 t2(*u2);
    S0 t3(*s0); // expected-error {{call to implicitly-deleted copy constructor}}
    S1 t4(*s1); // expected-error {{call to implicitly-deleted copy constructor}}
  }

  void testCopyAssignment(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {
    *x0 = *u0; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x1 = *u1; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x2 = *u2;
    *x3 = *s0; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x4 = *s1; // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
  }

  void testMoveConstructor(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {
    U0 t0(static_cast<U0 &&>(*u0)); // expected-error {{call to implicitly-deleted copy constructor}}
    U1 t1(static_cast<U1 &&>(*u1)); // expected-error {{call to implicitly-deleted copy constructor}}
    U2 t2(static_cast<U2 &&>(*u2));
    S0 t3(static_cast<S0 &&>(*s0)); // expected-error {{call to implicitly-deleted copy constructor}}
    S1 t4(static_cast<S1 &&>(*s1)); // expected-error {{call to implicitly-deleted copy constructor}}
  }

  void testMoveAssignment(U0 *u0, U1 *u1, U2 *u2, S0 *s0, S1 *s1) {
    *x0 = static_cast<U0 &&>(*u0); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x1 = static_cast<U1 &&>(*u1); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x2 = static_cast<U2 &&>(*u2);
    *x3 = static_cast<S0 &&>(*s0); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
    *x4 = static_cast<S1 &&>(*s1); // expected-error {{cannot be assigned because its copy assignment operator is implicitly deleted}}
  }
}

bool test_composite_type0(bool c, int * AQ * a0, int * AQ * a1) {
  auto t = c ? a0 : a1;
  return a0 == a1;
}

bool test_composite_type1(bool c, int * AQ * a0, int * AQ2 * a1) {
  auto t = c ? a0 : a1; // expected-error {{incompatible operand types ('int *__ptrauth(1,1,50) *' and 'int *__ptrauth(1,1,51) *')}}
  return a0 == a1; // expected-error {{comparison of distinct pointer types ('int *__ptrauth(1,1,50) *' and 'int *__ptrauth(1,1,51) *')}}
}

void 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}}
void test_bad_call_diag2(void ** ptr); // expected-note{{1st argument ('void *__ptrauth(1,1,50) *') has __ptrauth(1,1,50) qualifier, but parameter has no ptrauth qualifier}}

int test_call_diag() {
  void *AQ ptr1, *AQ2 ptr2, *ptr3;
  test_bad_call_diag(&ptr2); // expected-error {{no matching function for call to 'test_bad_call_diag'}}
  test_bad_call_diag(&ptr3); // expected-error {{no matching function for call to 'test_bad_call_diag'}}
  test_bad_call_diag2(&ptr1); // expected-error {{no matching function for call to 'test_bad_call_diag2'}}
}