Skip to content

Commit 9361113

Browse files
authored
[CodeGen] Remove the check that allowed non-POD compound literals to be directly evaluated into the destination even when it might alias the source (#167344)
Evaluate all aggregate compound literals into a temporary and then copy it to the destination if aliasing is possible. This fixes a latent issue exposed by #154490, where evaluating the RHS directly into the destination could ignore potential aliasing. rdar://164094548
1 parent 603ba84 commit 9361113

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

clang/lib/CodeGen/CGExprAgg.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -755,10 +755,9 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
755755

756756
void
757757
AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
758-
if (Dest.isPotentiallyAliased() &&
759-
E->getType().isPODType(CGF.getContext())) {
760-
// For a POD type, just emit a load of the lvalue + a copy, because our
761-
// compound literal might alias the destination.
758+
if (Dest.isPotentiallyAliased()) {
759+
// Just emit a load of the lvalue + a copy, because our compound literal
760+
// might alias the destination.
762761
EmitAggLoadOfLValue(E);
763762
return;
764763
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// RUN: %clang_cc1 -triple arm64e-apple-ios18 -fptrauth-calls -fptrauth-intrinsics -fobjc-arc -emit-llvm -o - %s | FileCheck %s
2+
3+
// CHECK: %[[STRUCT_S0:.*]] = type { i32, i32, ptr }
4+
// CHECK: %[[STRUCT_S1:.*]] = type { ptr, ptr }
5+
6+
// This struct isn't POD because it has an address-discriminated ptrauth
7+
// field.
8+
typedef struct {
9+
int f0, f1;
10+
int * __ptrauth(1,1,50) f2;
11+
} S0;
12+
13+
// This struct isn't POD because it has an address-discriminated ptrauth
14+
// field and an ARC ObjC pointer field.
15+
typedef struct {
16+
id f0;
17+
int * __ptrauth(1,1,50) f1;
18+
} S1;
19+
20+
// CHECK: define void @compound_literal_assignment0(ptr noundef %[[P:.*]])
21+
// CHECK: %[[P_ADDR:.*]] = alloca ptr, align 8
22+
// CHECK-NEXT: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_S0]], align 8
23+
// CHECK-NEXT: store ptr %[[P]], ptr %[[P_ADDR]], align 8
24+
// CHECK-NEXT: %[[V0:.*]] = load ptr, ptr %[[P_ADDR]], align 8
25+
// CHECK-NEXT: %[[F0:.*]] = getelementptr inbounds nuw %[[STRUCT_S0]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0
26+
// CHECK-NEXT: %[[V1:.*]] = load ptr, ptr %[[P_ADDR]], align 8
27+
// CHECK-NEXT: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_S0]], ptr %[[V1]], i32 0, i32 1
28+
// CHECK-NEXT: %[[V2:.*]] = load i32, ptr %[[F1]], align 4
29+
// CHECK-NEXT: store i32 %[[V2]], ptr %[[F0]], align 8
30+
// CHECK-NEXT: %[[F11:.*]] = getelementptr inbounds nuw %[[STRUCT_S0]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1
31+
// CHECK-NEXT: %[[V3:.*]] = load ptr, ptr %[[P_ADDR]], align 8
32+
// CHECK-NEXT: %[[F02:.*]] = getelementptr inbounds nuw %[[STRUCT_S0]], ptr %[[V3]], i32 0, i32 0
33+
// CHECK-NEXT: %[[V4:.*]] = load i32, ptr %[[F02]], align 8
34+
// CHECK-NEXT: store i32 %[[V4]], ptr %[[F11]], align 4
35+
// CHECK-NEXT: %[[F2:.*]] = getelementptr inbounds nuw %[[STRUCT_S0]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 2
36+
// CHECK-NEXT: store ptr null, ptr %[[F2]], align 8
37+
// CHECK-NEXT: call void @__copy_assignment_8_8_t0w8_pa1_50_8(ptr %[[V0]], ptr %[[_COMPOUNDLITERAL]])
38+
// CHECK-NEXT: ret void
39+
40+
void compound_literal_assignment0(S0 *p) {
41+
*p = (S0){.f0 = p->f1, .f1 = p->f0};
42+
}
43+
44+
// CHECK: define void @compound_literal_assignment1(ptr noundef %[[P:.*]])
45+
// CHECK: %[[P_ADDR:.*]] = alloca ptr, align 8
46+
// CHECK-NEXT: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_S1]], align 8
47+
// CHECK-NEXT: store ptr %[[P]], ptr %[[P_ADDR]], align 8
48+
// CHECK-NEXT: %[[V0:.*]] = load ptr, ptr %[[P_ADDR]], align 8
49+
// CHECK-NEXT: %[[F0:.*]] = getelementptr inbounds nuw %[[STRUCT_S1]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0
50+
// CHECK-NEXT: store ptr null, ptr %[[F0]], align 8
51+
// CHECK-NEXT: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_S1]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1
52+
// CHECK-NEXT: store ptr null, ptr %[[F1]], align 8
53+
// CHECK-NEXT: call void @__copy_assignment_8_8_s0_pa1_50_8(ptr %[[V0]], ptr %[[_COMPOUNDLITERAL]])
54+
// CHECK-NEXT: call void @__destructor_8_s0(ptr %[[_COMPOUNDLITERAL]])
55+
// CHECK-NEXT: ret void
56+
57+
void compound_literal_assignment1(S1 *p) {
58+
*p = (S1){};
59+
}

0 commit comments

Comments
 (0)