зеркало из https://github.com/microsoft/clang-1.git
Re-land the fix for PR7139.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104446 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
fb2db4657d
Коммит
1884eb0b5c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче