From: Fariborz Jahanian Date: Mon, 23 Aug 2010 18:51:39 +0000 (+0000) Subject: Support for IRGen of synthesize bitfield ivars in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=000835d0b04345c0014c603fe6339b3bc154050e;p=clang Support for IRGen of synthesize bitfield ivars in objc-nonfragile-abi2 (radar 7824380). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111823 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 2790c79417..a42c3894ed 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1269,6 +1269,10 @@ public: /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) /// and returns the result type of that conversion. QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); + + void ResetObjCLayout(const ObjCContainerDecl *CD) { + ObjCLayouts[CD] = 0; + } //===--------------------------------------------------------------------===// // Integer Predicates @@ -1409,7 +1413,7 @@ private: const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); - + private: /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index c48e229599..351f8bdae2 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -919,6 +919,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + /// \brief The location of the '@' in '@interface' SourceLocation AtLoc; @@ -929,8 +932,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id) : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id), - ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc), - CategoryNameLoc(CategoryNameLoc) { + ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false), + AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) { } public: @@ -982,6 +985,9 @@ public: bool IsClassExtension() const { return getIdentifier() == 0; } const ObjCCategoryDecl *getNextClassExtension() const; + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } + typedef specific_decl_iterator ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1154,11 +1160,15 @@ class ObjCImplementationDecl : public ObjCImplDecl { CXXBaseOrMemberInitializer **IvarInitializers; unsigned NumIvarInitializers; + /// true of class extension has at least one bitfield ivar. + bool HasSynthBitfield : 1; + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), - SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0), + HasSynthBitfield(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1196,6 +1206,9 @@ public: void setIvarInitializers(ASTContext &C, CXXBaseOrMemberInitializer ** initializers, unsigned numInitializers); + + bool hasSynthBitfield() const { return HasSynthBitfield; } + void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 4167841838..28c7a49a13 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -604,10 +604,17 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, // decl contexts, the previously built IvarList must be rebuilt. ObjCInterfaceDecl *ID = dyn_cast(DC); if (!ID) { - if (ObjCImplementationDecl *IM = dyn_cast(DC)) + if (ObjCImplementationDecl *IM = dyn_cast(DC)) { ID = IM->getClassInterface(); - else - ID = (cast(DC))->getClassInterface(); + if (BW) + IM->setHasSynthBitfield(true); + } + else { + ObjCCategoryDecl *CD = cast(DC); + ID = CD->getClassInterface(); + if (BW) + CD->setHasSynthBitfield(true); + } } ID->setIvarList(0); } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index f26fa3c610..e6388373ea 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1940,9 +1940,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Forward declarations, no (immediate) code generation. case Decl::ObjCClass: case Decl::ObjCForwardProtocol: - case Decl::ObjCCategory: case Decl::ObjCInterface: break; + + case Decl::ObjCCategory: { + ObjCCategoryDecl *CD = cast(D); + if (CD->IsClassExtension() && CD->hasSynthBitfield()) + Context.ResetObjCLayout(CD->getClassInterface()); + break; + } + case Decl::ObjCProtocol: Runtime->GenerateProtocol(cast(D)); @@ -1956,6 +1963,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::ObjCImplementation: { ObjCImplementationDecl *OMD = cast(D); + if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield()) + Context.ResetObjCLayout(OMD->getClassInterface()); EmitObjCPropertyImplementations(OMD); EmitObjCIvarInitializations(OMD); Runtime->GenerateClass(OMD); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0f9d12e6fe..f08092f922 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6349,9 +6349,13 @@ Decl *Sema::ActOnIvar(Scope *S, ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2) { // Case of ivar declared in an implementation. Context is that of its class. - EnclosingContext = IMPDecl->getClassInterface(); - assert(EnclosingContext && "Implementation has no class interface!"); + EnclosingContext = IMPDecl->getClassInterface(); + assert(EnclosingContext && "Implementation has no class interface!"); + } + else + EnclosingContext = EnclosingDecl; } else { if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index e8bf195787..0ee8c83183 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -476,6 +476,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), *Reader.getContext()); CD->setNextClassCategory(cast_or_null(Reader.GetDecl(Record[Idx++]))); + CD->setHasSynthBitfield(Record[Idx++]); CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } @@ -524,6 +525,7 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { cast_or_null(Reader.GetDecl(Record[Idx++]))); llvm::tie(D->IvarInitializers, D->NumIvarInitializers) = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx); + D->setHasSynthBitfield(Record[Idx++]); } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index a5d2ce21c2..3edb6302f8 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -428,6 +428,7 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { PL != PLEnd; ++PL) Writer.AddSourceLocation(*PL, Record); Writer.AddDeclRef(D->getNextClassCategory(), Record); + Record.push_back(D->hasSynthBitfield()); Writer.AddSourceLocation(D->getAtLoc(), Record); Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); Code = serialization::DECL_OBJC_CATEGORY; @@ -473,6 +474,7 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Writer.AddDeclRef(D->getSuperClass(), Record); Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers, D->NumIvarInitializers, Record); + Record.push_back(D->hasSynthBitfield()); Code = serialization::DECL_OBJC_IMPLEMENTATION; } diff --git a/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m new file mode 100644 index 0000000000..b474caa7a4 --- /dev/null +++ b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// rdar: // 7824380 + +@interface Super { + int ivar_super_a : 5; +} +@end + +@interface A : Super { +@public + int ivar_a : 5; +} +@end + +int f0(A *a) { + return a->ivar_a; +} + +@interface A () { +@public + int ivar_ext_a : 5; + int ivar_ext_b : 5; +}@end + +int f1(A *a) { + return a->ivar_ext_a + a->ivar_a; +} + +@interface A () { +@public + int ivar_ext2_a : 5; + int ivar_ext2_b : 5; +}@end + +int f2(A* a) { + return a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} + +@implementation A { +@public + int ivar_b : 5; + int ivar_c : 5; + int ivar_d : 5; +} +@end + +int f3(A *a) { + return a->ivar_d + a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} +