From: Argyrios Kyrtzidis Date: Mon, 9 Aug 2010 10:54:20 +0000 (+0000) Subject: Support ObjC implementation decls for PCH. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9d50c0635fb213b2a1857e3f8488580f0dab2f98;p=clang Support ObjC implementation decls for PCH. Strictly speaking, implementations don't go in headers but there's no law against it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110567 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 7dbfd2a3ad..8484216521 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1238,6 +1238,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplementationDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCImplementation; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index d9d79e1587..3a80330a2f 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -937,6 +937,8 @@ protected: /// name. The return value has type char *. llvm::Constant *GetClassName(IdentifierInfo *Ident); + llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); + /// BuildIvarLayout - Builds ivar layout bitmap for the class /// implementation for the __strong or __weak case. /// @@ -2538,8 +2540,7 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, /// given method if it has been defined. The result is null if the /// method has not been defined. The return value has type MethodPtrTy. llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { - // FIXME: Use DenseMap::lookup - llvm::Function *Fn = MethodDefinitions[MD]; + llvm::Function *Fn = GetMethodDefinition(MD); if (!Fn) return 0; @@ -3571,6 +3572,22 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { return getConstantGEP(VMContext, Entry, 0, 0); } +llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { + llvm::DenseMap::iterator + I = MethodDefinitions.find(MD); + if (I != MethodDefinitions.end()) + return I->second; + + if (MD->hasBody() && MD->getPCHLevel() > 0) { + // MD isn't emitted yet because it comes from PCH. + CGM.EmitTopLevelDecl(const_cast(MD)); + assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!"); + return MethodDefinitions[MD]; + } + + return NULL; +} + /// GetIvarLayoutName - Returns a unique constant for the given /// ivar layout bitmap. llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, @@ -5162,8 +5179,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { /// method has not been defined. The return value has type MethodPtrTy. llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( const ObjCMethodDecl *MD) { - // FIXME: Use DenseMap::lookup - llvm::Function *Fn = MethodDefinitions[MD]; + llvm::Function *Fn = GetMethodDefinition(MD); if (!Fn) return 0; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 930448419e..6c0bdf6068 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -514,7 +514,8 @@ void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); D->setSuperClass( cast_or_null(Reader.GetDecl(Record[Idx++]))); - // FIXME. Add reading of IvarInitializers and NumIvarInitializers. + llvm::tie(D->IvarInitializers, D->NumIvarInitializers) + = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx); } @@ -1298,7 +1299,7 @@ static bool isConsumerInterestedIn(Decl *D) { Var->isThisDeclarationADefinition() == VarDecl::Definition; if (FunctionDecl *Func = dyn_cast(D)) return Func->isThisDeclarationADefinition(); - return isa(D); + return isa(D) || isa(D); } /// \brief Get the correct cursor and offset for loading a type. diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index ec5c575efc..6a78140b3a 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -468,7 +468,8 @@ void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); Writer.AddDeclRef(D->getSuperClass(), Record); - // FIXME add writing of IvarInitializers and NumIvarInitializers. + Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers, + D->NumIvarInitializers, Record); Code = pch::DECL_OBJC_IMPLEMENTATION; } @@ -1096,8 +1097,8 @@ void PCHWriter::WriteDeclsBlockAbbrevs() { /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext &Context) { - // File scoped assembly must be seen. - if (isa(D)) + // File scoped assembly or obj-c implementation must be seen. + if (isa(D) || isa(D)) return true; return Context.DeclMustBeEmitted(D); diff --git a/test/PCH/objcxx-ivar-class.h b/test/PCH/objcxx-ivar-class.h new file mode 100644 index 0000000000..aa114e5577 --- /dev/null +++ b/test/PCH/objcxx-ivar-class.h @@ -0,0 +1,11 @@ +struct S { + S(); +}; + +@interface C { + S s; +} +@end + +@implementation C +@end diff --git a/test/PCH/objcxx-ivar-class.mm b/test/PCH/objcxx-ivar-class.mm new file mode 100644 index 0000000000..48d359c11b --- /dev/null +++ b/test/PCH/objcxx-ivar-class.mm @@ -0,0 +1,9 @@ +// Test this without pch. +// RUN: %clang_cc1 -include %S/objcxx-ivar-class.h -verify %s -emit-llvm -o - | FileCheck %s + +// Test with pch. +// RUN: %clang_cc1 -x objective-c++-header -emit-pch -o %t %S/objcxx-ivar-class.h +// RUN: %clang_cc1 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// CHECK: [C .cxx_destruct] +// CHECK: [C .cxx_construct]