From 13257c5527007ac6ce0c74c45b450e83d58316a8 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 9 Aug 2010 10:54:20 +0000 Subject: [PATCH] Support ObjC implementation decls for PCH. Strictly speaking, implementations don't go in headers but there's no law against it. llvm-svn: 110567 --- clang/include/clang/AST/DeclObjC.h | 3 +++ clang/lib/CodeGen/CGObjCMac.cpp | 24 ++++++++++++++++++++---- clang/lib/Frontend/PCHReaderDecl.cpp | 5 +++-- clang/lib/Frontend/PCHWriterDecl.cpp | 7 ++++--- clang/test/PCH/objcxx-ivar-class.h | 11 +++++++++++ clang/test/PCH/objcxx-ivar-class.mm | 9 +++++++++ 6 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 clang/test/PCH/objcxx-ivar-class.h create mode 100644 clang/test/PCH/objcxx-ivar-class.mm diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 7dbfd2a3ad00..8484216521be 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/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/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index d9d79e158752..3a80330a2fd4 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/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/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 930448419e2e..6c0bdf6068fc 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/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/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index ec5c575efc3f..6a78140b3ad5 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/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/clang/test/PCH/objcxx-ivar-class.h b/clang/test/PCH/objcxx-ivar-class.h new file mode 100644 index 000000000000..aa114e5577b0 --- /dev/null +++ b/clang/test/PCH/objcxx-ivar-class.h @@ -0,0 +1,11 @@ +struct S { + S(); +}; + +@interface C { + S s; +} +@end + +@implementation C +@end diff --git a/clang/test/PCH/objcxx-ivar-class.mm b/clang/test/PCH/objcxx-ivar-class.mm new file mode 100644 index 000000000000..48d359c11b99 --- /dev/null +++ b/clang/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]