From: Douglas Gregor Date: Fri, 17 Jun 2011 16:37:20 +0000 (+0000) Subject: When emitting a compound literal of POD type, continue to emit a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=673e98b4814642eb040a661fcc0f7953edd4c150;p=clang When emitting a compound literal of POD type, continue to emit a separate aggregate temporary and then memcpy it over to the destination. This fixes a regression I introduced with r133235, where the compound literal on the RHS of an assignment makes use of the structure on the LHS of the assignment. I'm deeply suspicious of AggExprEmitter::VisitBinAssign()'s optimization where it emits the RHS of an aggregate assignment directly into the LHS lvalue without checking whether there is any aliasing between the LHS/RHS. However, I'm not in a position to revisit this now. Big thanks to Eli for finding the regression! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133261 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 694316983e..b1ac731f21 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -247,6 +247,16 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) { void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + if (E->getType().isPODType(CGF.getContext())) { + // For a POD type, just emit a load of the lvalue + a copy, because our + // compound literal might alias the destination. + // FIXME: This is a band-aid; the real problem appears to be in our handling + // of assignments, where we store directly into the LHS without checking + // whether anything in the RHS aliases. + EmitAggLoadOfLValue(E); + return; + } + AggValueSlot Slot = EnsureSlot(E->getType()); CGF.EmitAggExpr(E->getInitializer(), Slot); } diff --git a/test/CodeGen/compound-literal.c b/test/CodeGen/compound-literal.c index 4b995dbfef..6d602989ad 100644 --- a/test/CodeGen/compound-literal.c +++ b/test/CodeGen/compound-literal.c @@ -1,12 +1,33 @@ -// RUN: %clang_cc1 < %s -emit-llvm +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s int* a = &(int){1}; struct s {int a, b, c;} * b = &(struct s) {1, 2, 3}; // Not working; complex constants are broken // _Complex double * x = &(_Complex double){1.0f}; -int xxx() { +void xxx() { int* a = &(int){1}; struct s {int a, b, c;} * b = &(struct s) {1, 2, 3}; _Complex double * x = &(_Complex double){1.0f}; } + +// CHECK: define void @f() +void f() { + typedef struct S { int x,y; } S; + // CHECK: [[S:%[a-zA-Z0-9.]+]] = alloca [[STRUCT:%[a-zA-Z0-9.]+]], + struct S s; + // CHECK-NEXT: [[COMPOUNDLIT:%[a-zA-Z0-9.]+]] = alloca [[STRUCT]] + // CHECK-NEXT: [[CX:%[a-zA-Z0-9.]+]] = getelementptr inbounds [[STRUCT]]* [[COMPOUNDLIT]], i32 0, i32 0 + // CHECK-NEXT: [[SY:%[a-zA-Z0-9.]+]] = getelementptr inbounds [[STRUCT]]* [[S]], i32 0, i32 1 + // CHECK-NEXT: [[TMP:%[a-zA-Z0-9.]+]] = load i32* [[SY]] + // CHECK-NEXT: store i32 [[TMP]], i32* [[CX]] + // CHECK-NEXT: [[CY:%[a-zA-Z0-9.]+]] = getelementptr inbounds [[STRUCT]]* [[COMPOUNDLIT]], i32 0, i32 1 + // CHECK-NEXT: [[SX:%[a-zA-Z0-9.]+]] = getelementptr inbounds [[STRUCT]]* [[S]], i32 0, i32 0 + // CHECK-NEXT: [[TMP:%[a-zA-Z0-9.]+]] = load i32* [[SX]] + // CHECK-NEXT: store i32 [[TMP]], i32* [[CY]] + // CHECK-NEXT: [[SI8:%[a-zA-Z0-9.]+]] = bitcast [[STRUCT]]* [[S]] to i8* + // CHECK-NEXT: [[COMPOUNDLITI8:%[a-zA-Z0-9.]+]] = bitcast [[STRUCT]]* [[COMPOUNDLIT]] to i8* + // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SI8]], i8* [[COMPOUNDLITI8]], i64 8, i32 4, i1 false) + s = (S){s.y,s.x}; + // CHECK-NEXT: ret void +}