summaryrefslogtreecommitdiff
path: root/tools/libclang
diff options
context:
space:
mode:
authorJan Korous <jkorous@apple.com>2019-08-26 17:25:23 +0000
committerJan Korous <jkorous@apple.com>2019-08-26 17:25:23 +0000
commit0cd2a94c8a0657dfb1ebe0d9d4d4322ee39ca8b0 (patch)
treebec3f8ab96dd10af48294c4add59ec99bfc60118 /tools/libclang
parent658d3ba9808f8632c3ee853fb9c7243a81e383fb (diff)
downloadclang-0cd2a94c8a0657dfb1ebe0d9d4d4322ee39ca8b0.tar.gz
[libclang][index][NFCi] Refactor machinery for skipping function bodies
Refactor machinery for skipping inline function bodies that have already been parsed in other frontend actions. Preparations for moving this code to libIndex. Differential Revision: https://reviews.llvm.org/D66694 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@369931 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/libclang')
-rw-r--r--tools/libclang/Indexing.cpp106
1 files changed, 65 insertions, 41 deletions
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index c4ee53385b..ce1e6b3828 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -120,43 +120,62 @@ namespace llvm {
namespace {
-class SessionSkipBodyData {
+/// Keeps track of function bodies that have already been parsed.
+///
+/// Is thread-safe.
+class SharedParsedRegionsStorage {
std::mutex Mux;
PPRegionSetTy ParsedRegions;
public:
- ~SessionSkipBodyData() = default;
+ ~SharedParsedRegionsStorage() = default;
void copyTo(PPRegionSetTy &Set) {
std::lock_guard<std::mutex> MG(Mux);
Set = ParsedRegions;
}
- void update(ArrayRef<PPRegion> Regions) {
+ void merge(ArrayRef<PPRegion> Regions) {
std::lock_guard<std::mutex> MG(Mux);
ParsedRegions.insert(Regions.begin(), Regions.end());
}
};
-class TUSkipBodyControl {
- SessionSkipBodyData &SessionData;
+/// Provides information whether source locations have already been parsed in
+/// another FrontendAction.
+///
+/// Is NOT thread-safe.
+class ParsedSrcLocationsTracker {
+ SharedParsedRegionsStorage &ParsedRegionsStorage;
PPConditionalDirectiveRecord &PPRec;
Preprocessor &PP;
+ /// Snapshot of the shared state at the point when this instance was
+ /// constructed.
PPRegionSetTy ParsedRegions;
+ /// Regions that were queried during this instance lifetime.
SmallVector<PPRegion, 32> NewParsedRegions;
+
+ /// Caching the last queried region.
PPRegion LastRegion;
bool LastIsParsed;
public:
- TUSkipBodyControl(SessionSkipBodyData &sessionData,
- PPConditionalDirectiveRecord &ppRec,
- Preprocessor &pp)
- : SessionData(sessionData), PPRec(ppRec), PP(pp) {
- SessionData.copyTo(ParsedRegions);
+ /// Creates snapshot of \p ParsedRegionsStorage.
+ ParsedSrcLocationsTracker(SharedParsedRegionsStorage &ParsedRegionsStorage,
+ PPConditionalDirectiveRecord &ppRec,
+ Preprocessor &pp)
+ : ParsedRegionsStorage(ParsedRegionsStorage), PPRec(ppRec), PP(pp) {
+ ParsedRegionsStorage.copyTo(ParsedRegions);
}
- bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
+ /// \returns true iff \p Loc has already been parsed.
+ ///
+ /// Can provide false-negative in case the location was parsed after this
+ /// instance had been constructed.
+ bool hasAlredyBeenParsed(SourceLocation Loc, FileID FID,
+ const FileEntry *FE) {
+ assert(FE);
PPRegion region = getRegion(Loc, FID, FE);
if (region.isInvalid())
return false;
@@ -166,40 +185,42 @@ public:
return LastIsParsed;
LastRegion = region;
+ // Source locations can't be revisited during single TU parsing.
+ // That means if we hit the same region again, it's a different location in
+ // the same region and so the "is parsed" value from the snapshot is still
+ // correct.
LastIsParsed = ParsedRegions.count(region);
if (!LastIsParsed)
- NewParsedRegions.push_back(region);
+ NewParsedRegions.emplace_back(std::move(region));
return LastIsParsed;
}
- void finished() {
- SessionData.update(NewParsedRegions);
- }
+ /// Updates ParsedRegionsStorage with newly parsed regions.
+ void syncWithStorage() { ParsedRegionsStorage.merge(NewParsedRegions); }
private:
PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) {
- SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
- if (RegionLoc.isInvalid()) {
+ assert(FE);
+ auto Bail = [this, FE]() {
if (isParsedOnceInclude(FE)) {
const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
return PPRegion(ID, 0, FE->getModificationTime());
}
return PPRegion();
- }
+ };
- const SourceManager &SM = PPRec.getSourceManager();
+ SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc);
assert(RegionLoc.isFileID());
+ if (RegionLoc.isInvalid())
+ return Bail();
+
FileID RegionFID;
unsigned RegionOffset;
- std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc);
+ std::tie(RegionFID, RegionOffset) =
+ PPRec.getSourceManager().getDecomposedLoc(RegionLoc);
- if (RegionFID != FID) {
- if (isParsedOnceInclude(FE)) {
- const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
- return PPRegion(ID, 0, FE->getModificationTime());
- }
- return PPRegion();
- }
+ if (RegionFID != FID)
+ return Bail();
const llvm::sys::fs::UniqueID &ID = FE->getUniqueID();
return PPRegion(ID, RegionOffset, FE->getModificationTime());
@@ -275,11 +296,12 @@ public:
class IndexingConsumer : public ASTConsumer {
CXIndexDataConsumer &DataConsumer;
- TUSkipBodyControl *SKCtrl;
+ ParsedSrcLocationsTracker *ParsedLocsTracker;
public:
- IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl)
- : DataConsumer(dataConsumer), SKCtrl(skCtrl) { }
+ IndexingConsumer(CXIndexDataConsumer &dataConsumer,
+ ParsedSrcLocationsTracker *parsedLocsTracker)
+ : DataConsumer(dataConsumer), ParsedLocsTracker(parsedLocsTracker) {}
// ASTConsumer Implementation
@@ -289,8 +311,8 @@ public:
}
void HandleTranslationUnit(ASTContext &Ctx) override {
- if (SKCtrl)
- SKCtrl->finished();
+ if (ParsedLocsTracker)
+ ParsedLocsTracker->syncWithStorage();
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
@@ -298,7 +320,7 @@ public:
}
bool shouldSkipFunctionBody(Decl *D) override {
- if (!SKCtrl) {
+ if (!ParsedLocsTracker) {
// Always skip bodies.
return true;
}
@@ -320,7 +342,7 @@ public:
if (!FE)
return false;
- return SKCtrl->isParsed(Loc, FID, FE);
+ return ParsedLocsTracker->hasAlredyBeenParsed(Loc, FID, FE);
}
};
@@ -346,12 +368,12 @@ public:
class IndexingFrontendAction : public ASTFrontendAction {
std::shared_ptr<CXIndexDataConsumer> DataConsumer;
- SessionSkipBodyData *SKData;
- std::unique_ptr<TUSkipBodyControl> SKCtrl;
+ SharedParsedRegionsStorage *SKData;
+ std::unique_ptr<ParsedSrcLocationsTracker> ParsedLocsTracker;
public:
IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer,
- SessionSkipBodyData *skData)
+ SharedParsedRegionsStorage *skData)
: DataConsumer(std::move(dataConsumer)), SKData(skData) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
@@ -372,10 +394,12 @@ public:
if (SKData) {
auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager());
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
- SKCtrl = std::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP);
+ ParsedLocsTracker =
+ std::make_unique<ParsedSrcLocationsTracker>(*SKData, *PPRec, PP);
}
- return std::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get());
+ return std::make_unique<IndexingConsumer>(*DataConsumer,
+ ParsedLocsTracker.get());
}
TranslationUnitKind getTranslationUnitKind() override {
@@ -402,10 +426,10 @@ static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) {
struct IndexSessionData {
CXIndex CIdx;
- std::unique_ptr<SessionSkipBodyData> SkipBodyData;
+ std::unique_ptr<SharedParsedRegionsStorage> SkipBodyData;
explicit IndexSessionData(CXIndex cIdx)
- : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {}
+ : CIdx(cIdx), SkipBodyData(new SharedParsedRegionsStorage) {}
};
} // anonymous namespace