Support ObjC implementation decls for PCH.

Strictly speaking, implementations don't go in headers but there's no law against it.

llvm-svn: 110567
This commit is contained in:
Argyrios Kyrtzidis 2010-08-09 10:54:20 +00:00
parent 5b6a03f490
commit 13257c5527
6 changed files with 50 additions and 9 deletions

View File

@ -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,

View File

@ -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<const ObjCMethodDecl*, llvm::Function*>::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<ObjCMethodDecl*>(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;

View File

@ -514,7 +514,8 @@ void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
D->setSuperClass(
cast_or_null<ObjCInterfaceDecl>(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<FunctionDecl>(D))
return Func->isThisDeclarationADefinition();
return isa<ObjCProtocolDecl>(D);
return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D);
}
/// \brief Get the correct cursor and offset for loading a type.

View File

@ -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<FileScopeAsmDecl>(D))
// File scoped assembly or obj-c implementation must be seen.
if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D))
return true;
return Context.DeclMustBeEmitted(D);

View File

@ -0,0 +1,11 @@
struct S {
S();
};
@interface C {
S s;
}
@end
@implementation C
@end

View File

@ -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]