From: Chris Lattner Date: Mon, 23 Aug 2010 05:26:13 +0000 (+0000) Subject: fix rdar://8340348, a miscompile of boost that was exposed by r109848. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b6c504b9101251bcb364dd9becbb887c97db27d3;p=clang fix rdar://8340348, a miscompile of boost that was exposed by r109848. That revision started classifying truly empty structs like "Y" and "X" as being NoClass/NoClass and turning them into 'ignore'. The call code turns around and allocates space for the ignored argument with GetUndefRValue. The bug is that GetUndefRValue would return the address as undef, instead of returning an object with a defined address but undefined contents. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111794 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 0cfd8b6ef9..cf7d01bcd0 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -441,9 +441,12 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) { return RValue::getComplex(std::make_pair(U, U)); } + // If this is a use of an undefined aggregate type, the aggregate must have an + // identifiable address. Just because the contents of the value are undefined + // doesn't mean that the address can't be taken and compared. if (hasAggregateLLVMType(Ty)) { - const llvm::Type *LTy = llvm::PointerType::getUnqual(ConvertType(Ty)); - return RValue::getAggregate(llvm::UndefValue::get(LTy)); + llvm::Value *DestPtr = CreateMemTemp(Ty, "undef.agg.tmp"); + return RValue::getAggregate(DestPtr); } return RValue::get(llvm::UndefValue::get(ConvertType(Ty))); diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 13f03478f0..cd097680d3 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -76,3 +76,27 @@ namespace PR5179 { return b2.b1.pa; } } + +namespace test5 { + struct Xbase { }; + struct Empty { }; + struct Y; + struct X : public Xbase { + Empty empty; + Y f(); + }; + struct Y : public X { + Empty empty; + }; + X getX(); + int takeY(const Y&, int y); + void g() { + // rdar://8340348 - The temporary for the X object needs to have a defined + // address when passed into X::f as 'this'. + takeY(getX().f(), 42); + } + // CHECK: void @_ZN5test51gEv() + // CHECK: alloca %"struct.test5::Y" + // CHECK: alloca %"struct.test5::X" + // CHECK: alloca %"struct.test5::Y" +}