<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 4 May 2017 at 12:43, Alex L <span dir="ltr"><<a href="mailto:arphaman@gmail.com" target="_blank">arphaman@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On 3 May 2017 at 22:23, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="m_-3344927875361258693gmail-">On 3 May 2017 at 07:29, Alex L <span dir="ltr"><<a href="mailto:arphaman@gmail.com" target="_blank">arphaman@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Richard,<div><br></div><div>This commit has caused an infinite loop in one of our internal libclang based tooling tests. It keeps repeating the following frames:</div><div><br></div><div><div>    frame #33528: 0x0000000109db2edf libclang.dylib`clang::Diagnost<wbr>icsEngine::ReportDelayed(this=<wbr>0x000000011c002c00) at Diagnostic.cpp:149</div><div>    frame #33529: 0x0000000109db5a36 libclang.dylib`clang::Diagnost<wbr>icsEngine::EmitCurrentDiagnost<wbr>ic(this=0x000000011c002c00, Force=false) at Diagnostic.cpp:428</div><div>    frame #33530: 0x000000010a33f93c libclang.dylib`clang::Diagnost<wbr>icBuilder::Emit(this=0x0000700<wbr>008d4bfd8) at Diagnostic.h:1013</div><div>    frame #33531: 0x000000010a33f8e5 libclang.dylib`clang::Diagnost<wbr>icBuilder::~DiagnosticBuilder(<wbr>this=0x0000700008d4bfd8) at Diagnostic.h:1036</div><div>    frame #33532: 0x000000010a335015 libclang.dylib`clang::Diagnost<wbr>icBuilder::~DiagnosticBuilder(<wbr>this=0x0000700008d4bfd8) at Diagnostic.h:1035</div></div><div><br></div><div>It doesn't really look like a regression though, it seems that this has just uncovered a bug in Clang: DiagnosticsEngine::ReportDelay<wbr>ed is clearing DelayedDiagID *after* reporting the issue which causes the infinite recursion, when it should clear it before. Is that right?</div></div></blockquote><div><br></div></span><div>EmitCurrentDiagnostic checks "DelayedDiagID != DiagID" before making the recursive call, which should be preventing the infinite recursion.</div><div><br></div><div>It looks like the immediate bug is that EmitCurrentDiagnostic grabs CurDiagID *after* calling EmitDiag / ProcessDiag, which clear CurDiagID when they succeed in emitting the diagnostic. But I agree, the right thing to do is clear DelayedDiagID before emitting the delayed diagnostic, not after. You should also be able to delete the incorrect recursion check in EmitCurrentDiagnostic too.</div></div></div></div></blockquote><div><br></div></span><div>Thanks, that makes sense.</div><div><br></div><div><div>Unfortunately I had to revert my fix as it uncovered two issues in Misc/error-limit-multiple-<wbr>notes.cpp and Misc/error-limit.c . It looks like your commit caused the infinite recursion in both of them, but the bots didn't catch that because they invoked not clang, and emitted the diagnostics that were checked (using FileCheck) before crashing, so they "passed". However, my fix causes the tests to fail, seemingly because now Clang doesn't suppress multiple notes after reaching the error limit (it suppresses just the first note). It looks like this is a regression introduced in this commit.</div></div><div><div class="h5"><div><br></div></div></div></div></div></div></blockquote><div>Sorry, I was wrong in my analysis. It's not a regression introduced by your commit, it's just a problem with my fix.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5"><div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="m_-3344927875361258693gmail-"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I will commit a fix for this now.</div></div></blockquote><div><br></div></span><div>Thank you!</div><div><div class="m_-3344927875361258693gmail-h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><span class="m_-3344927875361258693gmail-m_7144615206678599907HOEnZb"><font color="#888888"><div>Alex</div><div><br></div></font></span></div><div class="m_-3344927875361258693gmail-m_7144615206678599907HOEnZb"><div class="m_-3344927875361258693gmail-m_7144615206678599907h5"><div class="gmail_extra"><br><div class="gmail_quote">On 3 May 2017 at 01:28, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Author: rsmith<br>
Date: Tue May  2 19:28:49 2017<br>
New Revision: 301992<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=301992&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=301992&view=rev</a><br>
Log:<br>
[modules] Round-trip -Werror flag through explicit module build.<br>
<br>
The intent for an explicit module build is that the diagnostics produced within<br>
the module are those that were configured when the module was built, not those<br>
that are enabled within a user of the module. This includes diagnostics that<br>
don't actually show up until the module is used (for instance, diagnostics<br>
produced during template instantiation and weird cases like -Wpadded).<br>
<br>
We serialized and restored the diagnostic state for individual warning groups,<br>
but previously did not track the state for flags like -Werror and -Weverything,<br>
which are implemented as separate bits rather than as part of the diagnostics<br>
mapping information.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/<wbr>Diagnostic.h<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticIDs.h<br>
    cfe/trunk/lib/Basic/Diagnostic<wbr>.cpp<br>
    cfe/trunk/lib/Basic/Diagnostic<wbr>IDs.cpp<br>
    cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp<br>
    cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp<br>
    cfe/trunk/test/Index/keep-goin<wbr>g.cpp<br>
    cfe/trunk/test/Modules/diag-fl<wbr>ags.cpp<br>
    cfe/trunk/tools/libclang/CInde<wbr>x.cpp<br>
    cfe/trunk/unittests/Basic/Diag<wbr>nosticTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>Diagnostic.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/Diagnostic.h?rev=301992&<wbr>r1=301991&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>Diagnostic.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>Diagnostic.h Tue May  2 19:28:49 2017<br>
@@ -178,12 +178,7 @@ public:<br>
<br>
 private:<br>
   unsigned char AllExtensionsSilenced; // Used by __extension__<br>
-  bool IgnoreAllWarnings;        // Ignore all warnings: -w<br>
-  bool WarningsAsErrors;         // Treat warnings like errors.<br>
-  bool EnableAllWarnings;        // Enable all warnings.<br>
-  bool ErrorsAsFatal;            // Treat errors like fatal errors.<br>
-  bool FatalsAsError;             // Treat fatal errors like errors.<br>
-  bool SuppressSystemWarnings;   // Suppress warnings in system headers.<br>
+  bool SuppressAfterFatalError;  // Suppress diagnostics after a fatal error?<br>
   bool SuppressAllDiagnostics;   // Suppress all diagnostics.<br>
   bool ElideType;                // Elide common types of templates.<br>
   bool PrintTemplateTree;        // Print a tree when comparing templates.<br>
@@ -194,7 +189,6 @@ private:<br>
                                    // 0 -> no limit.<br>
   unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation<br>
                                     // backtrace stack, 0 -> no limit.<br>
-  diag::Severity ExtBehavior;       // Map extensions to warnings or errors?<br>
   IntrusiveRefCntPtr<Diagnostic<wbr>IDs> Diags;<br>
   IntrusiveRefCntPtr<Diagnostic<wbr>Options> DiagOpts;<br>
   DiagnosticConsumer *Client;<br>
@@ -216,6 +210,19 @@ private:<br>
     llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap;<br>
<br>
   public:<br>
+    // "Global" configuration state that can actually vary between modules.<br>
+    unsigned IgnoreAllWarnings : 1;      // Ignore all warnings: -w<br>
+    unsigned EnableAllWarnings : 1;      // Enable all warnings.<br>
+    unsigned WarningsAsErrors : 1;       // Treat warnings like errors.<br>
+    unsigned ErrorsAsFatal : 1;          // Treat errors like fatal errors.<br>
+    unsigned SuppressSystemWarnings : 1; // Suppress warnings in system headers.<br>
+    diag::Severity ExtBehavior : 4;     // Map extensions to warnings or errors?<br>
+<br>
+    DiagState()<br>
+        : IgnoreAllWarnings(false), EnableAllWarnings(false),<br>
+          WarningsAsErrors(false), ErrorsAsFatal(false),<br>
+          SuppressSystemWarnings(false), ExtBehavior(diag::Severity::Ig<wbr>nored) {}<br>
+<br>
     typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator;<br>
     typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iter<wbr>ator<br>
     const_iterator;<br>
@@ -493,33 +500,47 @@ public:<br>
   /// \brief When set to true, any unmapped warnings are ignored.<br>
   ///<br>
   /// If this and WarningsAsErrors are both set, then this one wins.<br>
-  void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }<br>
-  bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }<br>
+  void setIgnoreAllWarnings(bool Val) {<br>
+    GetCurDiagState()->IgnoreAllWa<wbr>rnings = Val;<br>
+  }<br>
+  bool getIgnoreAllWarnings() const {<br>
+    return GetCurDiagState()->IgnoreAllWa<wbr>rnings;<br>
+  }<br>
<br>
   /// \brief When set to true, any unmapped ignored warnings are no longer<br>
   /// ignored.<br>
   ///<br>
   /// If this and IgnoreAllWarnings are both set, then that one wins.<br>
-  void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }<br>
-  bool getEnableAllWarnings() const { return EnableAllWarnings; }<br>
+  void setEnableAllWarnings(bool Val) {<br>
+    GetCurDiagState()->EnableAllWa<wbr>rnings = Val;<br>
+  }<br>
+  bool getEnableAllWarnings() const {<br>
+    return GetCurDiagState()->EnableAllWa<wbr>rnings;<br>
+  }<br>
<br>
   /// \brief When set to true, any warnings reported are issued as errors.<br>
-  void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }<br>
-  bool getWarningsAsErrors() const { return WarningsAsErrors; }<br>
+  void setWarningsAsErrors(bool Val) {<br>
+    GetCurDiagState()->WarningsAsE<wbr>rrors = Val;<br>
+  }<br>
+  bool getWarningsAsErrors() const {<br>
+    return GetCurDiagState()->WarningsAsE<wbr>rrors;<br>
+  }<br>
<br>
   /// \brief When set to true, any error reported is made a fatal error.<br>
-  void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }<br>
-  bool getErrorsAsFatal() const { return ErrorsAsFatal; }<br>
+  void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFat<wbr>al = Val; }<br>
+  bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFat<wbr>al; }<br>
<br>
-  /// \brief When set to true, any fatal error reported is made an error.<br>
-  ///<br>
-  /// This setting takes precedence over the setErrorsAsFatal setting above.<br>
-  void setFatalsAsError(bool Val) { FatalsAsError = Val; }<br>
-  bool getFatalsAsError() const { return FatalsAsError; }<br>
+  /// \brief When set to true (the default), suppress further diagnostics after<br>
+  /// a fatal error.<br>
+  void setSuppressAfterFatalError(boo<wbr>l Val) { SuppressAfterFatalError = Val; }<br>
<br>
   /// \brief When set to true mask warnings that come from system headers.<br>
-  void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }<br>
-  bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }<br>
+  void setSuppressSystemWarnings(bool Val) {<br>
+    GetCurDiagState()->SuppressSys<wbr>temWarnings = Val;<br>
+  }<br>
+  bool getSuppressSystemWarnings() const {<br>
+    return GetCurDiagState()->SuppressSys<wbr>temWarnings;<br>
+  }<br>
<br>
   /// \brief Suppress all diagnostics, to silence the front end when we<br>
   /// know that we don't want any more diagnostics to be passed along to the<br>
@@ -571,11 +592,15 @@ public:<br>
   }<br>
<br>
   /// \brief Controls whether otherwise-unmapped extension diagnostics are<br>
-  /// mapped onto ignore/warning/error.<br>
+  /// mapped onto ignore/warning/error.<br>
   ///<br>
   /// This corresponds to the GCC -pedantic and -pedantic-errors option.<br>
-  void setExtensionHandlingBehavior(d<wbr>iag::Severity H) { ExtBehavior = H; }<br>
-  diag::Severity getExtensionHandlingBehavior() const { return ExtBehavior; }<br>
+  void setExtensionHandlingBehavior(d<wbr>iag::Severity H) {<br>
+    GetCurDiagState()->ExtBehavior = H;<br>
+  }<br>
+  diag::Severity getExtensionHandlingBehavior() const {<br>
+    return GetCurDiagState()->ExtBehavior<wbr>;<br>
+  }<br>
<br>
   /// \brief Counter bumped when an __extension__  block is/ encountered.<br>
   ///<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticIDs.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/DiagnosticIDs.h?rev=3019<wbr>92&r1=301991&r2=301992&view=di<wbr>ff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticIDs.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticIDs.h Tue May  2 19:28:49 2017<br>
@@ -122,15 +122,21 @@ public:<br>
   bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; }<br>
   void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; }<br>
<br>
-  /// Serialize the bits that aren't based on context.<br>
-  unsigned serializeBits() const {<br>
-    return (WasUpgradedFromWarning << 3) | Severity;<br>
+  /// Serialize this mapping as a raw integer.<br>
+  unsigned serialize() const {<br>
+    return (IsUser << 7) | (IsPragma << 6) | (HasNoWarningAsError << 5) |<br>
+           (HasNoErrorAsFatal << 4) | (WasUpgradedFromWarning << 3) | Severity;<br>
   }<br>
-  static diag::Severity deserializeSeverity(unsigned Bits) {<br>
-    return (diag::Severity)(Bits & 0x7);<br>
-  }<br>
-  static bool deserializeUpgradedFromWarning<wbr>(unsigned Bits) {<br>
-    return Bits >> 3;<br>
+  /// Deserialize a mapping.<br>
+  static DiagnosticMapping deserialize(unsigned Bits) {<br>
+    DiagnosticMapping Result;<br>
+    Result.IsUser = (Bits >> 7) & 1;<br>
+    Result.IsPragma = (Bits >> 6) & 1;<br>
+    Result.HasNoWarningAsError = (Bits >> 5) & 1;<br>
+    Result.HasNoErrorAsFatal = (Bits >> 4) & 1;<br>
+    Result.WasUpgradedFromWarning = (Bits >> 3) & 1;<br>
+    Result.Severity = Bits & 0x7;<br>
+    return Result;<br>
   }<br>
 };<br>
<br>
<br>
Modified: cfe/trunk/lib/Basic/Diagnostic<wbr>.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Basic/Diag<wbr>nostic.cpp?rev=301992&r1=30199<wbr>1&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Basic/Diagnostic<wbr>.cpp (original)<br>
+++ cfe/trunk/lib/Basic/Diagnostic<wbr>.cpp Tue May  2 19:28:49 2017<br>
@@ -67,18 +67,12 @@ DiagnosticsEngine::Diagnostics<wbr>Engine(Int<br>
   ArgToStringCookie = nullptr;<br>
<br>
   AllExtensionsSilenced = 0;<br>
-  IgnoreAllWarnings = false;<br>
-  WarningsAsErrors = false;<br>
-  EnableAllWarnings = false;<br>
-  ErrorsAsFatal = false;<br>
-  FatalsAsError = false;<br>
-  SuppressSystemWarnings = false;<br>
+  SuppressAfterFatalError = true;<br>
   SuppressAllDiagnostics = false;<br>
   ElideType = true;<br>
   PrintTemplateTree = false;<br>
   ShowColors = false;<br>
   ShowOverloads = Ovl_All;<br>
-  ExtBehavior = diag::Severity::Ignored;<br>
<br>
   ErrorLimit = 0;<br>
   TemplateBacktraceLimit = 0;<br>
@@ -343,8 +337,8 @@ bool DiagnosticsEngine::setDiagnost<wbr>icGro<br>
     return setSeverityForGroup(diag::Flav<wbr>or::WarningOrError, Group,<br>
                                diag::Severity::Fatal);<br>
<br>
-  // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and<br>
-  // potentially downgrade anything already mapped to be an error.<br>
+  // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,<br>
+  // and potentially downgrade anything already mapped to be a fatal error.<br>
<br>
   // Get the diagnostics in this group.<br>
   SmallVector<diag::kind, 8> GroupDiags;<br>
<br>
Modified: cfe/trunk/lib/Basic/Diagnostic<wbr>IDs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/DiagnosticIDs.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Basic/Diag<wbr>nosticIDs.cpp?rev=301992&r1=30<wbr>1991&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Basic/Diagnostic<wbr>IDs.cpp (original)<br>
+++ cfe/trunk/lib/Basic/Diagnostic<wbr>IDs.cpp Tue May  2 19:28:49 2017<br>
@@ -420,7 +420,7 @@ DiagnosticIDs::getDiagnosticSe<wbr>verity(uns<br>
     Result = Mapping.getSeverity();<br>
<br>
   // Upgrade ignored diagnostics if -Weverything is enabled.<br>
-  if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored &&<br>
+  if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&<br>
       !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)<br>
     Result = diag::Severity::Warning;<br>
<br>
@@ -435,7 +435,7 @@ DiagnosticIDs::getDiagnosticSe<wbr>verity(uns<br>
   // For extension diagnostics that haven't been explicitly mapped, check if we<br>
   // should upgrade the diagnostic.<br>
   if (IsExtensionDiag && !Mapping.isUser())<br>
-    Result = std::max(Result, Diag.ExtBehavior);<br>
+    Result = std::max(Result, State->ExtBehavior);<br>
<br>
   // At this point, ignored errors can no longer be upgraded.<br>
   if (Result == diag::Severity::Ignored)<br>
@@ -443,28 +443,24 @@ DiagnosticIDs::getDiagnosticSe<wbr>verity(uns<br>
<br>
   // Honor -w, which is lower in priority than pedantic-errors, but higher than<br>
   // -Werror.<br>
-  if (Result == diag::Severity::Warning && Diag.IgnoreAllWarnings)<br>
+  // FIXME: Under GCC, this also suppresses warnings that have been mapped to<br>
+  // errors by -W flags and #pragma diagnostic.<br>
+  if (Result == diag::Severity::Warning && State->IgnoreAllWarnings)<br>
     return diag::Severity::Ignored;<br>
<br>
   // If -Werror is enabled, map warnings to errors unless explicitly disabled.<br>
   if (Result == diag::Severity::Warning) {<br>
-    if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError()<wbr>)<br>
+    if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()<wbr>)<br>
       Result = diag::Severity::Error;<br>
   }<br>
<br>
   // If -Wfatal-errors is enabled, map errors to fatal unless explicity<br>
   // disabled.<br>
   if (Result == diag::Severity::Error) {<br>
-    if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())<br>
+    if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())<br>
       Result = diag::Severity::Fatal;<br>
   }<br>
<br>
-  // If explicitly requested, map fatal errors to errors.<br>
-  if (Result == diag::Severity::Fatal) {<br>
-      if (Diag.FatalsAsError)<br>
-        Result = diag::Severity::Error;<br>
-  }<br>
-<br>
   // Custom diagnostics always are emitted in system headers.<br>
   bool ShowInSystemHeader =<br>
       !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowI<wbr>nSystemHeader;<br>
@@ -472,7 +468,7 @@ DiagnosticIDs::getDiagnosticSe<wbr>verity(uns<br>
   // If we are in a system header, we ignore it. We look at the diagnostic class<br>
   // because we also want to ignore extensions and warnings in -Werror and<br>
   // -pedantic-errors modes, which *map* warnings/extensions to errors.<br>
-  if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&<br>
+  if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&<br>
       Diag.getSourceManager().isInS<wbr>ystemHeader(<br>
           Diag.getSourceManager().getEx<wbr>pansionLoc(Loc)))<br>
     return diag::Severity::Ignored;<br>
@@ -632,7 +628,7 @@ bool DiagnosticIDs::ProcessDiag(Dia<wbr>gnost<br>
<br>
   // If a fatal error has already been emitted, silence all subsequent<br>
   // diagnostics.<br>
-  if (Diag.FatalErrorOccurred) {<br>
+  if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) {<br>
     if (DiagLevel >= DiagnosticIDs::Error &&<br>
         Diag.Client->IncludeInDiagnos<wbr>ticCounts()) {<br>
       ++Diag.NumErrors;<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTReader.cpp?rev=301992&r<wbr>1=301991&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp Tue May  2 19:28:49 2017<br>
@@ -5531,14 +5531,8 @@ void ASTReader::ReadPragmaDiagnosti<wbr>cMapp<br>
              "Invalid data, not enough diag/map pairs");<br>
       while (Size--) {<br>
         unsigned DiagID = Record[Idx++];<br>
-        unsigned SeverityAndUpgradedFromWarning = Record[Idx++];<br>
-        bool WasUpgradedFromWarning =<br>
-            DiagnosticMapping::deserialize<wbr>UpgradedFromWarning(<br>
-                SeverityAndUpgradedFromWarning<wbr>);<br>
         DiagnosticMapping NewMapping =<br>
-            Diag.makeUserMapping(Diagnosti<wbr>cMapping::deserializeSeverity(<br>
-                                     SeverityAndUpgradedFromWarnin<wbr>g),<br>
-                                 Loc);<br>
+            DiagnosticMapping::deserialize<wbr>(Record[Idx++]);<br>
         if (!NewMapping.isPragma() && !IncludeNonPragmaStates)<br>
           continue;<br>
<br>
@@ -5547,14 +5541,12 @@ void ASTReader::ReadPragmaDiagnosti<wbr>cMapp<br>
         // If this mapping was specified as a warning but the severity was<br>
         // upgraded due to diagnostic settings, simulate the current diagnostic<br>
         // settings (and use a warning).<br>
-        if (WasUpgradedFromWarning && !Mapping.isErrorOrFatal()) {<br>
-          Mapping = Diag.makeUserMapping(diag::Sev<wbr>erity::Warning, Loc);<br>
-          continue;<br>
+        if (NewMapping.wasUpgradedFromWar<wbr>ning() && !Mapping.isErrorOrFatal()) {<br>
+          NewMapping.setSeverity(diag::S<wbr>everity::Warning);<br>
+          NewMapping.setUpgradedFromWarn<wbr>ing(false);<br>
         }<br>
<br>
-        // Use the deserialized mapping verbatim.<br>
         Mapping = NewMapping;<br>
-        Mapping.setUpgradedFromWarning<wbr>(WasUpgradedFromWarning);<br>
       }<br>
       return NewState;<br>
     };<br>
@@ -5569,22 +5561,36 @@ void ASTReader::ReadPragmaDiagnosti<wbr>cMapp<br>
       DiagStates.push_back(FirstSta<wbr>te);<br>
<br>
       // Skip the initial diagnostic state from the serialized module.<br>
-      assert(Record[0] == 0 &&<br>
+      assert(Record[1] == 0 &&<br>
              "Invalid data, unexpected backref in initial state");<br>
-      Idx = 2 + Record[1] * 2;<br>
+      Idx = 3 + Record[2] * 2;<br>
       assert(Idx < Record.size() &&<br>
              "Invalid data, not enough state change pairs in initial state");<br>
+    } else if (F.isModule()) {<br>
+      // For an explicit module, preserve the flags from the module build<br>
+      // command line (-w, -Weverything, -Werror, ...) along with any explicit<br>
+      // -Wblah flags.<br>
+      unsigned Flags = Record[Idx++];<br>
+      DiagState Initial;<br>
+      Initial.SuppressSystemWarnings = Flags & 1; Flags >>= 1;<br>
+      Initial.ErrorsAsFatal = Flags & 1; Flags >>= 1;<br>
+      Initial.WarningsAsErrors = Flags & 1; Flags >>= 1;<br>
+      Initial.EnableAllWarnings = Flags & 1; Flags >>= 1;<br>
+      Initial.IgnoreAllWarnings = Flags & 1; Flags >>= 1;<br>
+      Initial.ExtBehavior = (diag::Severity)Flags;<br>
+      FirstState = ReadDiagState(Initial, SourceLocation(), true);<br>
+<br>
+      // Set up the root buffer of the module to start with the initial<br>
+      // diagnostic state of the module itself, to cover files that contain no<br>
+      // explicit transitions (for which we did not serialize anything).<br>
+      Diag.DiagStatesByLoc.Files[F.O<wbr>riginalSourceFileID]<br>
+          .StateTransitions.push_back({F<wbr>irstState, 0});<br>
     } else {<br>
-      FirstState = ReadDiagState(<br>
-          F.isModule() ? DiagState() : *Diag.DiagStatesByLoc.CurDiagS<wbr>tate,<br>
-          SourceLocation(), F.isModule());<br>
-<br>
-      // For an explicit module, set up the root buffer of the module to start<br>
-      // with the initial diagnostic state of the module itself, to cover files<br>
-      // that contain no explicit transitions.<br>
-      if (F.isModule())<br>
-        Diag.DiagStatesByLoc.Files[F.O<wbr>riginalSourceFileID]<br>
-            .StateTransitions.push_back({F<wbr>irstState, 0});<br>
+      // For prefix ASTs, start with whatever the user configured on the<br>
+      // command line.<br>
+      Idx++; // Skip flags.<br>
+      FirstState = ReadDiagState(*Diag.DiagStates<wbr>ByLoc.CurDiagState,<br>
+                                 SourceLocation(), false);<br>
     }<br>
<br>
     // Read the state transitions.<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTWriter.cpp?rev=301992&r<wbr>1=301991&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp Tue May  2 19:28:49 2017<br>
@@ -2868,8 +2868,26 @@ void ASTWriter::WritePragmaDiagnost<wbr>icMap<br>
   unsigned CurrID = 0;<br>
   RecordData Record;<br>
<br>
+  auto EncodeDiagStateFlags =<br>
+      [](const DiagnosticsEngine::DiagState *DS) -> unsigned {<br>
+    unsigned Result = (unsigned)DS->ExtBehavior;<br>
+    for (unsigned Val :<br>
+         {DS->IgnoreAllWarnings, DS->EnableAllWarnings, DS->WarningsAsErrors,<br>
+          DS->ErrorsAsFatal, DS->SuppressSystemWarnings})<br>
+      Result = (Result << 1) | Val;<br>
+    return Result;<br>
+  };<br>
+<br>
+  unsigned Flags = EncodeDiagStateFlags(Diag.Diag<wbr>StatesByLoc.FirstDiagState);<br>
+  Record.push_back(Flags);<br>
+<br>
   auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State,<br>
                           bool IncludeNonPragmaStates) {<br>
+    // Ensure that the diagnostic state wasn't modified since it was created.<br>
+    // We will not correctly round-trip this information otherwise.<br>
+    assert(Flags == EncodeDiagStateFlags(State) &&<br>
+           "diag state flags vary in single AST file");<br>
+<br>
     unsigned &DiagStateID = DiagStateIDMap[State];<br>
     Record.push_back(DiagStateID)<wbr>;<br>
<br>
@@ -2882,7 +2900,7 @@ void ASTWriter::WritePragmaDiagnost<wbr>icMap<br>
       for (const auto &I : *State) {<br>
         if (I.second.isPragma() || IncludeNonPragmaStates) {<br>
           Record.push_back(I.first);<br>
-          Record.push_back(I.second.seri<wbr>alizeBits());<br>
+          Record.push_back(I.second.seri<wbr>alize());<br>
         }<br>
       }<br>
       // Update the placeholder.<br>
<br>
Modified: cfe/trunk/test/Index/keep-goin<wbr>g.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/keep-going.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Index/kee<wbr>p-going.cpp?rev=301992&r1=3019<wbr>91&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Index/keep-goin<wbr>g.cpp (original)<br>
+++ cfe/trunk/test/Index/keep-goin<wbr>g.cpp Tue May  2 19:28:49 2017<br>
@@ -25,5 +25,5 @@ class C : public A<float> { };<br>
 // CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [templateargs/1= [type=float] [typekind=Float]] [canonicaltype=A<float>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1]<br>
 // CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0]<br>
<br>
-// CHECK-DIAG: keep-going.cpp:1:10: error: 'missing1.h' file not found<br>
-// CHECK-DIAG: keep-going.cpp:8:10: error: 'missing2.h' file not found<br>
+// CHECK-DIAG: keep-going.cpp:1:10: fatal error: 'missing1.h' file not found<br>
+// CHECK-DIAG: keep-going.cpp:8:10: fatal error: 'missing2.h' file not found<br>
<br>
Modified: cfe/trunk/test/Modules/diag-fl<wbr>ags.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/diag-flags.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Modules/d<wbr>iag-flags.cpp?rev=301992&r1=30<wbr>1991&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Modules/diag-fl<wbr>ags.cpp (original)<br>
+++ cfe/trunk/test/Modules/diag-fl<wbr>ags.cpp Tue May  2 19:28:49 2017<br>
@@ -1,20 +1,42 @@<br>
 // RUN: rm -rf %t<br>
 //<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -emit-module -fmodules-cache-path=%t -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DIMPLICIT_FLAG -Werror=padded<br>
-//<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/explicit.pcm -Werror=string-plus-int -Wpadded<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DEXPLICIT_FLAG -fmodule-file=%t/explicit.pcm<br>
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DEXPLICIT_FLAG -fmodule-file=%t/explicit.pcm -Werror=padded<br>
+// For an implicit module, all that matters are the warning flags in the user.<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodules-cache-path=%t -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -Wpadded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -Wpadded -Werror<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -Werror=padded<br>
+//<br>
+// For an explicit module, all that matters are the warning flags in the module build.<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/nodiag.pcm<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Wpadded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -fmodule-file=%t/nodiag.pcm -Werror -Wpadded<br>
+//<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/warning.pcm -Wpadded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm -Werror=padded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/warning.pcm -Werror<br>
+//<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/werror-no-error.pcm -Werror -Wpadded -Wno-error=padded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-err<wbr>or.pcm<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-err<wbr>or.pcm -Wno-padded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DWARNING -fmodule-file=%t/werror-no-err<wbr>or.pcm -Werror=padded<br>
+//<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/error.pcm -Werror=padded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -fmodule-file=%t/error.pcm -Wno-padded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -fmodule-file=%t/error.pcm -Wno-error=padded<br>
+//<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -emit-module -fmodule-name=diag_flags -x c++ %S/Inputs/module.map -fmodules-ts -o %t/werror.pcm -Werror -Wpadded<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -fmodule-file=%t/werror.pcm -Wno-error<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fmodules -fimplicit-module-maps -verify -fmodules-cache-path=%t -I %S/Inputs %s -fmodules-ts -DERROR -fmodule-file=%t/werror.pcm -Wno-padded<br>
<br>
 import diag_flags;<br>
<br>
 // Diagnostic flags from the module user make no difference to diagnostics<br>
 // emitted within the module when using an explicitly-loaded module.<br>
-#ifdef IMPLICIT_FLAG<br>
+#if ERROR<br>
 // expected-error@diag_flags.h:14 {{padding struct}}<br>
-#elif defined(EXPLICIT_FLAG)<br>
+#elif WARNING<br>
 // expected-warning@diag_flags.h:<wbr>14 {{padding struct}}<br>
 #else<br>
 // expected-no-diagnostics<br>
<br>
Modified: cfe/trunk/tools/libclang/CInde<wbr>x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/tools/libclang<wbr>/CIndex.cpp?rev=301992&r1=3019<wbr>91&r2=301992&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/libclang/CInde<wbr>x.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CInde<wbr>x.cpp Tue May  2 19:28:49 2017<br>
@@ -3313,7 +3313,7 @@ clang_parseTranslationUnit_Imp<wbr>l(CXIndex<br>
     Diags(CompilerInstance::creat<wbr>eDiagnostics(new DiagnosticOptions));<br>
<br>
   if (options & CXTranslationUnit_KeepGoing)<br>
-    Diags->setFatalsAsError(true);<br>
+    Diags->setSuppressAfterFatalEr<wbr>ror(false);<br>
<br>
   // Recover resources if we crash before exiting this function.<br>
   llvm::CrashRecoveryContextCle<wbr>anupRegistrar<DiagnosticsEngin<wbr>e,<br>
<br>
Modified: cfe/trunk/unittests/Basic/Diag<wbr>nosticTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Basic/DiagnosticTest.cpp?rev=301992&r1=301991&r2=301992&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/unittests/Basi<wbr>c/DiagnosticTest.cpp?rev=30199<wbr>2&r1=301991&r2=301992&view=dif<wbr>f</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/unittests/Basic/Diag<wbr>nosticTest.cpp (original)<br>
+++ cfe/trunk/unittests/Basic/Diag<wbr>nosticTest.cpp Tue May  2 19:28:49 2017<br>
@@ -46,27 +46,30 @@ TEST(DiagnosticTest, suppressAndTrap) {<br>
   EXPECT_FALSE(Diags.hasUnrecov<wbr>erableErrorOccurred());<br>
 }<br>
<br>
-// Check that FatalsAsErrors works as intended<br>
-TEST(DiagnosticTest, fatalsAsErrors) {<br>
-  DiagnosticsEngine Diags(new DiagnosticIDs(),<br>
-                          new DiagnosticOptions,<br>
-                          new IgnoringDiagConsumer());<br>
-  Diags.setFatalsAsError(true);<br>
-<br>
-  // Diag that would set UncompilableErrorOccurred and ErrorOccurred.<br>
-  Diags.Report(diag::err_target_<wbr>unknown_triple) << "unknown";<br>
-<br>
-  // Diag that would set UnrecoverableErrorOccurred and ErrorOccurred.<br>
-  Diags.Report(diag::err_cannot_<wbr>open_file) << "file" << "error";<br>
-<br>
-  // Diag that would set FatalErrorOccurred<br>
-  // (via non-note following a fatal error).<br>
-  Diags.Report(diag::warn_mt_mes<wbr>sage) << "warning";<br>
-<br>
-  EXPECT_TRUE(Diags.hasErrorOccu<wbr>rred());<br>
-  EXPECT_FALSE(Diags.hasFatalErr<wbr>orOccurred());<br>
-  EXPECT_TRUE(Diags.hasUncompila<wbr>bleErrorOccurred());<br>
-  EXPECT_TRUE(Diags.hasUnrecover<wbr>ableErrorOccurred());<br>
+// Check that SuppressAfterFatalError works as intended<br>
+TEST(DiagnosticTest, suppressAfterFatalError) {<br>
+  for (unsigned Suppress = 0; Suppress != 2; ++Suppress) {<br>
+    DiagnosticsEngine Diags(new DiagnosticIDs(),<br>
+                            new DiagnosticOptions,<br>
+                            new IgnoringDiagConsumer());<br>
+    Diags.setSuppressAfterFatalErr<wbr>or(Suppress);<br>
+<br>
+    // Diag that would set UnrecoverableErrorOccurred and ErrorOccurred.<br>
+    Diags.Report(diag::err_cannot_<wbr>open_file) << "file" << "error";<br>
+<br>
+    // Diag that would set FatalErrorOccurred<br>
+    // (via non-note following a fatal error).<br>
+    Diags.Report(diag::warn_mt_mes<wbr>sage) << "warning";<br>
+<br>
+    EXPECT_TRUE(Diags.hasErrorOccu<wbr>rred());<br>
+    EXPECT_TRUE(Diags.hasFatalErro<wbr>rOccurred());<br>
+    EXPECT_TRUE(Diags.hasUncompila<wbr>bleErrorOccurred());<br>
+    EXPECT_TRUE(Diags.hasUnrecover<wbr>ableErrorOccurred());<br>
+<br>
+    // The warning should be emitted and counted only if we're not suppressing<br>
+    // after fatal errors.<br>
+    EXPECT_EQ(Diags.getNumWarnings<wbr>(), Suppress ? 0u : 1u);<br>
+  }<br>
 }<br>
<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>