diff options
author | John McCall <rjmccall@apple.com> | 2010-08-22 21:01:12 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-08-22 21:01:12 +0000 |
commit | f16aa103d3afd42fbca2ab346f191bf745cec092 (patch) | |
tree | af2fd36fb705f0d900afe40561c89341546459b6 | |
parent | b76495673a381d209410d78af9d969bb3ae0a95a (diff) |
Go back to asking CodeGenTypes whether a type is zero-initializable.
Make CGT defer to the ABI on all member pointer types.
This requires giving CGT a handle to the ABI.
It's way easier to make that work if we avoid lazily creating the ABI.
Make it so.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111786 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGRecordLayout.h | 13 | ||||
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 47 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 18 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 27 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.h | 17 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 13 | ||||
-rw-r--r-- | test/CodeGen/bitfield-2.c | 8 |
13 files changed, 96 insertions, 118 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index b805d136c4..8fb3fe3d4b 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -393,10 +393,7 @@ llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { MD->getParent()->getTypeForDecl())); } -bool CGCXXABI::RequiresNonZeroInitializer(QualType T) { - return false; -} - -bool CGCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) { - return RequiresNonZeroInitializer(QualType(D->getTypeForDecl(), 0)); +bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { + // Fake answer. + return true; } diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index d0bb0e864f..c248f1d64d 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -59,10 +59,10 @@ public: // Manipulations on constant expressions. - /// \brief Returns true if zero-initializing the given type requires - /// a constant other than the LLVM null value. - virtual bool RequiresNonZeroInitializer(QualType T); - virtual bool RequiresNonZeroInitializer(const CXXRecordDecl *D); + /// \brief Returns true if the given member pointer can be + /// zero-initialized (in the C++ sense) with an LLVM + /// zeroinitialized. + virtual bool isZeroInitializable(const MemberPointerType *MPT); virtual llvm::Constant * EmitMemberFunctionPointerConversion(llvm::Constant *C, diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index e8bc9b4f9a..feaf467636 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -547,8 +547,7 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, if (!E->hasInitializer() || Ctor->getParent()->isEmpty()) return; - if (!CGF.CGM.getCXXABI().RequiresNonZeroInitializer( - E->getAllocatedType())) { + if (CGF.CGM.getTypes().isZeroInitializable(E->getAllocatedType())) { // Optimization: since zero initialization will just set the memory // to all zeroes, generate a single memset to do it in one shot. EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr, diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index b97e725ae8..48826492df 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -958,8 +958,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, uint64_t StartOffset) { assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!"); - if (!CGM.getLangOptions().CPlusPlus || - !CGM.getCXXABI().RequiresNonZeroInitializer(T)) + if (CGM.getTypes().isZeroInitializable(T)) return; if (const ConstantArrayType *CAT = @@ -992,7 +991,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, continue; // Ignore bases that don't have any pointer to data members. - if (!CGM.getCXXABI().RequiresNonZeroInitializer(BaseDecl)) + if (CGM.getTypes().isZeroInitializable(BaseDecl)) continue; uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl); @@ -1006,7 +1005,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, E = RD->field_end(); I != E; ++I, ++FieldNo) { QualType FieldType = I->getType(); - if (!CGM.getCXXABI().RequiresNonZeroInitializer(FieldType)) + if (CGM.getTypes().isZeroInitializable(FieldType)) continue; uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo); @@ -1031,8 +1030,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T, } llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - if (!getLangOptions().CPlusPlus || - !getCXXABI().RequiresNonZeroInitializer(T)) + if (getTypes().isZeroInitializable(T)) return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { @@ -1076,7 +1074,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { continue; // Ignore bases that don't have any pointer to data members. - if (!getCXXABI().RequiresNonZeroInitializer(BaseDecl)) + if (getTypes().isZeroInitializable(BaseDecl)) continue; // Currently, all bases are arrays of i8. Figure out how many elements diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h index e95591e5cc..965fcc5201 100644 --- a/lib/CodeGen/CGRecordLayout.h +++ b/lib/CodeGen/CGRecordLayout.h @@ -174,20 +174,21 @@ private: /// Whether one of the fields in this record layout is a pointer to data /// member, or a struct that contains pointer to data member. - bool ContainsPointerToDataMember : 1; + bool IsZeroInitializable : 1; public: - CGRecordLayout(const llvm::Type *T, bool ContainsPointerToDataMember) - : LLVMType(T), ContainsPointerToDataMember(ContainsPointerToDataMember) {} + CGRecordLayout(const llvm::Type *T, bool IsZeroInitializable) + : LLVMType(T), IsZeroInitializable(IsZeroInitializable) {} /// \brief Return the LLVM type associated with this record. const llvm::Type *getLLVMType() const { return LLVMType; } - /// \brief Check whether this struct contains pointers to data members. - bool containsPointerToDataMember() const { - return ContainsPointerToDataMember; + /// \brief Check whether this struct can be C++ zero-initialized + /// with a zeroinitializer. + bool isZeroInitializable() const { + return IsZeroInitializable; } /// \brief Return llvm::StructType element number that corresponds to the diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 9f1687577c..ac1c2b5c74 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "CodeGenTypes.h" +#include "CGCXXABI.h" #include "llvm/DerivedTypes.h" #include "llvm/Type.h" #include "llvm/Support/Debug.h" @@ -45,10 +46,9 @@ public: typedef std::pair<const CXXRecordDecl *, unsigned> LLVMBaseInfo; llvm::SmallVector<LLVMBaseInfo, 16> LLVMNonVirtualBases; - /// ContainsPointerToDataMember - Whether one of the fields in this record - /// layout is a pointer to data member, or a struct that contains pointer to - /// data member. - bool ContainsPointerToDataMember; + /// IsZeroInitializable - Whether this struct can be C++ + /// zero-initialized with an LLVM zeroinitializer. + bool IsZeroInitializable; /// Packed - Whether the resulting LLVM struct will be packed or not. bool Packed; @@ -115,14 +115,14 @@ private: unsigned getTypeAlignment(const llvm::Type *Ty) const; - /// CheckForPointerToDataMember - Check if the given type contains a pointer + /// CheckZeroInitializable - Check if the given type contains a pointer /// to data member. - void CheckForPointerToDataMember(QualType T); - void CheckForPointerToDataMember(const CXXRecordDecl *RD); + void CheckZeroInitializable(QualType T); + void CheckZeroInitializable(const CXXRecordDecl *RD); public: CGRecordLayoutBuilder(CodeGenTypes &Types) - : ContainsPointerToDataMember(false), Packed(false), Types(Types), + : IsZeroInitializable(true), Packed(false), Types(Types), Alignment(0), AlignmentAsLLVMStruct(1), BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { } @@ -311,8 +311,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, return true; } - // Check if we have a pointer to data member in this field. - CheckForPointerToDataMember(D->getType()); + CheckZeroInitializable(D->getType()); assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!"); uint64_t FieldOffsetInBytes = FieldOffset / 8; @@ -458,7 +457,7 @@ void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl, return; } - CheckForPointerToDataMember(BaseDecl); + CheckZeroInitializable(BaseDecl); // FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can. AppendPadding(BaseOffset / 8, 1); @@ -603,9 +602,9 @@ unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const { return Types.getTargetData().getABITypeAlignment(Ty); } -void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) { +void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) { // This record already contains a member pointer. - if (ContainsPointerToDataMember) + if (!IsZeroInitializable) return; // Can only have member pointers if we're compiling C++. @@ -615,21 +614,17 @@ void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) { T = Types.getContext().getBaseElementType(T); if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { - if (!MPT->getPointeeType()->isFunctionType()) { - // We have a pointer to data member. - ContainsPointerToDataMember = true; - } + if (!Types.getCXXABI().isZeroInitializable(MPT)) + IsZeroInitializable = false; } else if (const RecordType *RT = T->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - - return CheckForPointerToDataMember(RD); + CheckZeroInitializable(RD); } } -void -CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) { +void CGRecordLayoutBuilder::CheckZeroInitializable(const CXXRecordDecl *RD) { // This record already contains a member pointer. - if (ContainsPointerToDataMember) + if (!IsZeroInitializable) return; // FIXME: It would be better if there was a way to explicitly compute the @@ -638,8 +633,8 @@ CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) { const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); - if (Layout.containsPointerToDataMember()) - ContainsPointerToDataMember = true; + if (!Layout.isZeroInitializable()) + IsZeroInitializable = false; } CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { @@ -652,7 +647,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { Builder.Packed); CGRecordLayout *RL = - new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember); + new CGRecordLayout(Ty, Builder.IsZeroInitializable); // Add all the non-virtual base field numbers. RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(), @@ -723,7 +718,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { void CGRecordLayout::print(llvm::raw_ostream &OS) const { OS << "<CGRecordLayout\n"; OS << " LLVMType:" << *LLVMType << "\n"; - OS << " ContainsPointerToDataMember:" << ContainsPointerToDataMember << "\n"; + OS << " IsZeroInitializable:" << IsZeroInitializable << "\n"; OS << " BitFields:[\n"; // Print bit-field infos in declaration order. diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 91442fa362..2b20dd9066 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -579,8 +579,7 @@ 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.getLangOptions().CPlusPlus && - CGM.getCXXABI().RequiresNonZeroInitializer(Ty)) { + if (!CGM.getTypes().isZeroInitializable(Ty)) { llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty); llvm::GlobalVariable *NullVariable = diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 2d9d57393e..f26fa3c610 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -41,6 +41,17 @@ using namespace clang; using namespace CodeGen; +static CGCXXABI &createCXXABI(CodeGenModule &CGM) { + switch (CGM.getContext().Target.getCXXABI()) { + case CXXABI_ARM: return *CreateARMCXXABI(CGM); + case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM); + case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM); + } + + llvm_unreachable("invalid C++ ABI kind"); + return *CreateItaniumCXXABI(CGM); +} + CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, llvm::Module &M, const llvm::TargetData &TD, @@ -48,8 +59,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, : BlockModule(C, M, TD, Types, *this), Context(C), Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M), TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags), - Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), - VTables(*this), Runtime(0), ABI(0), + ABI(createCXXABI(*this)), + Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI), + VTables(*this), Runtime(0), CFConstantStringClassRef(0), NSConstantStringClassRef(0), VMContext(M.getContext()), NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0), @@ -66,17 +78,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, else Runtime = CreateMacObjCRuntime(*this); - if (!Features.CPlusPlus) - ABI = 0; - else createCXXABI(); - // If debug info generation is enabled, create the CGDebugInfo object. DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0; } CodeGenModule::~CodeGenModule() { delete Runtime; - delete ABI; + delete &ABI; delete DebugInfo; } @@ -89,20 +97,6 @@ void CodeGenModule::createObjCRuntime() { Runtime = CreateMacObjCRuntime(*this); } -void CodeGenModule::createCXXABI() { - switch (Context.Target.getCXXABI()) { - case CXXABI_ARM: - ABI = CreateARMCXXABI(*this); - break; - case CXXABI_Itanium: - ABI = CreateItaniumCXXABI(*this); - break; - case CXXABI_Microsoft: - ABI = CreateMicrosoftCXXABI(*this); - break; - } -} - void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 426499d6eb..f44c8236fe 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -109,6 +109,7 @@ class CodeGenModule : public BlockModule { const llvm::TargetData &TheTargetData; mutable const TargetCodeGenInfo *TheTargetCodeGenInfo; Diagnostic &Diags; + CGCXXABI &ABI; CodeGenTypes Types; /// VTables - Holds information about C++ vtables. @@ -116,7 +117,6 @@ class CodeGenModule : public BlockModule { friend class CodeGenVTables; CGObjCRuntime* Runtime; - CGCXXABI* ABI; CGDebugInfo* DebugInfo; // WeakRefReferences - A set of references that have only been seen via @@ -189,8 +189,6 @@ class CodeGenModule : public BlockModule { /// Lazily create the Objective-C runtime void createObjCRuntime(); - /// Lazily create the C++ ABI - void createCXXABI(); llvm::LLVMContext &VMContext; @@ -228,15 +226,8 @@ public: /// been configured. bool hasObjCRuntime() { return !!Runtime; } - /// getCXXABI() - Return a reference to the configured - /// C++ ABI. - CGCXXABI &getCXXABI() { - if (!ABI) createCXXABI(); - return *ABI; - } - - /// hasCXXABI() - Return true iff a C++ ABI has been configured. - bool hasCXXABI() { return !!ABI; } + /// getCXXABI() - Return a reference to the configured C++ ABI. + CGCXXABI &getCXXABI() { return ABI; } llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) { return StaticLocalDeclMap[VD]; @@ -253,8 +244,7 @@ public: llvm::Module &getModule() const { return TheModule; } CodeGenTypes &getTypes() { return Types; } MangleContext &getMangleContext() { - if (!ABI) createCXXABI(); - return ABI->getMangleContext(); + return ABI.getMangleContext(); } CodeGenVTables &getVTables() { return VTables; } Diagnostic &getDiags() const { return Diags; } diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index d469b906fc..1402af14a5 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -13,6 +13,7 @@ #include "CodeGenTypes.h" #include "CGCall.h" +#include "CGCXXABI.h" #include "CGRecordLayout.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -26,9 +27,10 @@ using namespace clang; using namespace CodeGen; CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M, - const llvm::TargetData &TD, const ABIInfo &Info) + const llvm::TargetData &TD, const ABIInfo &Info, + CGCXXABI &CXXABI) : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD), - TheABIInfo(Info) { + TheABIInfo(Info), TheCXXABI(CXXABI) { } CodeGenTypes::~CodeGenTypes() { @@ -491,31 +493,34 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *TD) const { return *Layout; } -bool CodeGenTypes::ContainsPointerToDataMember(QualType T) { +bool CodeGenTypes::isZeroInitializable(QualType T) { // No need to check for member pointers when not compiling C++. if (!Context.getLangOptions().CPlusPlus) - return false; + return true; T = Context.getBaseElementType(T); + // Records are non-zero-initializable if they contain any + // non-zero-initializable subobjects. if (const RecordType *RT = T->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - - return ContainsPointerToDataMember(RD); + return isZeroInitializable(RD); } - + + // We have to ask the ABI about member pointers. if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) - return !MPT->getPointeeType()->isFunctionType(); + return getCXXABI().isZeroInitializable(MPT); - return false; + // Everything else is okay. + return true; } -bool CodeGenTypes::ContainsPointerToDataMember(const CXXRecordDecl *RD) { +bool CodeGenTypes::isZeroInitializable(const CXXRecordDecl *RD) { // FIXME: It would be better if there was a way to explicitly compute the // record layout instead of converting to a type. ConvertTagDeclType(RD); const CGRecordLayout &Layout = getCGRecordLayout(RD); - return Layout.containsPointerToDataMember(); + return Layout.isZeroInitializable(); } diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index 54019f9243..dac235f823 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -50,6 +50,7 @@ namespace clang { typedef CanQual<Type> CanQualType; namespace CodeGen { + class CGCXXABI; class CGRecordLayout; /// CodeGenTypes - This class organizes the cross-module state that is used @@ -60,6 +61,7 @@ class CodeGenTypes { llvm::Module& TheModule; const llvm::TargetData& TheTargetData; const ABIInfo& TheABIInfo; + CGCXXABI &TheCXXABI; llvm::SmallVector<std::pair<QualType, llvm::OpaqueType *>, 8> PointersToResolve; @@ -101,13 +103,14 @@ private: public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD, - const ABIInfo &Info); + const ABIInfo &Info, CGCXXABI &CXXABI); ~CodeGenTypes(); const llvm::TargetData &getTargetData() const { return TheTargetData; } const TargetInfo &getTarget() const { return Target; } ASTContext &getContext() const { return Context; } const ABIInfo &getABIInfo() const { return TheABIInfo; } + CGCXXABI &getCXXABI() const { return TheCXXABI; } llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } /// ConvertType - Convert type T into a llvm::Type. @@ -204,13 +207,13 @@ public: // These are internal details of CGT that shouldn't be used externally. void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys, bool IsRecursive); - /// ContainsPointerToDataMember - Return whether the given type contains a - /// pointer to a data member. - bool ContainsPointerToDataMember(QualType T); + /// IsZeroInitializable - Return whether a type can be + /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. + bool isZeroInitializable(QualType T); - /// ContainsPointerToDataMember - Return whether the record decl contains a - /// pointer to a data member. - bool ContainsPointerToDataMember(const CXXRecordDecl *RD); + /// IsZeroInitializable - Return whether a record type can be + /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer. + bool isZeroInitializable(const CXXRecordDecl *RD); }; } // end namespace CodeGen diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 4aa433c7ca..37244398f3 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -41,8 +41,7 @@ public: return MangleCtx; } - bool RequiresNonZeroInitializer(QualType T); - bool RequiresNonZeroInitializer(const CXXRecordDecl *D); + bool isZeroInitializable(const MemberPointerType *MPT); llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, llvm::Value *&This, @@ -460,10 +459,8 @@ ItaniumCXXABI::EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF, return Result; } -bool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) { - return CGM.getTypes().ContainsPointerToDataMember(T); -} - -bool ItaniumCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) { - return CGM.getTypes().ContainsPointerToDataMember(D); +/// The Itanium ABI requires non-zero initialization only for data +/// member pointers, for which '0' is a valid offset. +bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { + return MPT->getPointeeType()->isFunctionType(); } diff --git a/test/CodeGen/bitfield-2.c b/test/CodeGen/bitfield-2.c index e91859fb72..8de432faa8 100644 --- a/test/CodeGen/bitfield-2.c +++ b/test/CodeGen/bitfield-2.c @@ -12,7 +12,7 @@ // CHECK-RECORD: Record: struct s0 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:<{ [3 x i8] }> -// CHECK-RECORD: ContainsPointerToDataMember:0 +// CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ // CHECK-RECORD: <CGBitFieldInfo Size:24 IsSigned:1 // CHECK-RECORD: NumComponents:2 Components: [ @@ -57,7 +57,7 @@ unsigned long long test_0() { // CHECK-RECORD: Record: struct s1 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:<{ [2 x i8], i8 }> -// CHECK-RECORD: ContainsPointerToDataMember:0 +// CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ // CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1 // CHECK-RECORD: NumComponents:1 Components: [ @@ -114,7 +114,7 @@ unsigned long long test_1() { // CHECK-RECORD: Record: union u2 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:<{ i8 }> -// CHECK-RECORD: ContainsPointerToDataMember:0 +// CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ // CHECK-RECORD: <CGBitFieldInfo Size:3 IsSigned:0 // CHECK-RECORD: NumComponents:1 Components: [ @@ -289,7 +289,7 @@ _Bool test_6() { // CHECK-RECORD: Record: struct s7 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:{ i32, i32, i32, i8, [3 x i8], [4 x i8], [12 x i8] } -// CHECK-RECORD: ContainsPointerToDataMember:0 +// CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ // CHECK-RECORD: <CGBitFieldInfo Size:5 IsSigned:1 // CHECK-RECORD: NumComponents:1 Components: [ |