[cfe-commits] r110511 - in /cfe/trunk: lib/CodeGen/CodeGenFunction.cpp test/CodeGenCXX/value-init.cpp

John McCall rjmccall at apple.com
Sat Aug 7 01:21:30 PDT 2010


Author: rjmccall
Date: Sat Aug  7 03:21:30 2010
New Revision: 110511

URL: http://llvm.org/viewvc/llvm-project?rev=110511&view=rev
Log:
Inline a special case of EmitAggregateCopy into EmitNullInitialization
to avoid the awesome-but-wrong-in-this-case assertion in the canon EAC.
Fixes PR7834.

Also fix a subtle address-space bug in the memset path.


Modified:
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/test/CodeGenCXX/value-init.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=110511&r1=110510&r2=110511&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sat Aug  7 03:21:30 2010
@@ -545,21 +545,6 @@
 
 void
 CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
-  // If the type contains a pointer to data member we can't memset it to zero.
-  // Instead, create a null constant and copy it to the destination.
-  if (CGM.getTypes().ContainsPointerToDataMember(Ty)) {
-    llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
-    
-    llvm::GlobalVariable *NullVariable = 
-      new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
-                               /*isConstant=*/true, 
-                               llvm::GlobalVariable::PrivateLinkage,
-                               NullConstant, llvm::Twine());
-    EmitAggregateCopy(DestPtr, NullVariable, Ty, /*isVolatile=*/false);
-    return;
-  } 
-  
-
   // Ignore empty classes in C++.
   if (getContext().getLangOptions().CPlusPlus) {
     if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -567,29 +552,58 @@
         return;
     }
   }
-  
-  // Otherwise, just memset the whole thing to zero.  This is legal
-  // because in LLVM, all default initializers (other than the ones we just
-  // handled above) are guaranteed to have a bit pattern of all zeros.
-  const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+
+  // Cast the dest ptr to the appropriate i8 pointer type.
+  unsigned DestAS =
+    cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+  const llvm::Type *BP =
+    llvm::Type::getInt8PtrTy(VMContext, DestAS);
   if (DestPtr->getType() != BP)
     DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
 
   // Get size and alignment info for this aggregate.
   std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty);
+  uint64_t Size = TypeInfo.first;
+  unsigned Align = TypeInfo.second;
 
   // Don't bother emitting a zero-byte memset.
-  if (TypeInfo.first == 0)
+  if (Size == 0)
     return;
 
+  llvm::ConstantInt *SizeVal = llvm::ConstantInt::get(IntPtrTy, Size / 8);
+  llvm::ConstantInt *AlignVal = Builder.getInt32(Align / 8);
+
+  // If the type contains a pointer to data member we can't memset it to zero.
+  // Instead, create a null constant and copy it to the destination.
+  if (CGM.getTypes().ContainsPointerToDataMember(Ty)) {
+    llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
+
+    llvm::GlobalVariable *NullVariable = 
+      new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
+                               /*isConstant=*/true, 
+                               llvm::GlobalVariable::PrivateLinkage,
+                               NullConstant, llvm::Twine());
+    llvm::Value *SrcPtr =
+      Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy());
+
+    // FIXME: variable-size types?
+
+    // Get and call the appropriate llvm.memcpy overload.
+    llvm::Constant *Memcpy =
+      CGM.getMemCpyFn(DestPtr->getType(), SrcPtr->getType(), IntPtrTy);
+    Builder.CreateCall5(Memcpy, DestPtr, SrcPtr, SizeVal, AlignVal,
+                        /*volatile*/ Builder.getFalse());
+    return;
+  } 
+  
+  // Otherwise, just memset the whole thing to zero.  This is legal
+  // because in LLVM, all default initializers (other than the ones we just
+  // handled above) are guaranteed to have a bit pattern of all zeros.
+
   // FIXME: Handle variable sized types.
   Builder.CreateCall5(CGM.getMemSetFn(BP, IntPtrTy), DestPtr,
-                 llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)),
-                      // TypeInfo.first describes size in bits.
-                      llvm::ConstantInt::get(IntPtrTy, TypeInfo.first/8),
-                      llvm::ConstantInt::get(Int32Ty, TypeInfo.second/8),
-                      llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext),
-                                             0));
+                      Builder.getInt8(0),
+                      SizeVal, AlignVal, /*volatile*/ Builder.getFalse());
 }
 
 llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {

Modified: cfe/trunk/test/CodeGenCXX/value-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/value-init.cpp?rev=110511&r1=110510&r2=110511&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/value-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/value-init.cpp Sat Aug  7 03:21:30 2010
@@ -49,3 +49,21 @@
   enum_holder_and_int();
   // CHECK-NEXT: ret void
 }
+
+// PR7834: don't crash.
+namespace test1 {
+  struct A {
+    int A::*f;
+    A();
+    A(const A&);
+    A &operator=(const A &);
+  };
+
+  struct B {
+    A base;
+  };
+
+  void foo() {
+    B();
+  }
+}





More information about the cfe-commits mailing list