Dmitry.Kozhevnikov updated this revision to Diff 160848. Dmitry.Kozhevnikov changed the repository for this revision from rCTE Clang Tools Extra to rC Clang. Dmitry.Kozhevnikov added a comment.
Addressed the review comment about separating "suppressing diagnostics" from "providing more complete AST" Repository: rC Clang https://reviews.llvm.org/D50462 Files: include/clang/Basic/Diagnostic.h lib/Lex/PPDirectives.cpp lib/Sema/SemaTemplateInstantiate.cpp unittests/Frontend/PCHPreambleTest.cpp
Index: unittests/Frontend/PCHPreambleTest.cpp =================================================================== --- unittests/Frontend/PCHPreambleTest.cpp +++ unittests/Frontend/PCHPreambleTest.cpp @@ -77,7 +77,8 @@ RemappedFiles[Filename] = Contents; } - std::unique_ptr<ASTUnit> ParseAST(const std::string &EntryFile) { + std::unique_ptr<ASTUnit> ParseAST(const std::string &EntryFile, + bool SuppressAfterFatalError = true) { PCHContainerOpts = std::make_shared<PCHContainerOperations>(); std::shared_ptr<CompilerInvocation> CI(new CompilerInvocation); CI->getFrontendOpts().Inputs.push_back( @@ -88,11 +89,15 @@ CI->getPreprocessorOpts().RemappedFileBuffers = GetRemappedFiles(); + CI->getLangOpts()->CPlusPlus = true; + CI->getLangOpts()->CPlusPlus11 = true; + PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); PPOpts.RemappedFilesKeepOriginalName = true; IntrusiveRefCntPtr<DiagnosticsEngine> Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, new DiagnosticConsumer)); + Diags->setSuppressAfterFatalError(SuppressAfterFatalError); FileManager *FileMgr = new FileManager(FSOpts, VFS); @@ -197,4 +202,34 @@ ASSERT_LE(HeaderReadCount, GetFileReadCount(Header)); } +TEST_F(PCHPreambleTest, MissingHeader) { + std::string Header1 = "//./header1.h"; + AddFile(Header1, "template <class T, class U = int> class C;\n" + "template <class T, class U> class C{};\n"); + + std::string Header2 = "//./header2.h"; + AddFile(Header2, "using Alias = C<int>;\n"); + + std::string Main = "//./main.cpp"; + AddFile(Main, "#include \"nonexistent1\"\n" + "#include \"//./header1.h\"\n" + "#include \"nonexistent2\"\n" + "#include \"//./header2.h\"\n" + "Alias Var;"); + + std::unique_ptr<ASTUnit> AST( + ParseAST(Main, /*SuppressAfterFatalError=*/false)); + ASSERT_TRUE(AST.get()); + + // only "file not found" errors should be emitted, + // "Alias" should be visible for lookup. + auto ExpectedErrorsCount = 2u; + + ASSERT_EQ(AST->getDiagnostics().getClient()->getNumErrors(), + ExpectedErrorsCount); + ASSERT_TRUE(ReparseAST(AST)); + ASSERT_EQ(AST->getDiagnostics().getClient()->getNumErrors(), + ExpectedErrorsCount); +} + } // anonymous namespace Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -219,6 +219,7 @@ // error have occurred. Any diagnostics we might have raised will not be // visible, and we do not need to construct a correct AST. if (SemaRef.Diags.hasFatalErrorOccurred() && + !SemaRef.Diags.shouldRecoverAfterFatalErrors() && SemaRef.Diags.hasUncompilableErrorOccurred()) { Invalid = true; return; Index: lib/Lex/PPDirectives.cpp =================================================================== --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -1899,7 +1899,8 @@ // Any diagnostics after the fatal error will not be visible. As the // compilation failed already and errors in subsequently included files won't // be visible, avoid preprocessing those files. - if (ShouldEnter && Diags->hasFatalErrorOccurred()) + if (ShouldEnter && Diags->hasFatalErrorOccurred() && + !Diags->shouldRecoverAfterFatalErrors()) ShouldEnter = false; // Determine whether we should try to import the module for this #include, if Index: include/clang/Basic/Diagnostic.h =================================================================== --- include/clang/Basic/Diagnostic.h +++ include/clang/Basic/Diagnostic.h @@ -752,6 +752,15 @@ } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } + /// Determine whether the client should because a fatal error was issued, so + /// clients can cut off extra processing that might be wasteful in this case. + bool shouldRecoverAfterFatalErrors() const { + // todo: a separate flag might be required for a client that doesn't want to + // show any errors after the fatal, but still wants to collect as much + // information from the source code as possible. + return SuppressAfterFatalError; + } + /// Determine whether any kind of unrecoverable error has occurred. bool hasUnrecoverableErrorOccurred() const { return FatalErrorOccurred || UnrecoverableErrorOccurred;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits