From 4ed69c25ab95ef923b9917a3c3599665ca7bbda7 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 9 Jun 2017 01:20:48 +0000 Subject: [PATCH] [libclang] Introduce a new parsing option 'CXTranslationUnit_SingleFileParse' that puts preprocessor in a mode for parsing a single file only. This is useful for parsing a single file, as a fast/inaccurate 'mode' that can still provide declarations from the file, like the classes and their methods. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305044 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang-c/Index.h | 9 ++++++-- include/clang/Frontend/ASTUnit.h | 1 + include/clang/Lex/PreprocessorOptions.h | 4 ++++ lib/Frontend/ASTUnit.cpp | 3 ++- lib/Lex/PPDirectives.cpp | 6 ++++- test/Index/singe-file-parse.m | 11 +++++++++ tools/c-index-test/c-index-test.c | 30 +++++++++++++++++++++++++ tools/libclang/CIndex.cpp | 6 +++-- 8 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 test/Index/singe-file-parse.m diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 987ba71023..417ac9fd36 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 42 +#define CINDEX_VERSION_MINOR 43 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -1234,7 +1234,12 @@ enum CXTranslationUnit_Flags { * purposes of an IDE, this is undesirable behavior and as much information * as possible should be reported. Use this flag to enable this behavior. */ - CXTranslationUnit_KeepGoing = 0x200 + CXTranslationUnit_KeepGoing = 0x200, + + /** + * \brief Sets the preprocessor in a mode for parsing a single file only. + */ + CXTranslationUnit_SingleFileParse = 0x400 }; /** diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index d05b7de0dc..259946b342 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -871,6 +871,7 @@ public: bool CacheCodeCompletionResults = false, bool IncludeBriefCommentsInCodeCompletion = false, bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, + bool SingleFileParse = false, bool UserFilesAreVolatile = false, bool ForSerialization = false, llvm::Optional ModuleFormat = llvm::None, std::unique_ptr *ErrAST = nullptr, diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index c85d2384fa..f536be8d8e 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -95,6 +95,9 @@ public: /// If given, a PTH cache file to use for speeding up header parsing. std::string TokenCache; + /// When enabled, preprocessor is in a mode for parsing a single file only. + bool SingleFileParseMode = false; + /// \brief True if the SourceManager should report the original file name for /// contents of files that were remapped to other files. Defaults to true. bool RemappedFilesKeepOriginalName; @@ -181,6 +184,7 @@ public: ImplicitPCHInclude.clear(); ImplicitPTHInclude.clear(); TokenCache.clear(); + SingleFileParseMode = false; RetainRemappedFileBuffers = true; PrecompiledPreambleBytes.first = 0; PrecompiledPreambleBytes.second = 0; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 3040517a9d..bf856f0146 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -1982,7 +1982,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, - bool UserFilesAreVolatile, bool ForSerialization, + bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, llvm::Optional ModuleFormat, std::unique_ptr *ErrAST, IntrusiveRefCntPtr VFS) { assert(Diags.get() && "no DiagnosticsEngine was provided"); @@ -2011,6 +2011,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0; + PPOpts.SingleFileParseMode = SingleFileParse; // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index b2c3c2e707..89c2ebd00a 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" @@ -1845,10 +1846,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // we've imported or already built. bool ShouldEnter = true; + if (PPOpts->SingleFileParseMode) + ShouldEnter = false; + // Determine whether we should try to import the module for this #include, if // there is one. Don't do so if precompiled module support is disabled or we // are processing this module textually (because we're building the module). - if (File && SuggestedModule && getLangOpts().Modules && + if (ShouldEnter && File && SuggestedModule && getLangOpts().Modules && SuggestedModule.getModule()->getTopLevelModuleName() != getLangOpts().CurrentModule) { // If this include corresponds to a module but that module is diff --git a/test/Index/singe-file-parse.m b/test/Index/singe-file-parse.m new file mode 100644 index 0000000000..d13915b30c --- /dev/null +++ b/test/Index/singe-file-parse.m @@ -0,0 +1,11 @@ +// RUN: c-index-test -single-file-parse %s | FileCheck %s + +#include + +// CHECK-NOT: TypedefDecl=intptr_t + +// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=MyCls +@interface MyCls +// CHECK: [[@LINE+1]]:8: ObjCInstanceMethodDecl=some_meth +-(void)some_meth; +@end diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 31ad828a2f..d25ae117a6 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1850,6 +1850,34 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, return result; } +static int perform_single_file_parse(const char *filename) { + CXIndex Idx; + CXTranslationUnit TU; + enum CXErrorCode Err; + int result; + + Idx = clang_createIndex(/* excludeDeclsFromPCH */1, + /* displayDiagnostics=*/1); + + Err = clang_parseTranslationUnit2(Idx, filename, + /*command_line_args=*/NULL, + /*num_command_line_args=*/0, + /*unsaved_files=*/NULL, + /*num_unsaved_files=*/0, + CXTranslationUnit_SingleFileParse, &TU); + if (Err != CXError_Success) { + fprintf(stderr, "Unable to load translation unit!\n"); + describeLibclangFailure(Err); + clang_disposeIndex(Idx); + return 1; + } + + result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL, + /*CommentSchemaFile=*/NULL); + clang_disposeIndex(Idx); + return result; +} + /******************************************************************************/ /* Logic for testing clang_getCursor(). */ /******************************************************************************/ @@ -4439,6 +4467,8 @@ int cindextest_main(int argc, const char **argv) { return perform_test_load_source(argc - 3, argv + 3, argv[2], I, postVisit); } + else if (argc >= 3 && strcmp(argv[1], "-single-file-parse") == 0) + return perform_single_file_parse(argv[2]); else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0) return perform_file_scan(argv[2], argv[3], argc >= 5 ? argv[4] : 0); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 2d92de19d9..1ccf6cbd32 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3300,12 +3300,14 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, options & CXTranslationUnit_CreatePreambleOnFirstParse; // FIXME: Add a flag for modules. TranslationUnitKind TUKind - = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete; + = (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. @@ -3390,7 +3392,7 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, /*CaptureDiagnostics=*/true, *RemappedFiles.get(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses, TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion, - /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, + /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse, /*UserFilesAreVolatile=*/true, ForSerialization, CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(), &ErrUnit)); -- 2.40.0