]> granicus.if.org Git - clang/commitdiff
[libclang][index][NFCi] Refactor machinery for skipping function bodies
authorJan Korous <jkorous@apple.com>
Mon, 26 Aug 2019 17:25:23 +0000 (17:25 +0000)
committerJan Korous <jkorous@apple.com>
Mon, 26 Aug 2019 17:25:23 +0000 (17:25 +0000)
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

tools/libclang/Indexing.cpp

index c4ee53385bd7e36b107f3e5e2a921cd2f4ea8f14..ce1e6b3828fc0ec8a245d615e499540cfa716dab 100644 (file)
@@ -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