forked from OSchip/llvm-project
PCH: When writing PCH files, tweak the predicate function deciding whether to mark a decl as "external" to be closer to reality.
This still isn't perfect, but I believe it is conservatively accurate at marking decls which IRgen needs to see, while still keeping the "deserialization footprint" on Cocoa.h. llvm-svn: 82112
This commit is contained in:
parent
865c2a7f23
commit
5bb5ec5b07
|
@ -529,6 +529,69 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
|
||||||
ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
|
ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
|
||||||
|
/// consumers of the AST.
|
||||||
|
///
|
||||||
|
/// Such decls will always be deserialized from the PCH file, so we would like
|
||||||
|
/// this to be as restrictive as possible. Currently the predicate is driven by
|
||||||
|
/// code generation requirements, if other clients have a different notion of
|
||||||
|
/// what is "required" then we may have to consider an alternate scheme where
|
||||||
|
/// clients can iterate over the top-level decls and get information on them,
|
||||||
|
/// without necessary deserializing them. We could explicitly require such
|
||||||
|
/// clients to use a separate API call to "realize" the decl. This should be
|
||||||
|
/// relatively painless since they would presumably only do it for top-level
|
||||||
|
/// decls.
|
||||||
|
//
|
||||||
|
// FIXME: This predicate is essentially IRgen's predicate to determine whether a
|
||||||
|
// declaration can be deferred. Merge them somehow.
|
||||||
|
static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
|
||||||
|
// File scoped assembly must be seen.
|
||||||
|
if (isa<FileScopeAsmDecl>(D))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Otherwise if this isn't a function or a file scoped variable it doesn't
|
||||||
|
// need to be seen.
|
||||||
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||||
|
if (!VD->isFileVarDecl())
|
||||||
|
return false;
|
||||||
|
} else if (!isa<FunctionDecl>(D))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Aliases and used decls must be seen.
|
||||||
|
if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||||
|
// Forward declarations don't need to be seen.
|
||||||
|
if (!FD->isThisDeclarationADefinition())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Constructors and destructors must be seen.
|
||||||
|
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Otherwise, this is required unless it is static.
|
||||||
|
//
|
||||||
|
// FIXME: Inlines.
|
||||||
|
return FD->getStorageClass() != FunctionDecl::Static;
|
||||||
|
} else {
|
||||||
|
const VarDecl *VD = cast<VarDecl>(D);
|
||||||
|
|
||||||
|
// In C++, this doesn't need to be seen if it is marked "extern".
|
||||||
|
if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
|
||||||
|
(VD->getStorageClass() == VarDecl::Extern ||
|
||||||
|
VD->isExternC()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// In C, this doesn't need to be seen unless it is a definition.
|
||||||
|
if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Otherwise, this is required unless it is static.
|
||||||
|
return VD->getStorageClass() != VarDecl::Static;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Write a block containing all of the declarations.
|
/// \brief Write a block containing all of the declarations.
|
||||||
void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
||||||
// Enter the declarations block.
|
// Enter the declarations block.
|
||||||
|
@ -595,9 +658,11 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
||||||
// Flush any expressions that were written as part of this declaration.
|
// Flush any expressions that were written as part of this declaration.
|
||||||
FlushStmts();
|
FlushStmts();
|
||||||
|
|
||||||
// Note external declarations so that we can add them to a record
|
// Note "external" declarations so that we can add them to a record in the
|
||||||
// in the PCH file later.
|
// PCH file later.
|
||||||
if (isa<FileScopeAsmDecl>(D))
|
//
|
||||||
|
// FIXME: This should be renamed, the predicate is much more complicated.
|
||||||
|
if (isRequiredDecl(D, Context))
|
||||||
ExternalDefinitions.push_back(ID);
|
ExternalDefinitions.push_back(ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue