Jelajahi Sumber

[libclang] Allow skipping function bodies in preamble only

Second attempt. Fix line endings and warning.

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@332587 91177308-0d34-0410-b5e6-96231b3b80d8
Ivan Donchevskii 7 tahun lalu
induk
melakukan
94fc51b9de

+ 9 - 1
include/clang-c/Index.h

@@ -1324,7 +1324,15 @@ enum CXTranslationUnit_Flags {
   /**
   /**
    * Sets the preprocessor in a mode for parsing a single file only.
    * Sets the preprocessor in a mode for parsing a single file only.
    */
    */
-  CXTranslationUnit_SingleFileParse = 0x400
+  CXTranslationUnit_SingleFileParse = 0x400,
+
+  /**
+   * \brief Used in combination with CXTranslationUnit_SkipFunctionBodies to
+   * constrain the skipping of function bodies to the preamble.
+   *
+   * The function bodies of the main file are not skipped.
+   */
+  CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800
 };
 };
 
 
 /**
 /**

+ 12 - 4
include/clang/Frontend/ASTUnit.h

@@ -81,6 +81,9 @@ class FileSystem;
 
 
 } // namespace vfs
 } // namespace vfs
 
 
+/// \brief Enumerates the available scopes for skipping function bodies.
+enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile };
+
 /// Utility class for loading a ASTContext from an AST file.
 /// Utility class for loading a ASTContext from an AST file.
 class ASTUnit {
 class ASTUnit {
 public:
 public:
@@ -348,6 +351,9 @@ private:
   /// inconsistent state, and is not safe to free.
   /// inconsistent state, and is not safe to free.
   unsigned UnsafeToFree : 1;
   unsigned UnsafeToFree : 1;
 
 
+  /// \brief Enumerator specifying the scope for skipping function bodies.
+  SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
+
   /// Cache any "global" code-completion results, so that we can avoid
   /// Cache any "global" code-completion results, so that we can avoid
   /// recomputing them with each completion.
   /// recomputing them with each completion.
   void CacheCodeCompletionResults();
   void CacheCodeCompletionResults();
@@ -363,7 +369,7 @@ private:
 
 
   std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
   std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
       std::shared_ptr<PCHContainerOperations> PCHContainerOps,
-      const CompilerInvocation &PreambleInvocationIn,
+      CompilerInvocation &PreambleInvocationIn,
       IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
       IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true,
       unsigned MaxLines = 0);
       unsigned MaxLines = 0);
   void RealizeTopLevelDeclsFromPreamble();
   void RealizeTopLevelDeclsFromPreamble();
@@ -801,9 +807,11 @@ public:
       TranslationUnitKind TUKind = TU_Complete,
       TranslationUnitKind TUKind = TU_Complete,
       bool CacheCodeCompletionResults = false,
       bool CacheCodeCompletionResults = false,
       bool IncludeBriefCommentsInCodeCompletion = false,
       bool IncludeBriefCommentsInCodeCompletion = false,
-      bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
-      bool SingleFileParse = false,
-      bool UserFilesAreVolatile = false, bool ForSerialization = false,
+      bool AllowPCHWithCompilerErrors = false,
+      SkipFunctionBodiesScope SkipFunctionBodies =
+          SkipFunctionBodiesScope::None,
+      bool SingleFileParse = false, bool UserFilesAreVolatile = false,
+      bool ForSerialization = false,
       llvm::Optional<StringRef> ModuleFormat = llvm::None,
       llvm::Optional<StringRef> ModuleFormat = llvm::None,
       std::unique_ptr<ASTUnit> *ErrAST = nullptr,
       std::unique_ptr<ASTUnit> *ErrAST = nullptr,
       IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
       IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);

+ 14 - 3
lib/Frontend/ASTUnit.cpp

@@ -1271,7 +1271,7 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
 std::unique_ptr<llvm::MemoryBuffer>
 std::unique_ptr<llvm::MemoryBuffer>
 ASTUnit::getMainBufferWithPrecompiledPreamble(
 ASTUnit::getMainBufferWithPrecompiledPreamble(
     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
-    const CompilerInvocation &PreambleInvocationIn,
+    CompilerInvocation &PreambleInvocationIn,
     IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
     IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild,
     unsigned MaxLines) {
     unsigned MaxLines) {
   auto MainFilePath =
   auto MainFilePath =
@@ -1338,9 +1338,18 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
     SimpleTimer PreambleTimer(WantTiming);
     SimpleTimer PreambleTimer(WantTiming);
     PreambleTimer.setOutput("Precompiling preamble");
     PreambleTimer.setOutput("Precompiling preamble");
 
 
+    const bool PreviousSkipFunctionBodies =
+        PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;
+    if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)
+      PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;
+
     llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
     llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
         PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
         PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
         PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
         PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
+
+    PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =
+        PreviousSkipFunctionBodies;
+
     if (NewPreamble) {
     if (NewPreamble) {
       Preamble = std::move(*NewPreamble);
       Preamble = std::move(*NewPreamble);
       PreambleRebuildCounter = 1;
       PreambleRebuildCounter = 1;
@@ -1691,7 +1700,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
     ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
     ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
     unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
     unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
     bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
     bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
-    bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
+    bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
     bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
     bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
     llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
     llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
     IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
     IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
@@ -1724,7 +1733,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
   // Override the resources path.
   // Override the resources path.
   CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
   CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
 
 
-  CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;
+  CI->getFrontendOpts().SkipFunctionBodies =
+      SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
 
 
   if (ModuleFormat)
   if (ModuleFormat)
     CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
     CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
@@ -1750,6 +1760,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
     = IncludeBriefCommentsInCodeCompletion;
     = IncludeBriefCommentsInCodeCompletion;
   AST->UserFilesAreVolatile = UserFilesAreVolatile;
   AST->UserFilesAreVolatile = UserFilesAreVolatile;
   AST->Invocation = CI;
   AST->Invocation = CI;
+  AST->SkipFunctionBodies = SkipFunctionBodies;
   if (ForSerialization)
   if (ForSerialization)
     AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));
     AST->WriterData.reset(new ASTWriterData(*AST->PCMCache));
   // Zero out now to ease cleanup during crash recovery.
   // Zero out now to ease cleanup during crash recovery.

+ 3 - 0
test/Parser/skip-function-bodies.h

@@ -0,0 +1,3 @@
+int header1(int t) {
+  return t;
+}

+ 12 - 1
test/Parser/skip-function-bodies.mm

@@ -1,4 +1,4 @@
-// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s
+#include "skip-function-bodies.h"
 
 
 class A {
 class A {
   class B {};
   class B {};
@@ -27,6 +27,7 @@ void J() {
   class K {};
   class K {};
 }
 }
 
 
+// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 c-index-test -test-load-source all %s | FileCheck %s
 // CHECK: skip-function-bodies.mm:3:7: ClassDecl=A:3:7 (Definition) Extent=[3:1 - 14:2]
 // 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: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]
 // CHECK: skip-function-bodies.mm:6:1: CXXAccessSpecifier=:6:1 (Definition) Extent=[6:1 - 6:8]
@@ -43,3 +44,13 @@ void J() {
 // CHECK-NOT: skip-function-bodies.mm:21:11: TypeRef=class A:3:7 Extent=[21:11 - 21:12]
 // 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: 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:27:9: ClassDecl=K:27:9 (Definition) Extent=[27:3 - 27:13]
+
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN:  CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE=1 \
+// RUN:  CINDEXTEST_SKIP_FUNCTION_BODIES=1 \
+// RUN:  CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE=1 \
+// RUN:  c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-PREAMBLE %s
+// CHECK-PREAMBLE: skip-function-bodies.h:1:5: FunctionDecl=header1:1:5 Extent=[1:1 - 1:19]
+// CHECK-PREAMBLE-NOT: skip-function-bodies.h:2:3: ReturnStmt= Extent=[2:3 - 2:11]
+// CHECK-PREAMBLE: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6]
+// CHECK-PREAMBLE: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18]

+ 2 - 0
tools/c-index-test/c-index-test.c

@@ -82,6 +82,8 @@ static unsigned getDefaultParsingOptions() {
     options |= CXTranslationUnit_CreatePreambleOnFirstParse;
     options |= CXTranslationUnit_CreatePreambleOnFirstParse;
   if (getenv("CINDEXTEST_KEEP_GOING"))
   if (getenv("CINDEXTEST_KEEP_GOING"))
     options |= CXTranslationUnit_KeepGoing;
     options |= CXTranslationUnit_KeepGoing;
+  if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE"))
+    options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble;
 
 
   return options;
   return options;
 }
 }

+ 7 - 1
tools/libclang/CIndex.cpp

@@ -3380,9 +3380,15 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
     = options & CXTranslationUnit_CacheCompletionResults;
     = options & CXTranslationUnit_CacheCompletionResults;
   bool IncludeBriefCommentsInCodeCompletion
   bool IncludeBriefCommentsInCodeCompletion
     = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
     = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
-  bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;
   bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
   bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
   bool ForSerialization = options & CXTranslationUnit_ForSerialization;
   bool ForSerialization = options & CXTranslationUnit_ForSerialization;
+  SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
+  if (options & CXTranslationUnit_SkipFunctionBodies) {
+    SkipFunctionBodies =
+        (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble)
+            ? SkipFunctionBodiesScope::Preamble
+            : SkipFunctionBodiesScope::PreambleAndMainFile;
+  }
 
 
   // Configure the diagnostics.
   // Configure the diagnostics.
   IntrusiveRefCntPtr<DiagnosticsEngine>
   IntrusiveRefCntPtr<DiagnosticsEngine>