[cfe-commits] r110131 - in /cfe/trunk: include/clang/Frontend/ASTUnit.h include/clang/Frontend/PCHWriter.h lib/Frontend/ASTUnit.cpp test/Index/preamble.c tools/libclang/CIndex.cpp
Douglas Gregor
dgregor at apple.com
Tue Aug 3 12:06:41 PDT 2010
Author: dgregor
Date: Tue Aug 3 14:06:41 2010
New Revision: 110131
URL: http://llvm.org/viewvc/llvm-project?rev=110131&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/include/clang/Frontend/PCHWriter.h
cfe/trunk/lib/Frontend/ASTUnit.cpp
cfe/trunk/test/Index/preamble.c
cfe/trunk/tools/libclang/CIndex.cpp
Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=110131&r1=110130&r2=110131&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Tue Aug 3 14:06:41 2010
@@ -14,12 +14,13 @@
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
+#include "clang/Index/ASTLocation.h"
+#include "clang/Frontend/PCHBitCodes.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Index/ASTLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/System/Path.h"
@@ -168,7 +169,11 @@
/// \brief The group of timers associated with this translation unit.
llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
-
+
+ /// \brief A list of the PCH ID numbers for each of the top-level
+ /// declarations parsed within the precompiled preamble.
+ std::vector<pch::DeclID> TopLevelDeclsInPreamble;
+
/// \brief The timers we've created from the various parses, reparses, etc.
/// involved in this translation unit.
std::vector<llvm::Timer *> Timers;
@@ -185,7 +190,8 @@
ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer);
llvm::MemoryBuffer *BuildPrecompiledPreamble();
-
+ void RealizeTopLevelDeclsFromPreamble();
+
public:
class ConcurrencyCheck {
volatile ASTUnit &Self;
@@ -236,16 +242,48 @@
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ /// \brief Retrieve the maximum PCH level of declarations that a
+ /// traversal of the translation unit should consider.
+ unsigned getMaxPCHLevel() const;
+
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
ASTLocation getLastASTLocation() const { return LastLoc; }
- std::vector<Decl*> &getTopLevelDecls() {
+ typedef std::vector<Decl *>::iterator top_level_iterator;
+
+ top_level_iterator top_level_begin() {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.begin();
}
- const std::vector<Decl*> &getTopLevelDecls() const {
+
+ top_level_iterator top_level_end() {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.end();
+ }
+
+ std::size_t top_level_size() const {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ return TopLevelDeclsInPreamble.size() + TopLevelDecls.size();
+ }
+
+ bool top_level_empty() const {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
+ }
+
+ /// \brief Add a new top-level declaration.
+ void addTopLevelDecl(Decl *D) {
+ TopLevelDecls.push_back(D);
+ }
+
+ /// \brief Add a new top-level declaration, identified by its ID in
+ /// the precompiled preamble.
+ void addTopLevelDeclFromPreamble(pch::DeclID D) {
+ TopLevelDeclsInPreamble.push_back(D);
}
/// \brief Retrieve the mapping from File IDs to the preprocessed entities
Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=110131&r1=110130&r2=110131&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Tue Aug 3 14:06:41 2010
@@ -448,6 +448,10 @@
llvm::BitstreamWriter Stream;
PCHWriter Writer;
+protected:
+ PCHWriter &getWriter() { return Writer; }
+ const PCHWriter &getWriter() const { return Writer; }
+
public:
PCHGenerator(const Preprocessor &PP, bool Chaining,
const char *isysroot, llvm::raw_ostream *Out);
Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=110131&r1=110130&r2=110131&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Aug 3 14:06:41 2010
@@ -309,7 +309,7 @@
// fundamental problem in the parser right now.
if (isa<ObjCMethodDecl>(D))
continue;
- Unit.getTopLevelDecls().push_back(D);
+ Unit.addTopLevelDecl(D);
}
}
};
@@ -331,6 +331,7 @@
class PrecompilePreambleConsumer : public PCHGenerator {
ASTUnit &Unit;
+ std::vector<Decl *> TopLevelDecls;
public:
PrecompilePreambleConsumer(ASTUnit &Unit,
@@ -338,7 +339,7 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
delete NewPreamble.first;
if (PreambleTimer)
PreambleTimer->stopTimer();
-
+ TopLevelDeclsInPreamble.clear();
return 0;
}
@@ -935,6 +950,31 @@
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,
Modified: cfe/trunk/test/Index/preamble.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/preamble.c?rev=110131&r1=110130&r2=110131&view=diff
==============================================================================
--- cfe/trunk/test/Index/preamble.c (original)
+++ cfe/trunk/test/Index/preamble.c Tue Aug 3 14:06:41 2010
@@ -5,6 +5,16 @@
// RUN: %clang -x c-header -o %t.pch %S/Inputs/prefix.h
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck %s
// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+// CHECK: preamble.h:1:12: FunctionDecl=bar:1:12 (Definition) Extent=[1:12 - 6:2]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[1:23 - 6:2]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[2:3 - 2:16]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[3:3 - 3:15]
+// CHECK: preamble.h:4:3: UnexposedExpr= Extent=[4:3 - 4:13]
+// CHECK: preamble.h:4:3: DeclRefExpr=ptr:2:8 Extent=[4:3 - 4:6]
+// CHECK: preamble.h:4:9: UnexposedExpr=ptr1:3:10 Extent=[4:9 - 4:13]
+// CHECK: preamble.h:4:9: DeclRefExpr=ptr1:3:10 Extent=[4:9 - 4:13]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[5:3 - 5:11]
+// CHECK: preamble.h:5:10: UnexposedExpr= Extent=[5:10 - 5:11]
// CHECK: preamble.c:3:5: FunctionDecl=wibble:3:5 Extent=[3:5 - 3:16]
// CHECK: preamble.c:3:15: ParmDecl=:3:15 (Definition) Extent=[3:12 - 3:16]
// CHECK-DIAG: preamble.h:4:7:{4:9-4:13}: warning: incompatible pointer types assigning to 'int *' from 'float *'
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=110131&r1=110130&r2=110131&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Aug 3 14:06:41 2010
@@ -478,10 +478,10 @@
ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
RegionOfInterest.isInvalid()) {
- const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
- for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
- ie = TLDs.end(); it != ie; ++it) {
- if (Visit(MakeCXCursor(*it, CXXUnit), true))
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ if (Visit(MakeCXCursor(*TL, CXXUnit), true))
return true;
}
} else if (VisitDeclContext(
@@ -1636,18 +1636,8 @@
CXClientData client_data) {
ASTUnit *CXXUnit = getCursorASTUnit(parent);
- unsigned PCHLevel = Decl::MaxPCHLevel;
-
- // Set the PCHLevel to filter out unwanted decls if requested.
- if (CXXUnit->getOnlyLocalDecls()) {
- PCHLevel = 0;
-
- // If the main input was an AST, bump the level.
- if (CXXUnit->isMainFileAST())
- ++PCHLevel;
- }
-
- CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
+ CursorVisitor CursorVis(CXXUnit, visitor, client_data,
+ CXXUnit->getMaxPCHLevel());
return CursorVis.VisitChildren(parent);
}
More information about the cfe-commits
mailing list