]> granicus.if.org Git - clang/commitdiff
[libclang] Allow skipping function bodies in preamble only
authorIvan Donchevskii <ivan.donchevskii@qt.io>
Thu, 17 May 2018 07:31:29 +0000 (07:31 +0000)
committerIvan Donchevskii <ivan.donchevskii@qt.io>
Thu, 17 May 2018 07:31:29 +0000 (07:31 +0000)
As an addition to CXTranslationUnit_SkipFunctionBodies, provide the
new option CXTranslationUnit_LimitSkipFunctionBodiesToPreamble,
which constraints the skipping of functions bodies to the preamble
only. Function bodies in the main file are not affected if this
option is set.

Skipping function bodies only in the preamble is what clangd already
does and the introduced flag implements it for libclang clients.

Patch by Nikolai Kosjar.

Differential Revision: https://reviews.llvm.org/D45815

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332578 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
include/clang/Frontend/ASTUnit.h
lib/Frontend/ASTUnit.cpp
test/Parser/skip-function-bodies.h [new file with mode: 0644]
test/Parser/skip-function-bodies.mm
tools/c-index-test/c-index-test.c
tools/libclang/CIndex.cpp

index 3fee13a40b46c2fc10558894c9f54550edafe593..4e6fcce8adf8b88cba433445e1b0ea4a9b9d3bbe 100644 (file)
@@ -1321,13 +1321,21 @@ enum CXTranslationUnit_Flags {
    */
   CXTranslationUnit_KeepGoing = 0x200,
 
-  /**
-   * Sets the preprocessor in a mode for parsing a single file only.
-   */
-  CXTranslationUnit_SingleFileParse = 0x400
-};
-
-/**
+  /**\r
+   * Sets the preprocessor in a mode for parsing a single file only.\r
+   */\r
+  CXTranslationUnit_SingleFileParse = 0x400,\r
+\r
+  /**\r
+   * \brief Used in combination with CXTranslationUnit_SkipFunctionBodies to\r
+   * constrain the skipping of function bodies to the preamble.\r
+   *\r
+   * The function bodies of the main file are not skipped.\r
+   */\r
+  CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800,\r
+};\r
+\r
+/**\r
  * Returns the set of flags that is suitable for parsing a translation
  * unit that is being edited.
  *
index af67dd1aedcf94b12d419006bf7fff963ef8665f..8ce4492b37113b9beade6b00a24a12ed8b85121f 100644 (file)
@@ -78,12 +78,15 @@ class TargetInfo;
 namespace vfs {
 
 class FileSystem;
-
-} // namespace vfs
-
-/// Utility class for loading a ASTContext from an AST file.
-class ASTUnit {
-public:
+\r
+} // namespace vfs\r
+\r
+/// \brief Enumerates the available scopes for skipping function bodies.\r
+enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile };\r
+\r
+/// Utility class for loading a ASTContext from an AST file.\r
+class ASTUnit {\r
+public:\r
   struct StandaloneFixIt {
     std::pair<unsigned, unsigned> RemoveRange;
     std::pair<unsigned, unsigned> InsertFromRange;
@@ -345,12 +348,15 @@ private:
   unsigned CurrentTopLevelHashValue = 0;
   
   /// Bit used by CIndex to mark when a translation unit may be in an
-  /// inconsistent state, and is not safe to free.
-  unsigned UnsafeToFree : 1;
-
-  /// Cache any "global" code-completion results, so that we can avoid
-  /// recomputing them with each completion.
-  void CacheCodeCompletionResults();
+  /// inconsistent state, and is not safe to free.\r
+  unsigned UnsafeToFree : 1;\r
+\r
+  /// \brief Enumerator specifying the scope for skipping function bodies.\r
+  SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;\r
+\r
+  /// Cache any "global" code-completion results, so that we can avoid\r
+  /// recomputing them with each completion.\r
+  void CacheCodeCompletionResults();\r
   
   /// Clear out and deallocate 
   void ClearCachedCompletionResults();
@@ -360,13 +366,13 @@ private:
   bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
              std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
              IntrusiveRefCntPtr<vfs::FileSystem> VFS);
-
-  std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
-      std::shared_ptr<PCHContainerOperations> PCHContainerOps,
-      const CompilerInvocation &PreambleInvocationIn,
-      IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
-      unsigned MaxLines = 0);
-  void RealizeTopLevelDeclsFromPreamble();
+\r
+  std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(\r
+      std::shared_ptr<PCHContainerOperations> PCHContainerOps,\r
+      CompilerInvocation &PreambleInvocationIn,\r
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,\r
+      unsigned MaxLines = 0);\r
+  void RealizeTopLevelDeclsFromPreamble();\r
 
   /// Transfers ownership of the objects (like SourceManager) from
   /// \param CI to this ASTUnit.
@@ -798,15 +804,17 @@ public:
       ArrayRef<RemappedFile> RemappedFiles = None,
       bool RemappedFilesKeepOriginalName = true,
       unsigned PrecompilePreambleAfterNParses = 0,
-      TranslationUnitKind TUKind = TU_Complete,
-      bool CacheCodeCompletionResults = false,
-      bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
-      bool SingleFileParse = false,
-      bool UserFilesAreVolatile = false, bool ForSerialization = false,
-      llvm::Optional<StringRef> ModuleFormat = llvm::None,
-      std::unique_ptr<ASTUnit> *ErrAST = nullptr,
-      IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+      TranslationUnitKind TUKind = TU_Complete,\r
+      bool CacheCodeCompletionResults = false,\r
+      bool IncludeBriefCommentsInCodeCompletion = false,\r
+      bool AllowPCHWithCompilerErrors = false,\r
+      SkipFunctionBodiesScope SkipFunctionBodies =\r
+          SkipFunctionBodiesScope::None,\r
+      bool SingleFileParse = false, bool UserFilesAreVolatile = false,\r
+      bool ForSerialization = false,\r
+      llvm::Optional<StringRef> ModuleFormat = llvm::None,\r
+      std::unique_ptr<ASTUnit> *ErrAST = nullptr,\r
+      IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);\r
 
   /// Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.
index 9b672d97551818f1e624a6ddbb7e93a376f6d5a3..0ce7adb620e74390a73a2130aaff01cadc1cc528 100644 (file)
@@ -1268,13 +1268,13 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
 /// \returns If the precompiled preamble can be used, returns a newly-allocated
 /// buffer that should be used in place of the main file when doing so.
 /// Otherwise, returns a NULL pointer.
-std::unique_ptr<llvm::MemoryBuffer>
-ASTUnit::getMainBufferWithPrecompiledPreamble(
-    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
-    const CompilerInvocation &PreambleInvocationIn,
-    IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
-    unsigned MaxLines) {
-  auto MainFilePath =
+std::unique_ptr<llvm::MemoryBuffer>\r
+ASTUnit::getMainBufferWithPrecompiledPreamble(\r
+    std::shared_ptr<PCHContainerOperations> PCHContainerOps,\r
+    CompilerInvocation &PreambleInvocationIn,\r
+    IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,\r
+    unsigned MaxLines) {\r
+  auto MainFilePath =\r
       PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
   std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
       getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),
@@ -1335,15 +1335,24 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
                       &NewPreambleDiagsStandalone);
 
     // We did not previously compute a preamble, or it can't be reused anyway.
-    SimpleTimer PreambleTimer(WantTiming);
-    PreambleTimer.setOutput("Precompiling preamble");
-
-    llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
-        PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
-        PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
-    if (NewPreamble) {
-      Preamble = std::move(*NewPreamble);
-      PreambleRebuildCounter = 1;
+    SimpleTimer PreambleTimer(WantTiming);\r
+    PreambleTimer.setOutput("Precompiling preamble");\r
+\r
+    const bool PreviousSkipFunctionBodies =\r
+        PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;\r
+    if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)\r
+      PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;\r
+\r
+    llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(\r
+        PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,\r
+        PCHContainerOps, /*StoreInMemory=*/false, Callbacks);\r
+\r
+    PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =\r
+        PreviousSkipFunctionBodies;\r
+\r
+    if (NewPreamble) {\r
+      Preamble = std::move(*NewPreamble);\r
+      PreambleRebuildCounter = 1;\r
     } else {
       switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {
       case BuildPreambleError::CouldntCreateTempFile:
@@ -1688,13 +1697,13 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
     IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
     bool OnlyLocalDecls, bool CaptureDiagnostics,
-    ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
-    unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
-    bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
-    bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
-    bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
-    llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
-    IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
+    ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,\r
+    unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,\r
+    bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,\r
+    bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,\r
+    bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,\r
+    llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,\r
+    IntrusiveRefCntPtr<vfs::FileSystem> VFS) {\r
   assert(Diags.get() && "no DiagnosticsEngine was provided");
 
   SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@@ -1721,13 +1730,14 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
   PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
   PPOpts.SingleFileParseMode = SingleFileParse;
 
-  // Override the resources path.
-  CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
-
-  CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;
-
-  if (ModuleFormat)
-    CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
+  // Override the resources path.\r
+  CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;\r
+\r
+  CI->getFrontendOpts().SkipFunctionBodies =\r
+      SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;\r
+\r
+  if (ModuleFormat)\r
+    CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();\r
 
   // Create the AST unit.
   std::unique_ptr<ASTUnit> AST;
@@ -1747,12 +1757,13 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
   AST->TUKind = TUKind;
   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
   AST->IncludeBriefCommentsInCodeCompletion
-    = IncludeBriefCommentsInCodeCompletion;
-  AST->UserFilesAreVolatile = UserFilesAreVolatile;
-  AST->Invocation = CI;
-  if (ForSerialization)
-    AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));
-  // Zero out now to ease cleanup during crash recovery.
+    = IncludeBriefCommentsInCodeCompletion;\r
+  AST->UserFilesAreVolatile = UserFilesAreVolatile;\r
+  AST->Invocation = CI;\r
+  AST->SkipFunctionBodies = SkipFunctionBodies;\r
+  if (ForSerialization)\r
+    AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));\r
+  // Zero out now to ease cleanup during crash recovery.\r
   CI = nullptr;
   Diags = nullptr;
 
