]> granicus.if.org Git - clang/commitdiff
Support for IRGen of synthesize bitfield ivars in
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 23 Aug 2010 18:51:39 +0000 (18:51 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 23 Aug 2010 18:51:39 +0000 (18:51 +0000)
objc-nonfragile-abi2 (radar 7824380).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111823 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/AST/DeclObjC.h
lib/AST/DeclObjC.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaDecl.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/CodeGenObjC/ivar-layout-nonfragile-abi2.m [new file with mode: 0644]

index 2790c7941705f065b7c4e3c37ba9ac9cecb72a6c..a42c3894ed0dd887308a02d7814fe74683777a26 100644 (file)
@@ -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.
index c48e2295993d7ddd8d9bc8e8806b8efe57fdefb0..351f8bdae2b131f6cb5de7d48e08ca10bb7cd572 100644 (file)
@@ -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<ObjCIvarDecl> 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.
index 41678418380e864540022625c5e7170398830c79..28c7a49a1322eb4103c37ec6c3c1cccc8c1094f4 100644 (file)
@@ -604,10 +604,17 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
     // decl contexts, the previously built IvarList must be rebuilt.
     ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
     if (!ID) {
-      if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
+      if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) {
         ID = IM->getClassInterface();
-      else
-        ID = (cast<ObjCCategoryDecl>(DC))->getClassInterface();
+        if (BW)
+          IM->setHasSynthBitfield(true);
+      }
+      else {
+        ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+        ID = CD->getClassInterface();
+        if (BW)
+          CD->setHasSynthBitfield(true);
+      }
     }
     ID->setIvarList(0);
   }
index f26fa3c6105d44e7db6b123b96c680786baaa5fa..e6388373eae37a24baf93e0037a29f0ac44744e9 100644 (file)
@@ -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<ObjCCategoryDecl>(D);
+      if (CD->IsClassExtension() && CD->hasSynthBitfield())
+        Context.ResetObjCLayout(CD->getClassInterface());
+      break;
+    }
+      
 
   case Decl::ObjCProtocol:
     Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
@@ -1956,6 +1963,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
 
   case Decl::ObjCImplementation: {
     ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+    if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
+      Context.ResetObjCLayout(OMD->getClassInterface());
     EmitObjCPropertyImplementations(OMD);
     EmitObjCIvarInitializations(OMD);
     Runtime->GenerateClass(OMD);
index 0f9d12e6fe265738b4a8491a1fa0e43fca4fbd56..f08092f92204bc9b0793208527182294eb17bb79 100644 (file)
@@ -6349,9 +6349,13 @@ Decl *Sema::ActOnIvar(Scope *S,
   ObjCContainerDecl *EnclosingContext;
   if (ObjCImplementationDecl *IMPDecl =
       dyn_cast<ObjCImplementationDecl>(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<ObjCCategoryDecl>(EnclosingDecl)) {
index e8bf195787b45d0013795c7f7d5141663b472086..0ee8c83183a8fea88f0d4d64144136c9ea78d424 100644 (file)
@@ -476,6 +476,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
   CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                       *Reader.getContext());
   CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(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<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
   llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
       = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
+  D->setHasSynthBitfield(Record[Idx++]);
 }
 
 
index a5d2ce21c21589691da2ff68824c6e783cfdc509..3edb6302f8f744efa167b6dbc49866a98ba21e5e 100644 (file)
@@ -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 (file)
index 0000000..b474caa
--- /dev/null
@@ -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;
+}
+