Skip to content

Commit 283a9f0

Browse files
author
git apple-llvm automerger
committed
Merge commit '5b16941f5707' from llvm.org/main into next
2 parents e9fa0d7 + 301fd41 commit 283a9f0

File tree

9 files changed

+247
-24
lines changed

9 files changed

+247
-24
lines changed

clang/lib/AST/Type.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2932,6 +2932,9 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type,
29322932
if (CanonicalType->isIncompleteType())
29332933
return false;
29342934

2935+
if (CanonicalType.hasAddressDiscriminatedPointerAuth())
2936+
return false;
2937+
29352938
// As an extension, Clang treats vector types as Scalar types.
29362939
if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
29372940
return true;
@@ -2944,7 +2947,7 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type,
29442947
return ClassDecl->isTriviallyCopyable();
29452948
}
29462949
}
2947-
return true;
2950+
return !RT->getDecl()->isNonTrivialToPrimitiveCopy();
29482951
}
29492952
// No other types can match.
29502953
return false;

clang/lib/CodeGen/CGBlocks.cpp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,7 +1632,7 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
16321632

16331633
if (T.hasAddressDiscriminatedPointerAuth())
16341634
return std::make_pair(
1635-
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth, Flags);
1635+
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth, Flags);
16361636

16371637
Flags = BLOCK_FIELD_IS_OBJECT;
16381638
bool isBlockPointer = T->isBlockPointerType();
@@ -1656,8 +1656,8 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
16561656
Flags);
16571657
case QualType::PCK_PtrAuth:
16581658
return std::make_pair(
1659-
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth,
1660-
BlockFieldFlags());
1659+
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth,
1660+
BlockFieldFlags());
16611661
case QualType::PCK_Trivial:
16621662
case QualType::PCK_VolatileTrivial: {
16631663
if (!T->isObjCRetainableType())
@@ -1981,10 +1981,10 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
19811981
EmitARCCopyWeak(dstField, srcField);
19821982
break;
19831983
case BlockCaptureEntityKind::AddressDiscriminatedPointerAuth: {
1984-
auto type = CI.getVariable()->getType();
1985-
auto ptrauth = type.getPointerAuth();
1986-
assert(ptrauth && ptrauth.isAddressDiscriminated());
1987-
EmitPointerAuthCopy(ptrauth, type, dstField, srcField);
1984+
QualType Type = CI.getVariable()->getType();
1985+
PointerAuthQualifier PointerAuth = Type.getPointerAuth();
1986+
assert(PointerAuth && PointerAuth.isAddressDiscriminated());
1987+
EmitPointerAuthCopy(PointerAuth, Type, dstField, srcField);
19881988
// We don't need to push cleanups for ptrauth types.
19891989
continue;
19901990
}
@@ -2330,24 +2330,24 @@ class AddressDiscriminatedByrefHelpers final : public BlockByrefHelpers {
23302330
QualType VarType;
23312331

23322332
public:
2333-
AddressDiscriminatedByrefHelpers(CharUnits alignment, QualType type)
2334-
: BlockByrefHelpers(alignment), VarType(type) {
2335-
assert(type.hasAddressDiscriminatedPointerAuth());
2333+
AddressDiscriminatedByrefHelpers(CharUnits Alignment, QualType Type)
2334+
: BlockByrefHelpers(Alignment), VarType(Type) {
2335+
assert(Type.hasAddressDiscriminatedPointerAuth());
23362336
}
23372337

2338-
void emitCopy(CodeGenFunction &CGF, Address destField,
2339-
Address srcField) override {
2340-
CGF.EmitPointerAuthCopy(VarType.getPointerAuth(), VarType,
2341-
destField, srcField);
2338+
void emitCopy(CodeGenFunction &CGF, Address DestField,
2339+
Address SrcField) override {
2340+
CGF.EmitPointerAuthCopy(VarType.getPointerAuth(), VarType, DestField,
2341+
SrcField);
23422342
}
23432343

23442344
bool needsDispose() const override { return false; }
2345-
void emitDispose(CodeGenFunction &CGF, Address field) override {
2345+
void emitDispose(CodeGenFunction &CGF, Address Field) override {
23462346
llvm_unreachable("should never be called");
23472347
}
23482348

2349-
void profileImpl(llvm::FoldingSetNodeID &id) const override {
2350-
id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2349+
void profileImpl(llvm::FoldingSetNodeID &ID) const override {
2350+
ID.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
23512351
}
23522352
};
23532353

@@ -2552,12 +2552,10 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
25522552
return ::buildByrefHelpers(
25532553
CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
25542554
}
2555-
25562555
if (type.hasAddressDiscriminatedPointerAuth()) {
25572556
return ::buildByrefHelpers(
25582557
CGM, byrefInfo, AddressDiscriminatedByrefHelpers(valueAlignment, type));
25592558
}
2560-
25612559
// If type is a non-trivial C struct type that is non-trivial to
25622560
// destructly move or destroy, build the copy and dispose helpers.
25632561
if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct ||

clang/lib/CodeGen/CGBlocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ enum class BlockCaptureEntityKind {
147147
None,
148148
AddressDiscriminatedPointerAuth,
149149
CXXRecord, // Copy or destroy
150+
AddressDiscriminatedPointerAuth,
150151
ARCWeak,
151152
ARCStrong,
152153
NonTrivialCStruct,

clang/lib/CodeGen/CGCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4865,7 +4865,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
48654865

48664866
if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) &&
48674867
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue &&
4868-
!type.isNonTrivialToPrimitiveCopy() && !type->isArrayParameterType()) {
4868+
!type->isArrayParameterType() && !type.isNonTrivialToPrimitiveCopy()) {
48694869
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
48704870
assert(L.isSimple());
48714871
args.addUncopiedAggregate(L, type);

clang/lib/CodeGen/CGNonTrivialStruct.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,11 @@ struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
270270
void visitPtrAuth(QualType FT, const FieldDecl *FD,
271271
CharUnits CurStructOffset) {
272272
this->appendStr("_pa");
273-
PointerAuthQualifier PtrAuth = FT.getPointerAuth();
273+
PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
274274
this->appendStr(llvm::to_string(PtrAuth.getKey()) + "_");
275275
this->appendStr(llvm::to_string(PtrAuth.getExtraDiscriminator()) + "_");
276+
if (PtrAuth.authenticatesNullValues())
277+
this->appendStr("anv_");
276278
CharUnits FieldOffset = CurStructOffset + this->getFieldOffset(FD);
277279
this->appendStr(llvm::to_string(FieldOffset.getQuantity()));
278280
}
@@ -578,10 +580,9 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
578580
RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
579581
this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
580582
}
581-
582583
void visitPtrAuth(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
583584
std::array<Address, 2> Addrs) {
584-
PointerAuthQualifier PtrAuth = FT.getPointerAuth();
585+
PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
585586
Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
586587
Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
587588
this->CGF->EmitPointerAuthCopy(PtrAuth, FT, Addrs[DstIdx], Addrs[SrcIdx]);

clang/test/CodeGen/ptrauth-in-c-struct.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,23 @@ typedef struct {
2424
int * IQ f; // No address discrimination.
2525
} SI;
2626

27+
typedef struct {
28+
// Transitively includes an address discriminated value
29+
SA nested;
30+
} Nested_AddrDiscrimination;
31+
32+
typedef struct {
33+
// Transitively includes a pointer to a struct containing
34+
// an address discriminated value, which means that this
35+
// does not actually contain an address discriminated value
36+
SA *nestedPtr;
37+
} Nested_PtrAddrDiscrimination;
38+
2739
SA getSA(void);
2840
void calleeSA(SA);
2941

42+
int g0;
43+
3044
// CHECK: define void @test_copy_constructor_SA(ptr noundef %{{.*}})
3145
// CHECK: call void @__copy_constructor_8_8_t0w4_pa1_50_8(
3246

@@ -150,3 +164,42 @@ void test_copy_constructor_SI(SI *s) {
150164

151165
void test_parameter_SI(SI a) {
152166
}
167+
168+
// CHECK-LABEL: define void @test_array(
169+
// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_SA]], ptr %{{.*}}, i32 0, i32 1
170+
// CHECK: %[[V0:.*]] = ptrtoint ptr %[[F1]] to i64
171+
// CHECK: %[[V1:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V0]], i64 50)
172+
// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @g0 to i64), i32 1, i64 %[[V1]])
173+
// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr
174+
// CHECK: store ptr %[[V3]], ptr %[[F1]], align 8
175+
// CHECK: %[[F12:.*]] = getelementptr inbounds nuw %[[STRUCT_SA]], ptr %{{.*}}, i32 0, i32 1
176+
// CHECK: %[[V4:.*]] = ptrtoint ptr %[[F12]] to i64
177+
// CHECK: %[[V5:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V4]], i64 50)
178+
// CHECK: %[[V6:.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @g0 to i64), i32 1, i64 %[[V5]])
179+
// CHECK: %[[V7:.*]] = inttoptr i64 %[[V6]] to ptr
180+
// CHECK: store ptr %[[V7]], ptr %[[F12]], align 8
181+
182+
void test_array(void) {
183+
const SA a[] = {{0, &g0}, {1, &g0}};
184+
}
185+
186+
187+
void test_nested_struct(Nested_AddrDiscrimination* Src) {
188+
Nested_AddrDiscrimination Dst = *Src;
189+
}
190+
// CHECK-LABEL: define void @test_nested_struct
191+
// CHECK: [[DST:%.*]] = alloca %struct.Nested_AddrDiscrimination
192+
// CHECK: [[SRC_ADDR:%.*]] = load ptr, ptr %Src.addr
193+
// CHECK: call void @__copy_constructor_8_8_S_t0w4_pa1_50_8(ptr [[DST]], ptr [[SRC_ADDR]])
194+
195+
// CHECK-LABEL: define linkonce_odr hidden void @__copy_constructor_8_8_S_t0w4_pa1_50_8(
196+
// CHECK: call void @__copy_constructor_8_8_t0w4_pa1_50_8
197+
198+
199+
void test_nested_struct_ptr(Nested_PtrAddrDiscrimination* Src) {
200+
Nested_PtrAddrDiscrimination Dst = *Src;
201+
}
202+
// CHECK-LABEL: define void @test_nested_struct_ptr
203+
// CHECK: [[DST:%.*]] = alloca %struct.Nested_PtrAddrDiscrimination
204+
// CHECK: [[SRC_ADDR:%.*]] = load ptr, ptr %Src.addr
205+
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST]], ptr align 8 [[SRC_ADDR]], i64 8, i1 false)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -fblocks -emit-llvm %s -o - | FileCheck %s
2+
3+
struct A {
4+
int value;
5+
};
6+
struct A *createA(void);
7+
8+
void use_block(int (^)(void));
9+
10+
// CHECK-LABEL: define void @test_block_nonaddress_capture(
11+
void test_block_nonaddress_capture() {
12+
// CHECK: [[VAR:%.*]] = alloca ptr,
13+
// CHECK: [[BLOCK:%.*]] = alloca
14+
// flags - no copy/dispose required
15+
// CHECK: store i32 1073741824, ptr
16+
// CHECK: [[CAPTURE:%.*]] = getelementptr inbounds {{.*}} [[BLOCK]], i32 0, i32 5
17+
// CHECK: [[LOAD:%.*]] = load ptr, ptr [[VAR]],
18+
// CHECK: store ptr [[LOAD]], ptr [[CAPTURE]]
19+
struct A * __ptrauth(1, 0, 15) ptr = createA();
20+
use_block(^{ return ptr->value; });
21+
}
22+
// CHECK-LABEL: define internal i32 @__test_block_nonaddress_capture_block_invoke
23+
// CHECK: call i64 @llvm.ptrauth.auth(i64 {{%.*}}, i32 1, i64 15)
24+
25+
// CHECK-LABEL: define void @test_block_address_capture(
26+
void test_block_address_capture() {
27+
// CHECK: [[VAR:%.*]] = alloca ptr,
28+
// CHECK: [[BLOCK:%.*]] = alloca
29+
// flags - copy/dispose required
30+
// CHECK: store i32 1107296256, ptr
31+
// CHECK: [[CAPTURE:%.*]] = getelementptr inbounds {{.*}} [[BLOCK]], i32 0, i32 5
32+
// CHECK: [[LOAD:%.*]] = load ptr, ptr [[VAR]],
33+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[VAR]] to i64
34+
// CHECK: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 30)
35+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[CAPTURE]] to i64
36+
// CHECK: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 30)
37+
// CHECK: [[T0:%.*]] = icmp ne ptr [[LOAD]], null
38+
// CHECK: br i1 [[T0]]
39+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64
40+
// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]])
41+
// CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
42+
// CHECK: [[T0:%.*]] = phi
43+
// CHECK: store ptr [[T0]], ptr [[CAPTURE]]
44+
struct A * __ptrauth(1, 1, 30) ptr = createA();
45+
use_block(^{ return ptr->value; });
46+
}
47+
// CHECK-LABEL: define internal i32 @__test_block_address_capture_block_invoke
48+
// CHECK: call i64 @llvm.ptrauth.auth(i64 {{%.*}}, i32 1, i64 {{%.*}})
49+
50+
// CHECK: linkonce_odr hidden void @__copy_helper_block_8_32p1d30(
51+
// CHECK: [[OLDSLOT:%.*]] = getelementptr inbounds {{.*}} {{.*}}, i32 0, i32 5
52+
// CHECK: [[NEWSLOT:%.*]] = getelementptr inbounds {{.*}} {{.*}}, i32 0, i32 5
53+
// CHECK: [[LOAD:%.*]] = load ptr, ptr [[OLDSLOT]],
54+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[OLDSLOT]] to i64
55+
// CHECK: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 30)
56+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[NEWSLOT]] to i64
57+
// CHECK: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 30)
58+
// CHECK: [[T0:%.*]] = icmp ne ptr [[LOAD]], null
59+
// CHECK: br i1 [[T0]]
60+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64
61+
// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]])
62+
// CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
63+
// CHECK: [[T0:%.*]] = phi
64+
// CHECK: store ptr [[T0]], ptr [[NEWSLOT]]
65+
66+
// CHECK-LABEL: define void @test_block_nonaddress_byref_capture(
67+
void test_block_nonaddress_byref_capture() {
68+
// flags - no copy/dispose required for byref
69+
// CHECK: store i32 0,
70+
// CHECK: call ptr @createA()
71+
// flags - copy/dispose required for block (because it captures byref)
72+
// CHECK: store i32 1107296256,
73+
__block struct A * __ptrauth(1, 0, 45) ptr = createA();
74+
use_block(^{ return ptr->value; });
75+
}
76+
77+
// CHECK-LABEL: define void @test_block_address_byref_capture(
78+
void test_block_address_byref_capture() {
79+
// CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:.*]], align
80+
// CHECK: [[BLOCK:%.*]] = alloca
81+
// flags - byref requires copy/dispose
82+
// CHECK: store i32 33554432,
83+
// CHECK: store i32 48,
84+
// CHECK: [[COPY_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 4
85+
// CHECK: store ptr @__Block_byref_object_copy_, ptr [[COPY_HELPER_FIELD]], align
86+
// CHECK: [[DISPOSE_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 5
87+
// CHECK: store ptr @__Block_byref_object_dispose_, ptr [[DISPOSE_HELPER_FIELD]], align
88+
// flags - copy/dispose required
89+
// CHECK: store i32 1107296256, ptr
90+
__block struct A * __ptrauth(1, 1, 60) ptr = createA();
91+
use_block(^{ return ptr->value; });
92+
}
93+
// CHECK-LABEL: define internal void @__Block_byref_object_copy_
94+
// CHECK: [[NEWSLOT:%.*]] = getelementptr inbounds {{.*}} {{.*}}, i32 0, i32 6
95+
// CHECK: [[OLDSLOT:%.*]] = getelementptr inbounds {{.*}} {{.*}}, i32 0, i32 6
96+
// CHECK: [[LOAD:%.*]] = load ptr, ptr [[OLDSLOT]],
97+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[OLDSLOT]] to i64
98+
// CHECK: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 60)
99+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[NEWSLOT]] to i64
100+
// CHECK: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 60)
101+
// CHECK: [[T0:%.*]] = icmp ne ptr [[LOAD]], null
102+
// CHECK: br i1 [[T0]]
103+
// CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64
104+
// CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]])
105+
// CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
106+
// CHECK: [[T0:%.*]] = phi
107+
// CHECK: store ptr [[T0]], ptr [[NEWSLOT]]

