diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 587a68beb225..82c72288d918 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -465,7 +465,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, /*IsInitializer=*/true); CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); } else if (FieldType->isArrayType() && !MemberInit->getInit()) { - CGF.EmitNullInitialization(LHS.getAddress(), Field->getType()); + CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType()); } else if (!CGF.hasAggregateLLVMType(Field->getType())) { RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true)); CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a4a4bda723d8..74e64e59a5a8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1844,7 +1844,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue( const CXXZeroInitValueExpr *E) { QualType Ty = E->getType(); LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty)); - EmitNullInitialization(LV.getAddress(), Ty); + EmitMemSetToZero(LV.getAddress(), Ty); return LV; } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 4a7e6ecc42d9..3bf2f8a52025 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -573,10 +573,14 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) { llvm::Value *Null = llvm::Constant::getNullValue(CGF.ConvertType(T)); CGF.EmitStoreThroughLValue(RValue::get(Null), LV, T); } else { + // Otherwise, just memset the whole thing to zero. This is legal + // because in LLVM, all default initializers are guaranteed to have a + // bit pattern of all zeros. + // FIXME: That isn't true for member pointers! // There's a potential optimization opportunity in combining // memsets; that would be easy for arrays, but relatively // difficult for structures with the current code. - CGF.EmitNullInitialization(LV.getAddress(), T); + CGF.EmitMemSetToZero(LV.getAddress(), T); } } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index b07a02b5b3c7..2f70969e9490 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -123,10 +123,10 @@ public: return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } Value *VisitCXXZeroInitValueExpr(const CXXZeroInitValueExpr *E) { - return CGF.CGM.EmitNullConstant(E->getType()); + return llvm::Constant::getNullValue(ConvertType(E->getType())); } Value *VisitGNUNullExpr(const GNUNullExpr *E) { - return CGF.CGM.EmitNullConstant(E->getType()); + return llvm::Constant::getNullValue(ConvertType(E->getType())); } Value *VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index d44c56fcf68d..674f50234e55 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -632,7 +632,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // Fast enumeration state. QualType StateTy = getContext().getObjCFastEnumerationStateType(); llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); - EmitNullInitialization(StatePtr, StateTy); + EmitMemSetToZero(StatePtr, StateTy); // Number of elements in the items array. static const unsigned NumItems = 16; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 222dcc4b8f5e..d3bf1645a026 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -472,23 +472,7 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type, CGM.ErrorUnsupported(S, Type, OmitOnError); } -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; - } - - +void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { // Ignore empty classes in C++. if (getContext().getLangOptions().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { @@ -497,9 +481,6 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { } } - // 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); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8e68949f3023..bac05ba70512 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -747,10 +747,8 @@ public: llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L); llvm::BasicBlock *GetIndirectGotoBlock(); - /// EmitNullInitialization - Generate code to set a value of the given type to - /// null, If the type contains data member pointers, they will be initialized - /// to -1 in accordance with the Itanium C++ ABI. - void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty); + /// EmitMemSetToZero - Generate code to memset a value of the given type to 0. + void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty); // EmitVAArg - Generate code to get an argument from the passed in pointer // and update it accordingly. The return value is a pointer to the argument. diff --git a/clang/test/CodeGenCXX/pointers-to-data-members.cpp b/clang/test/CodeGenCXX/pointers-to-data-members.cpp index ac238fb8fc6c..cab06dbd3d37 100644 --- a/clang/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/clang/test/CodeGenCXX/pointers-to-data-members.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -O3 | FileCheck --check-prefix=CHECK-O3 %s + struct A { int a; int b; }; struct B { int b; }; struct C : B, A { }; @@ -118,30 +118,3 @@ A::A() : a() {} } -namespace PR7139 { - -struct pair { - int first; - int second; -}; - -typedef int pair::*ptr_to_member_type; - -struct ptr_to_member_struct { - ptr_to_member_type data; - int i; -}; - -struct A { - ptr_to_member_struct a; - - A() : a() {} -}; - -// CHECK-O3: define zeroext i1 @_ZN6PR71395checkEv() nounwind readnone -bool check() { - // CHECK-O3: ret i1 true - return A().a.data == 0; -} - -}