aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/ASTUnit.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-08-03 19:06:41 +0000
committerDouglas Gregor <dgregor@apple.com>2010-08-03 19:06:41 +0000
commiteb8837b88c18631c69ac75f64ab1853762063180 (patch)
treeb323d79db49f00e97aefcd3a7f26dc403ab97144 /lib/Frontend/ASTUnit.cpp
parent1d832436e9cd9223cbad66c5ca9ac87ed5c8560c (diff)
When using a precompiled preamble, keep track of the top-level
declarations that we saw when creating the precompiled preamble, and provide those declarations in addition to the declarations parsed in the main source file when traversing top-level declarations. This makes the use of precompiled preambles a pure optimization, rather than changing the semantics of the parsed translation unit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110131 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/ASTUnit.cpp')
-rw-r--r--lib/Frontend/ASTUnit.cpp54
1 files changed, 47 insertions, 7 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index bd60296ca8..c37610afc3 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -309,7 +309,7 @@ public:
// fundamental problem in the parser right now.
if (isa<ObjCMethodDecl>(D))
continue;
- Unit.getTopLevelDecls().push_back(D);
+ Unit.addTopLevelDecl(D);
}
}
};
@@ -331,6 +331,7 @@ public:
class PrecompilePreambleConsumer : public PCHGenerator {
ASTUnit &Unit;
+ std::vector<Decl *> TopLevelDecls;
public:
PrecompilePreambleConsumer(ASTUnit &Unit,
@@ -338,7 +339,7 @@ public:
const char *isysroot, llvm::raw_ostream *Out)
: PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
- void HandleTopLevelDecl(DeclGroupRef D) {
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
Decl *D = *it;
// FIXME: Currently ObjC method declarations are incorrectly being
@@ -347,7 +348,20 @@ public:
// fundamental problem in the parser right now.
if (isa<ObjCMethodDecl>(D))
continue;
- Unit.getTopLevelDecls().push_back(D);
+ TopLevelDecls.push_back(D);
+ }
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ PCHGenerator::HandleTranslationUnit(Ctx);
+ if (!Unit.getDiagnostics().hasErrorOccurred()) {
+ // Translate the top-level declarations we captured during
+ // parsing into declaration IDs in the precompiled
+ // preamble. This will allow us to deserialize those top-level
+ // declarations when requested.
+ for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
+ Unit.addTopLevelDeclFromPreamble(
+ getWriter().getDeclID(TopLevelDecls[I]));
}
}
};
@@ -855,7 +869,9 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// Clear out old caches and data.
StoredDiagnostics.clear();
-
+ TopLevelDecls.clear();
+ TopLevelDeclsInPreamble.clear();
+
// Capture any diagnostics that would otherwise be dropped.
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
getDiagnostics(),
@@ -867,7 +883,6 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
// Create the source manager.
Clang.setSourceManager(new SourceManager(getDiagnostics()));
- // FIXME: Eventually, we'll have to track top-level declarations here, too.
llvm::OwningPtr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction(*this));
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
@@ -889,7 +904,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
Clang.takeDiagnosticClient();
Clang.takeInvocation();
- if (Diagnostics->getNumErrors() > 0) {
+ if (Diagnostics->hasErrorOccurred()) {
// There were errors parsing the preamble, so no precompiled header was
// generated. Forget that we even tried.
// FIXME: Should we leave a note for ourselves to try again?
@@ -899,7 +914,7 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
delete NewPreamble.first;
if (PreambleTimer)
PreambleTimer->stopTimer();
-
+ TopLevelDeclsInPreamble.clear();
return 0;
}
@@ -935,6 +950,31 @@ llvm::MemoryBuffer *ASTUnit::BuildPrecompiledPreamble() {
FrontendOpts.Inputs[0].second);
}
+void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
+ std::vector<Decl *> Resolved;
+ Resolved.reserve(TopLevelDeclsInPreamble.size());
+ ExternalASTSource &Source = *getASTContext().getExternalSource();
+ for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
+ // Resolve the declaration ID to an actual declaration, possibly
+ // deserializing the declaration in the process.
+ Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
+ if (D)
+ Resolved.push_back(D);
+ }
+ TopLevelDeclsInPreamble.clear();
+ TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
+}
+
+unsigned ASTUnit::getMaxPCHLevel() const {
+ if (!getOnlyLocalDecls())
+ return Decl::MaxPCHLevel;
+
+ unsigned Result = 0;
+ if (isMainFileAST() || SavedMainFileBuffer)
+ ++Result;
+ return Result;
+}
+
ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls,