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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits