nik created this revision. Herald added subscribers: cfe-commits, kbarton, nemanjai, klimek.
As an addition to CXTranslationUnit_SkipFunctionBodies, provide the new options CXTranslationUnit_LimitSkipFunctionBodiesToPreamble CXTranslationUnit_LimitSkipFunctionBodiesToNonTemplates. The first one constraints the skipping of functions bodies to the preamble. The second one allows to exclude template function bodies from being skipped, which is useful for diagnostics about wrong/incomplete template instantiations. For the purpose of an IDE both options makes sense. Repository: rC Clang https://reviews.llvm.org/D45815 Files: include/clang-c/Index.h include/clang/Frontend/ASTUnit.h include/clang/Frontend/FrontendOptions.h include/clang/Frontend/SkipFunctionBodies.h include/clang/Parse/ParseAST.h include/clang/Parse/Parser.h lib/Frontend/ASTUnit.cpp lib/Parse/ParseAST.cpp lib/Parse/Parser.cpp test/Parser/skip-function-bodies.h test/Parser/skip-function-bodies.mm tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/Indexing.cpp unittests/CodeGen/BufferSourceTest.cpp unittests/CodeGen/CodeGenExternalTest.cpp unittests/CodeGen/IncrementalProcessingTest.cpp unittests/CodeGen/TBAAMetadataTest.cpp unittests/Frontend/PCHPreambleTest.cpp unittests/Lex/PPCallbacksTest.cpp unittests/Tooling/ToolingTest.cpp
Index: unittests/Tooling/ToolingTest.cpp =================================================================== --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -250,7 +250,7 @@ struct SkipBodyAction : public clang::ASTFrontendAction { std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, StringRef) override { - Compiler.getFrontendOpts().SkipFunctionBodies = true; + Compiler.getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies_All; return llvm::make_unique<SkipBodyConsumer>(); } }; Index: unittests/Lex/PPCallbacksTest.cpp =================================================================== --- unittests/Lex/PPCallbacksTest.cpp +++ unittests/Lex/PPCallbacksTest.cpp @@ -201,7 +201,7 @@ ASTConsumer Consumer; Sema S(PP, Context, Consumer); - Parser P(PP, S, false); + Parser P(PP, S, SkipFunctionBodies_None); PragmaOpenCLExtensionCallbacks* Callbacks = new PragmaOpenCLExtensionCallbacks; PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); Index: unittests/Frontend/PCHPreambleTest.cpp =================================================================== --- unittests/Frontend/PCHPreambleTest.cpp +++ unittests/Frontend/PCHPreambleTest.cpp @@ -103,7 +103,9 @@ } bool ReparseAST(const std::unique_ptr<ASTUnit> &AST) { - bool reparseFailed = AST->Reparse(PCHContainerOpts, GetRemappedFiles(), VFS); + bool reparseFailed = + AST->Reparse(PCHContainerOpts, GetRemappedFiles(), + ASTUnit::SkipFunctionBodiesOptions(), VFS); return !reparseFailed; } Index: unittests/CodeGen/TBAAMetadataTest.cpp =================================================================== --- unittests/CodeGen/TBAAMetadataTest.cpp +++ unittests/CodeGen/TBAAMetadataTest.cpp @@ -73,7 +73,7 @@ } const BasicBlock *compile() { - clang::ParseAST(compiler.getSema(), false, false); + clang::ParseAST(compiler.getSema(), false, clang::SkipFunctionBodies_None); M = CG->GetModule(); // Do not expect more than one function definition. Index: unittests/CodeGen/IncrementalProcessingTest.cpp =================================================================== --- unittests/CodeGen/IncrementalProcessingTest.cpp +++ unittests/CodeGen/IncrementalProcessingTest.cpp @@ -143,7 +143,7 @@ Sema& S = compiler.getSema(); std::unique_ptr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, - /*SkipFunctionBodies*/ false)); + SkipFunctionBodies_None)); Parser &P = *ParseOP.get(); std::array<std::unique_ptr<llvm::Module>, 3> M; Index: unittests/CodeGen/CodeGenExternalTest.cpp =================================================================== --- unittests/CodeGen/CodeGenExternalTest.cpp +++ unittests/CodeGen/CodeGenExternalTest.cpp @@ -294,7 +294,7 @@ sm.setMainFileID(sm.createFileID( llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); - clang::ParseAST(compiler.getSema(), false, false); + clang::ParseAST(compiler.getSema(), false, clang::SkipFunctionBodies_None); ASSERT_TRUE(test_codegen_fns_ran); } Index: unittests/CodeGen/BufferSourceTest.cpp =================================================================== --- unittests/CodeGen/BufferSourceTest.cpp +++ unittests/CodeGen/BufferSourceTest.cpp @@ -74,7 +74,7 @@ sm.setMainFileID(sm.createFileID( llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); - clang::ParseAST(compiler.getSema(), false, false); + clang::ParseAST(compiler.getSema(), false, clang::SkipFunctionBodies_None); } } // end anonymous namespace Index: tools/libclang/Indexing.cpp =================================================================== --- tools/libclang/Indexing.cpp +++ tools/libclang/Indexing.cpp @@ -540,7 +540,7 @@ bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) && CInvok->getLangOpts()->CPlusPlus; if (SkipBodies) - CInvok->getFrontendOpts().SkipFunctionBodies = true; + CInvok->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies_All; auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -3346,6 +3346,20 @@ Options); } +static ASTUnit::SkipFunctionBodiesOptions +skipFunctionBodiesOptionsFromParseOptions(unsigned options) { + ASTUnit::SkipFunctionBodiesOptions SkipFunctionBodiesOpts; + if (options & CXTranslationUnit_SkipFunctionBodies) { + if (options & CXTranslationUnit_LimitSkipFunctionBodiesToNonTemplates) + SkipFunctionBodiesOpts.LimitToNonTemplateFunctions = true; + SkipFunctionBodiesOpts.Scope = + (options & CXTranslationUnit_LimitSkipFunctionBodiesToPreamble) + ? ASTUnit::SkipFunctionBodiesOptions::Preamble + : ASTUnit::SkipFunctionBodiesOptions::MainFileAndPreamble; + } + return SkipFunctionBodiesOpts; +} + static CXErrorCode clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, const char *const *command_line_args, @@ -3376,9 +3390,10 @@ = options & CXTranslationUnit_CacheCompletionResults; bool IncludeBriefCommentsInCodeCompletion = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; - bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies; bool SingleFileParse = options & CXTranslationUnit_SingleFileParse; bool ForSerialization = options & CXTranslationUnit_ForSerialization; + ASTUnit::SkipFunctionBodiesOptions SkipFunctionBodiesOpts = + skipFunctionBodiesOptionsFromParseOptions(options); // Configure the diagnostics. IntrusiveRefCntPtr<DiagnosticsEngine> @@ -3467,7 +3482,7 @@ /*CaptureDiagnostics=*/true, *RemappedFiles.get(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses, TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion, - /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse, + /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodiesOpts, SingleFileParse, /*UserFilesAreVolatile=*/true, ForSerialization, CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(), &ErrUnit)); @@ -4055,7 +4070,8 @@ } if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(), - *RemappedFiles.get())) + *RemappedFiles.get(), + skipFunctionBodiesOptionsFromParseOptions(TU->ParsingOptions))) return CXError_Success; if (isASTReadError(CXXUnit)) return CXError_ASTReadError; Index: tools/c-index-test/c-index-test.c =================================================================== --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -82,6 +82,10 @@ options |= CXTranslationUnit_CreatePreambleOnFirstParse; if (getenv("CINDEXTEST_KEEP_GOING")) options |= CXTranslationUnit_KeepGoing; + if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE")) + options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble; + if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_NON_TEMPLATES")) + options |= CXTranslationUnit_LimitSkipFunctionBodiesToNonTemplates; return options; } Index: test/Parser/skip-function-bodies.mm =================================================================== --- test/Parser/skip-function-bodies.mm +++ 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 B {}; @@ -27,6 +27,12 @@ class K {}; } +template <typename T> +T g(T t) { + return t; +} + +// 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: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] @@ -43,3 +49,48 @@ // 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: skip-function-bodies.mm:31:3: FunctionTemplate=g:31:3 Extent=[30:1 - 31:9] +// CHECK: skip-function-bodies.mm:30:20: TemplateTypeParameter=T:30:20 (Definition) Extent=[30:11 - 30:21] [access=public] +// CHECK: skip-function-bodies.mm:31:1: TypeRef=T:30:20 Extent=[31:1 - 31:2] +// CHECK: skip-function-bodies.mm:31:7: ParmDecl=t:31:7 (Definition) Extent=[31:5 - 31:8] +// CHECK: skip-function-bodies.mm:31:5: TypeRef=T:30:20 Extent=[31:5 - 31:6] +// CHECK-NOT: skip-function-bodies.mm:31:10: CompoundStmt= Extent=[31:10 - 33:2] +// CHECK-NOT: skip-function-bodies.mm:32:3: ReturnStmt= Extent=[32:3 - 32:11] +// CHECK-NOT: skip-function-bodies.mm:32:10: DeclRefExpr=t:31:7 Extent=[32:10 - 32:11] + +// RUN: env CINDEXTEST_SKIP_FUNCTION_BODIES=1 \ +// RUN: CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_NON_TEMPLATES=1 \ +// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-TEMPLATES %s +// CHECK-TEMPLATES-NOT: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6] +// CHECK-TEMPLATES-NOT: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18] +// CHECK-TEMPLATES: skip-function-bodies.mm:31:3: FunctionTemplate=g:31:3 (Definition) Extent=[30:1 - 33:2] +// CHECK-TEMPLATES: skip-function-bodies.mm:30:20: TemplateTypeParameter=T:30:20 (Definition) Extent=[30:11 - 30:21] [access=public] +// CHECK-TEMPLATES: skip-function-bodies.mm:31:1: TypeRef=T:30:20 Extent=[31:1 - 31:2] +// CHECK-TEMPLATES: skip-function-bodies.mm:31:7: ParmDecl=t:31:7 (Definition) Extent=[31:5 - 31:8] +// CHECK-TEMPLATES: skip-function-bodies.mm:31:5: TypeRef=T:30:20 Extent=[31:5 - 31:6] +// CHECK-TEMPLATES: skip-function-bodies.mm:31:10: CompoundStmt= Extent=[31:10 - 33:2] +// CHECK-TEMPLATES: skip-function-bodies.mm:32:3: ReturnStmt= Extent=[32:3 - 32:11] +// CHECK-TEMPLATES: skip-function-bodies.mm:32:10: DeclRefExpr=t:31:7 Extent=[32:10 - 32:11] + +// 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-PREAMBLE1 %s +// CHECK-PREAMBLE1: skip-function-bodies.h:1:5: FunctionDecl=header1:1:5 Extent=[1:1 - 1:19] +// CHECK-PREAMBLE1-NOT: skip-function-bodies.h:2:3: ReturnStmt= Extent=[2:3 - 2:11] +// CHECK-PREAMBLE1: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6] +// CHECK-PREAMBLE1: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18] + +// 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: CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_NON_TEMPLATES=1 \ +// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-PREAMBLE2 %s +// CHECK-PREAMBLE2: skip-function-bodies.h:1:5: FunctionDecl=header1:1:5 Extent=[1:1 - 1:19] +// CHECK-PREAMBLE2-NOT: skip-function-bodies.h:2:3: ReturnStmt= Extent=[2:3 - 2:11] +// CHECK-PREAMBLE2: skip-function-bodies.h:6:3: FunctionTemplate=header2:6:3 (Definition) Extent=[5:1 - 8:2] +// CHECK-PREAMBLE2: skip-function-bodies.h:7:3: ReturnStmt= Extent=[7:3 - 7:11] +// CHECK-PREAMBLE2: skip-function-bodies.mm:8:12: StructDecl=C:8:12 (Definition) Extent=[8:5 - 10:6] +// CHECK-PREAMBLE2: skip-function-bodies.mm:9:12: CXXMethod=d:9:12 (Definition) Extent=[9:7 - 9:18] Index: test/Parser/skip-function-bodies.h =================================================================== --- /dev/null +++ test/Parser/skip-function-bodies.h @@ -0,0 +1,8 @@ +int header1(int t) { + return t; +} + +template <typename T> +T header2(T t) { + return t; +} Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -47,12 +47,16 @@ return Ident__except; } -Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) +Parser::Parser(Preprocessor &pp, Sema &actions, SkipFunctionBodiesKind skipFunctionBodies) : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), GreaterThanIsOperator(true), ColonIsSacred(false), InMessageExpression(false), TemplateParameterDepth(0), ParsingInObjCContainer(false) { - SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; + + if (pp.isCodeCompletionEnabled()) + SkipFunctionBodies = SkipFunctionBodies_All; + else + SkipFunctionBodies = skipFunctionBodies; Tok.startToken(); Tok.setKind(tok::eof); Actions.CurScope = nullptr; @@ -1100,6 +1104,19 @@ } } + bool SkipFunctionBodyRequested = false; + switch (SkipFunctionBodies) { + case SkipFunctionBodies_All: + SkipFunctionBodyRequested = true; + break; + case SkipFunctionBodies_AllExceptTemplates: + SkipFunctionBodyRequested = TemplateInfo.Kind != ParsedTemplateInfo::Template; + break; + case SkipFunctionBodies_None: + default: + SkipFunctionBodyRequested = false; + } + // In delayed template parsing mode, for function template we consume the // tokens and store them for late parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && @@ -1117,7 +1134,7 @@ D.complete(DP); D.getMutableDeclSpec().abort(); - if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) && + if (SkipFunctionBodyRequested && (!DP || Actions.canSkipFunctionBody(DP)) && trySkippingFunctionBody()) { BodyScope.Exit(); return Actions.ActOnSkippedFunctionBody(DP); @@ -1217,7 +1234,7 @@ return Res; } - if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && + if (SkipFunctionBodyRequested && (!Res || Actions.canSkipFunctionBody(Res)) && trySkippingFunctionBody()) { BodyScope.Exit(); Actions.ActOnSkippedFunctionBody(Res); Index: lib/Parse/ParseAST.cpp =================================================================== --- lib/Parse/ParseAST.cpp +++ lib/Parse/ParseAST.cpp @@ -100,7 +100,7 @@ ASTContext &Ctx, bool PrintStats, TranslationUnitKind TUKind, CodeCompleteConsumer *CompletionConsumer, - bool SkipFunctionBodies) { + SkipFunctionBodiesKind SkipFunctionBodies) { std::unique_ptr<Sema> S( new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); @@ -111,7 +111,7 @@ ParseAST(*S.get(), PrintStats, SkipFunctionBodies); } -void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { +void clang::ParseAST(Sema &S, bool PrintStats, SkipFunctionBodiesKind SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Index: lib/Frontend/ASTUnit.cpp =================================================================== --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -1612,9 +1612,37 @@ return AST; } +namespace { +class SkipFunctionBodiesModifierRAII { +public: + SkipFunctionBodiesModifierRAII( + FrontendOptions &FrontendOpts, + ASTUnit::SkipFunctionBodiesOptions SkipFunctionBodiesOpts) + : FrontendOpts(FrontendOpts), + PreviousValue(FrontendOpts.SkipFunctionBodies) { + if (SkipFunctionBodiesOpts.Scope == + ASTUnit::SkipFunctionBodiesOptions::Preamble) { + FrontendOpts.SkipFunctionBodies = + SkipFunctionBodiesOpts.LimitToNonTemplateFunctions + ? SkipFunctionBodies_AllExceptTemplates + : SkipFunctionBodies_All; + } + } + + ~SkipFunctionBodiesModifierRAII() { + FrontendOpts.SkipFunctionBodies = PreviousValue; + } + +private: + FrontendOptions &FrontendOpts; + SkipFunctionBodiesKind PreviousValue; +}; +} // namespace + bool ASTUnit::LoadFromCompilerInvocation( std::shared_ptr<PCHContainerOperations> PCHContainerOps, unsigned PrecompilePreambleAfterNParses, + SkipFunctionBodiesOptions SkipFunctionBodiesOpts, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { if (!Invocation) return true; @@ -1630,8 +1658,12 @@ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (PrecompilePreambleAfterNParses > 0) { PreambleRebuildCounter = PrecompilePreambleAfterNParses; - OverrideMainBuffer = - getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); + { + SkipFunctionBodiesModifierRAII m(Invocation->getFrontendOpts(), + SkipFunctionBodiesOpts); + OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( + PCHContainerOps, *Invocation, VFS); + } getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); } @@ -1678,6 +1710,7 @@ if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), PrecompilePreambleAfterNParses, + SkipFunctionBodiesOptions(), AST->FileMgr->getVirtualFileSystem())) return nullptr; return AST; @@ -1691,7 +1724,7 @@ ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, - bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, + bool AllowPCHWithCompilerErrors, SkipFunctionBodiesOptions SkipFunctionBodiesOpts, bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { @@ -1724,7 +1757,14 @@ // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; - CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies; + if (SkipFunctionBodiesOpts.Scope == SkipFunctionBodiesOptions::MainFileAndPreamble) { + CI->getFrontendOpts().SkipFunctionBodies = + SkipFunctionBodiesOpts.LimitToNonTemplateFunctions + ? SkipFunctionBodies_AllExceptTemplates + : SkipFunctionBodies_All; + } else { + CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies_None; + } if (ModuleFormat) CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue(); @@ -1762,6 +1802,7 @@ if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), PrecompilePreambleAfterNParses, + SkipFunctionBodiesOpts, VFS)) { // Some error occurred, if caller wants to examine diagnostics, pass it the // ASTUnit. @@ -1777,6 +1818,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, ArrayRef<RemappedFile> RemappedFiles, + SkipFunctionBodiesOptions SkipFunBodiesOpts, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { if (!Invocation) return true; @@ -1805,9 +1847,12 @@ // If we have a preamble file lying around, or if we might try to // build a precompiled preamble, do so now. std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; - if (Preamble || PreambleRebuildCounter > 0) + if (Preamble || PreambleRebuildCounter > 0) { + SkipFunctionBodiesModifierRAII m(Invocation->getFrontendOpts(), + SkipFunBodiesOpts); OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); + } // Clear out the diagnostics state. FileMgr.reset(); Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -18,6 +18,7 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Basic/Specifiers.h" +#include "clang/Frontend/SkipFunctionBodies.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" @@ -261,15 +262,15 @@ /// /// This option can be used, for example, to speed up searches for /// declarations/definitions when indexing. - bool SkipFunctionBodies; + SkipFunctionBodiesKind SkipFunctionBodies; /// The location of the expression statement that is being parsed right now. /// Used to determine if an expression that is being parsed is a statement or /// just a regular sub-expression. SourceLocation ExprStatementTokLoc; public: - Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); + Parser(Preprocessor &PP, Sema &Actions, SkipFunctionBodiesKind SkipFunctionBodies); ~Parser() override; const LangOptions &getLangOpts() const { return PP.getLangOpts(); } Index: include/clang/Parse/ParseAST.h =================================================================== --- include/clang/Parse/ParseAST.h +++ include/clang/Parse/ParseAST.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_PARSE_PARSEAST_H #include "clang/Basic/LangOptions.h" +#include "clang/Frontend/SkipFunctionBodies.h" namespace clang { class Preprocessor; @@ -40,12 +41,12 @@ ASTContext &Ctx, bool PrintStats = false, TranslationUnitKind TUKind = TU_Complete, CodeCompleteConsumer *CompletionConsumer = nullptr, - bool SkipFunctionBodies = false); + SkipFunctionBodiesKind SkipFunctionBodies = SkipFunctionBodies_None); /// \brief Parse the main file known to the preprocessor, producing an /// abstract syntax tree. void ParseAST(Sema &S, bool PrintStats = false, - bool SkipFunctionBodies = false); + SkipFunctionBodiesKind SkipFunctionBodies = SkipFunctionBodies_None); } // end namespace clang Index: include/clang/Frontend/SkipFunctionBodies.h =================================================================== --- /dev/null +++ include/clang/Frontend/SkipFunctionBodies.h @@ -0,0 +1,25 @@ +//===--- FrontendOptions.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SKIPFUNCTIONBODIES_H +#define LLVM_CLANG_FRONTEND_SKIPFUNCTIONBODIES_H + +namespace clang { + +/// Skip over function bodies to speed up parsing in cases you do not need +/// them (e.g. with code completion). +enum SkipFunctionBodiesKind { + SkipFunctionBodies_None, + SkipFunctionBodies_All, + SkipFunctionBodies_AllExceptTemplates, +}; + +} // end namespace clang + +#endif Index: include/clang/Frontend/FrontendOptions.h =================================================================== --- include/clang/Frontend/FrontendOptions.h +++ include/clang/Frontend/FrontendOptions.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Frontend/SkipFunctionBodies.h" #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Sema/CodeCompleteOptions.h" #include "llvm/ADT/StringRef.h" @@ -274,10 +275,6 @@ /// Emit ARC errors even if the migrator can fix them. unsigned ARCMTMigrateEmitARCErrors : 1; - /// Skip over function bodies to speed up parsing in cases you do not need - /// them (e.g. with code completion). - unsigned SkipFunctionBodies : 1; - /// Whether we can use the global module index if available. unsigned UseGlobalModuleIndex : 1; @@ -302,6 +299,8 @@ /// Whether timestamps should be written to the produced PCH file. unsigned IncludeTimestamps : 1; + SkipFunctionBodiesKind SkipFunctionBodies; + CodeCompleteOptions CodeCompleteOpts; enum { @@ -444,10 +443,10 @@ ShowStats(false), ShowTimers(false), ShowVersion(false), FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), - SkipFunctionBodies(false), UseGlobalModuleIndex(true), - GenerateGlobalModuleIndex(true), ASTDumpDecls(false), - ASTDumpLookups(false), BuildingImplicitModule(false), - ModulesEmbedAllFiles(false), IncludeTimestamps(true) {} + UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true), + ASTDumpDecls(false), ASTDumpLookups(false), + BuildingImplicitModule(false), ModulesEmbedAllFiles(false), + IncludeTimestamps(true), SkipFunctionBodies(SkipFunctionBodies_None) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return InputKind::C. Index: include/clang/Frontend/ASTUnit.h =================================================================== --- include/clang/Frontend/ASTUnit.h +++ include/clang/Frontend/ASTUnit.h @@ -675,6 +675,12 @@ bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, bool UserFilesAreVolatile = false); + struct SkipFunctionBodiesOptions { + SkipFunctionBodiesOptions() {} + enum { None, MainFileAndPreamble, Preamble } Scope = None; + bool LimitToNonTemplateFunctions = false; + }; + private: /// \brief Helper function for \c LoadFromCompilerInvocation() and /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation. @@ -693,6 +699,7 @@ bool LoadFromCompilerInvocation( std::shared_ptr<PCHContainerOperations> PCHContainerOps, unsigned PrecompilePreambleAfterNParses, + SkipFunctionBodiesOptions SkipFunctionBodiesOpts, IntrusiveRefCntPtr<vfs::FileSystem> VFS); public: @@ -801,9 +808,10 @@ 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, + bool AllowPCHWithCompilerErrors = false, + SkipFunctionBodiesOptions SkipFunctionBodiesOpts = SkipFunctionBodiesOptions(), + 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); @@ -821,6 +829,7 @@ /// contain any translation-unit information, false otherwise. bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, ArrayRef<RemappedFile> RemappedFiles = None, + SkipFunctionBodiesOptions SkipFunctionBodiesOpts = SkipFunctionBodiesOptions(), IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); /// \brief Free data that will be re-generated on the next parse. Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -1324,7 +1324,24 @@ /** * \brief 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, + + /** + * \brief Used in combination with CXTranslationUnit_SkipFunctionBodies to + * exclude template function bodies from being skipped. + * + * Parsing template function bodies allows diagnostics for wrong/incomplete + * template instantiations. + */ + CXTranslationUnit_LimitSkipFunctionBodiesToNonTemplates = 0x1000, }; /**
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits