aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGClass.cpp2
-rw-r--r--lib/CodeGen/CGExpr.cpp2
-rw-r--r--lib/CodeGen/CGExprAgg.cpp6
-rw-r--r--lib/CodeGen/CGObjC.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp21
-rw-r--r--lib/CodeGen/CodeGenFunction.h6
-rw-r--r--test/CodeGenCXX/pointers-to-data-members.cpp29
7 files changed, 56 insertions, 12 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 82c72288d9..587a68beb2 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/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.EmitMemSetToZero(LHS.getAddress(), Field->getType());
+ CGF.EmitNullInitialization(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/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 17d85dc9d9..d67618bfca 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1856,7 +1856,7 @@ LValue CodeGenFunction::EmitNullInitializationLValue(
const CXXZeroInitValueExpr *E) {
QualType Ty = E->getType();
LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty));
- EmitMemSetToZero(LV.getAddress(), Ty);
+ EmitNullInitialization(LV.getAddress(), Ty);
return LV;
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 7b0c316c9d..18c69121d4 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -582,14 +582,10 @@ 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.EmitMemSetToZero(LV.getAddress(), T);
+ CGF.EmitNullInitialization(LV.getAddress(), T);
}
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 6efba44b0e..7c842a9498 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -640,7 +640,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fast enumeration state.
QualType StateTy = getContext().getObjCFastEnumerationStateType();
llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
- EmitMemSetToZero(StatePtr, StateTy);
+ EmitNullInitialization(StatePtr, StateTy);
// Number of elements in the items array.
static const unsigned NumItems = 16;
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index d3bf1645a0..222dcc4b8f 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -472,7 +472,23 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
CGM.ErrorUnsupported(S, Type, OmitOnError);
}
-void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
+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>()) {
@@ -481,6 +497,9 @@ void CodeGenFunction::EmitMemSetToZero(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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index dcc65cc2e8..944aa48044 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -747,8 +747,10 @@ public:
llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
llvm::BasicBlock *GetIndirectGotoBlock();
- /// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
- void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty);
+ /// 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);
// 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/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp
index cab06dbd3d..ac238fb8fc 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/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,3 +118,30 @@ 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;
+}
+
+}