]> granicus.if.org Git - clang/commitdiff
fix rdar://8340348, a miscompile of boost that was exposed by r109848.
authorChris Lattner <sabre@nondot.org>
Mon, 23 Aug 2010 05:26:13 +0000 (05:26 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 23 Aug 2010 05:26:13 +0000 (05:26 +0000)
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

lib/CodeGen/CGExpr.cpp
test/CodeGenCXX/x86_64-arguments.cpp

index 0cfd8b6ef9ce48a83966353808219b4e0a01b9d6..cf7d01bcd05290ddca15d7f0059a561990a795ae 100644 (file)
@@ -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)));
index 13f03478f019f0c11157b06414e5bbf5e0d32c17..cd097680d370ccc8e6ccfee5b142c7bcc30628fd 100644 (file)
@@ -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"
+}