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

Reply via email to