clang/test/Sema/ptrauth-qualifier.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,45 @@ static_assert(_Generic(typeof(overload_func(&ptr0)), int : 1, default : 0));
147147
static_assert(_Generic(typeof(overload_func(&valid0)), float : 1, default : 0));
148148

149149
void func(int array[__ptrauth(VALID_DATA_KEY) 10]); // expected-error {{'__ptrauth' qualifier only applies to pointer types; 'int[10]' is invalid}}
150+
151+
struct S0 { // expected-note 4 {{struct S0' has subobjects that are non-trivial to copy}}
152+
intp __ptrauth(1, 1, 50) f0; // expected-note 4 {{f0 has type '__ptrauth(1,1,50) intp' (aka 'int *__ptrauth(1,1,50)') that is non-trivial to copy}}
153+
};
154+
155+
union U0 { // expected-note 4 {{union U0' has subobjects that are non-trivial to copy}}
156+
struct S0 s0;
157+
};
158+
159+
struct S1 {
160+
intp __ptrauth(1, 0, 50) f0;
161+
};
162+
163+
union U1 {
164+
struct S1 s1;
165+
};
166+
167+
union U2 { // expected-note 2 {{union U2' has subobjects that are non-trivial to copy}}
168+
intp __ptrauth(1, 1, 50) f0; // expected-note 2 {{f0 has type '__ptrauth(1,1,50) intp' (aka 'int *__ptrauth(1,1,50)') that is non-trivial to copy}}
169+
intp __ptrauth(1, 0, 50) f1;
170+
};
171+
172+
struct S2 { // expected-note 2 {{struct S2' has subobjects that are non-trivial to copy}}
173+
intp __ptrauth(1, 1, 50) f0[4]; // expected-note 2 {{f0 has type '__ptrauth(1,1,50) intp' (aka 'int *__ptrauth(1,1,50)') that is non-trivial to copy}}
174+
};
175+
176+
union U3 { // expected-note 2 {{union U3' has subobjects that are non-trivial to copy}}
177+
struct S2 s2;
178+
};
179+
180+
struct S4 {
181+
union U0 u0;
182+
};
183+
184+
union U0 foo0(union U0); // expected-error {{cannot use type 'union U0' for function/method return since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'union U0' for a function/method parameter since it is a union that is non-trivial to copy}}
185+
union U1 foo1(union U1);
186+
187+
union U2 foo2(union U2); // expected-error {{cannot use type 'union U2' for function/method return since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'union U2' for a function/method parameter since it is a union that is non-trivial to copy}}
188+
189+
union U3 foo3(union U3); // expected-error {{cannot use type 'union U3' for function/method return since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'union U3' for a function/method parameter since it is a union that is non-trivial to copy}}
190+
191+
struct S4 foo4(struct S4); // expected-error {{cannot use type 'struct S4' for function/method return since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'struct S4' for a function/method parameter since it contains a union that is non-trivial to copy}}

clang/test/SemaCXX/ptrauth-qualifier.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,21 @@ namespace test_concept {
211211
func(&p2); // expected-error {{no matching function for call to 'func'}}
212212
}
213213
}
214+
215+
template <class A, class B> constexpr int test_ptrauth_conflict() {
216+
A *a = nullptr;
217+
B *b = nullptr;
218+
a = b; // #BtoA
219+
b = a; // #AtoB
220+
return 0;
221+
}
222+
223+
constexpr int no_ptrauth = test_ptrauth_conflict<int *, int *>();
224+
constexpr int matching_ptrauth =
225+
test_ptrauth_conflict<int * __ptrauth(1,1,123), int * __ptrauth(1,1,123)>();
226+
constexpr int mismatching_ptrauth =
227+
test_ptrauth_conflict<int * __ptrauth(2,1,1024), int * __ptrauth(1,1,123)>(); // #FailedConstExpr
228+
// 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}}

0 commit comments

Comments
 (0)