diff --git a/test/Parser/skip-function-bodies.h b/test/Parser/skip-function-bodies.h
new file mode 100644 (file)
index 0000000..250026c
--- /dev/null
@@ -0,0 +1,3 @@
+int header1(int t) {\r
+  return t;\r
+}\r
index e5b7b2adf83892b0351dbe6316cdb50d8ea88441..b2fe485a1d565b280ffc9c0abb388d057a868c57 100644 (file)
@@ -1,7 +1,7 @@
-// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s
-
-class A {
-  class B {};
+#include "skip-function-bodies.h"\r
+\r
+class A {\r
+  class B {};\r
 
 public:
   A() {
@@ -24,12 +24,13 @@ public:
 @end
 
 void J() {
-  class K {};
-}
-
-// CHECK: skip-function-bodies.mm:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 14:2]
-// CHECK: skip-function-bodies.mm:4:9: ClassDecl=B:4:9 (Definition) Extent=[4:3 - 4:13]
-// CHECK: skip-function-bodies.mm:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:8]
+  class K {};\r
+}\r
+\r
+// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s\r
+// CHECK: skip-function-bodies.mm:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 14:2]\r
+// CHECK: skip-function-bodies.mm:4:9: ClassDecl=B:4:9 (Definition) Extent=[4:3 - 4:13]\r
+// CHECK: skip-function-bodies.mm:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:8]\r
 // CHECK: skip-function-bodies.mm:7:3: CXXConstructor=A:7:3 (default constructor) Extent=[7:3 - 7:6]
 // CHECK-NOT: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6]
 // CHECK-NOT: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18]
@@ -40,6 +41,16 @@ void J() {
 // CHECK: skip-function-bodies.mm:19:17: ObjCImplementationDecl=F:19:17 (Definition) Extent=[19:1 - 24:2]
 // CHECK: skip-function-bodies.mm:20:10: ObjCInstanceMethodDecl=G:20:10 Extent=[20:1 - 20:13]
 // CHECK-NOT: skip-function-bodies.mm:21:13: TypedefDecl=H:21:13 (Definition) Extent=[21:3 - 21:14]
-// CHECK-NOT: skip-function-bodies.mm:21:11: TypeRef=class A:3:7 Extent=[21:11 - 21:12]
-// CHECK: skip-function-bodies.mm:26:6: FunctionDecl=J:26:6 Extent=[26:1 - 26:9]
-// CHECK-NOT: skip-function-bodies.mm:27:9: ClassDecl=K:27:9 (Definition) Extent=[27:3 - 27:13]
+// CHECK-NOT: skip-function-bodies.mm:21:11: TypeRef=class A:3:7 Extent=[21:11 - 21:12]\r
+// CHECK: skip-function-bodies.mm:26:6: FunctionDecl=J:26:6 Extent=[26:1 - 26:9]\r
+// CHECK-NOT: skip-function-bodies.mm:27:9: ClassDecl=K:27:9 (Definition) Extent=[27:3 - 27:13]\r
+\r
+// RUN: env CINDEXTEST_EDITING=1 \\r
+// RUN:  CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE=1 \\r
+// RUN:  CINDEXTEST_SKIP_FUNCTION_BODIES=1 \\r
+// RUN:  CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE=1 \\r
+// RUN:  c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-PREAMBLE %s\r
+// CHECK-PREAMBLE: skip-function-bodies.h:1:5: FunctionDecl=header1:1:5 Extent=[1:1 - 1:19]\r
+// CHECK-PREAMBLE-NOT: skip-function-bodies.h:2:3: ReturnStmt= Extent=[2:3 - 2:11]\r
+// CHECK-PREAMBLE: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6]\r
+// CHECK-PREAMBLE: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18]\r
index d57ac4f9f6caa234f8a4fe51de35dddcb1952326..828cb98c1f98c8b6b5bdc16d4e39b529c0034f89 100644 (file)
@@ -79,12 +79,14 @@ static unsigned getDefaultParsingOptions() {
   if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS"))
     options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
   if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE"))
-    options |= CXTranslationUnit_CreatePreambleOnFirstParse;
-  if (getenv("CINDEXTEST_KEEP_GOING"))
-    options |= CXTranslationUnit_KeepGoing;
-
-  return options;
-}
+    options |= CXTranslationUnit_CreatePreambleOnFirstParse;\r
+  if (getenv("CINDEXTEST_KEEP_GOING"))\r
+    options |= CXTranslationUnit_KeepGoing;\r
+  if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))\r
+    options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble;\r
+\r
+  return options;\r
+}\r
 
 static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
   struct Mapping {
index c348506545d081f6a9d92eb20de45c1863dfb894..9b682da71ea173dffe32e46406a653c812f61042 100644 (file)
@@ -3377,15 +3377,21 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
     = (options & (CXTranslationUnit_Incomplete |
                   CXTranslationUnit_SingleFileParse))? TU_Prefix : TU_Complete;
   bool CacheCodeCompletionResults
-    = options & CXTranslationUnit_CacheCompletionResults;
-  bool IncludeBriefCommentsInCodeCompletion
-    = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
-  bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;
-  bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
-  bool ForSerialization = options & CXTranslationUnit_ForSerialization;
-
-  // Configure the diagnostics.
-  IntrusiveRefCntPtr<DiagnosticsEngine>
+    = options & CXTranslationUnit_CacheCompletionResults;\r
+  bool IncludeBriefCommentsInCodeCompletion\r
+    = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;\r
+  bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;\r
+  bool ForSerialization = options & CXTranslationUnit_ForSerialization;\r
+  SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;\r
+  if (options & CXTranslationUnit_SkipFunctionBodies) {\r
+    SkipFunctionBodies =\r
+        (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble)\r
+            ? SkipFunctionBodiesScope::Preamble\r
+            : SkipFunctionBodiesScope::PreambleAndMainFile;\r
+  }\r
+\r
+  // Configure the diagnostics.\r
+  IntrusiveRefCntPtr<DiagnosticsEngine>\r
     Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
 
   if (options & CXTranslationUnit_KeepGoing)