forked from OSchip/llvm-project
[PCH] Fix a regression that r139441 introduced (decls were getting passed
to the consumer without being fully deserialized). The regression was on compiling boost.python and it was too difficult to get a reduced test case unfortunately. Also modify the logic of how objc methods are getting passed to the consumer; codegen depended on receiving objc methods before the implementation decl. Since the interesting objc methods are ones with a body and such methods only exist inside an ObjCImplDecl, deserialize and pass to consumer all the methods of ObCImplDecl when we see one. Fixes http://llvm.org/PR10922 & rdar://10117105. llvm-svn: 139644
This commit is contained in:
parent
f92b2e0714
commit
a98e861939
|
@ -6387,7 +6387,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
|||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
if (!VD->isFileVarDecl())
|
||||
return false;
|
||||
} else if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))
|
||||
} else if (!isa<FunctionDecl>(D))
|
||||
return false;
|
||||
|
||||
// Weak references don't produce any output by themselves.
|
||||
|
@ -6427,9 +6427,6 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D))
|
||||
return Method->hasBody();
|
||||
|
||||
const VarDecl *VD = cast<VarDecl>(D);
|
||||
assert(VD->isFileVarDecl() && "Expected file scoped var");
|
||||
|
|
|
@ -4142,12 +4142,31 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
|
|||
return const_cast<DeclContext*>(DC)->lookup(Name);
|
||||
}
|
||||
|
||||
/// \brief Under non-PCH compilation the consumer receives the objc methods
|
||||
/// before receiving the implementation, and codegen depends on this.
|
||||
/// We simulate this by deserializing and passing to consumer the methods of the
|
||||
/// implementation before passing the deserialized implementation decl.
|
||||
static void PassObjCImplDeclToConsumer(ObjCImplDecl *ImplD,
|
||||
ASTConsumer *Consumer) {
|
||||
assert(ImplD && Consumer);
|
||||
|
||||
for (ObjCImplDecl::method_iterator
|
||||
I = ImplD->meth_begin(), E = ImplD->meth_end(); I != E; ++I)
|
||||
Consumer->HandleInterestingDecl(DeclGroupRef(*I));
|
||||
|
||||
Consumer->HandleInterestingDecl(DeclGroupRef(ImplD));
|
||||
}
|
||||
|
||||
void ASTReader::PassInterestingDeclsToConsumer() {
|
||||
assert(Consumer);
|
||||
while (!InterestingDecls.empty()) {
|
||||
DeclGroupRef DG(InterestingDecls.front());
|
||||
Decl *D = InterestingDecls.front();
|
||||
InterestingDecls.pop_front();
|
||||
Consumer->HandleInterestingDecl(DG);
|
||||
|
||||
if (ObjCImplDecl *ImplD = dyn_cast<ObjCImplDecl>(D))
|
||||
PassObjCImplDeclToConsumer(ImplD, Consumer);
|
||||
else
|
||||
Consumer->HandleInterestingDecl(DeclGroupRef(D));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1393,6 +1393,9 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
|
|||
/// code generation, e.g., inline function definitions, Objective-C
|
||||
/// declarations with metadata, etc.
|
||||
static bool isConsumerInterestedIn(Decl *D) {
|
||||
// An ObjCMethodDecl is never considered as "interesting" because its
|
||||
// implementation container always is.
|
||||
|
||||
if (isa<FileScopeAsmDecl>(D) ||
|
||||
isa<ObjCProtocolDecl>(D) ||
|
||||
isa<ObjCImplDecl>(D))
|
||||
|
@ -1402,8 +1405,6 @@ static bool isConsumerInterestedIn(Decl *D) {
|
|||
Var->isThisDeclarationADefinition() == VarDecl::Definition;
|
||||
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
|
||||
return Func->doesThisDeclarationHaveABody();
|
||||
if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D))
|
||||
return Method->hasBody();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1737,14 +1738,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
|||
// AST consumer might need to know about, queue it.
|
||||
// We don't pass it to the consumer immediately because we may be in recursive
|
||||
// loading, and some declarations may still be initializing.
|
||||
if (isConsumerInterestedIn(D)) {
|
||||
if (Consumer) {
|
||||
DeclGroupRef DG(D);
|
||||
Consumer->HandleInterestingDecl(DG);
|
||||
} else {
|
||||
if (isConsumerInterestedIn(D))
|
||||
InterestingDecls.push_back(D);
|
||||
}
|
||||
}
|
||||
|
||||
return D;
|
||||
}
|
||||
|
|
|
@ -1594,6 +1594,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
/// relatively painless since they would presumably only do it for top-level
|
||||
/// decls.
|
||||
static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
|
||||
// An ObjCMethodDecl is never considered as "required" because its
|
||||
// implementation container always is.
|
||||
|
||||
// File scoped assembly or obj-c implementation must be seen.
|
||||
if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D))
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue