Make DiagnosticErrorTrap keep a count of the errors that occurred so multiple
DiagnosticErrorTraps can be composed (e.g. a trap inside another trap).

Fixes http://llvm.org/PR10462 & rdar://9852007.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136447 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index b7a1f3a..8cc1771 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -255,10 +255,10 @@
   /// \brief Indicates that an unrecoverable error has occurred.
   bool UnrecoverableErrorOccurred;
   
-  /// \brief Toggles for DiagnosticErrorTrap to check whether an error occurred
+  /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
   /// during a parsing section, e.g. during parsing a function.
-  bool TrapErrorOccurred;
-  bool TrapUnrecoverableErrorOccurred;
+  unsigned TrapNumErrorsOccurred;
+  unsigned TrapNumUnrecoverableErrorsOccurred;
 
   /// LastDiagLevel - This is the level of the last diagnostic emitted.  This is
   /// used to emit continuation diagnostics with the same level as the
@@ -639,6 +639,8 @@
 /// queried.
 class DiagnosticErrorTrap {
   Diagnostic &Diag;
+  unsigned NumErrors;
+  unsigned NumUnrecoverableErrors;
 
 public:
   explicit DiagnosticErrorTrap(Diagnostic &Diag)
@@ -647,19 +649,19 @@
   /// \brief Determine whether any errors have occurred since this
   /// object instance was created.
   bool hasErrorOccurred() const {
-    return Diag.TrapErrorOccurred;
+    return Diag.TrapNumErrorsOccurred > NumErrors;
   }
 
   /// \brief Determine whether any unrecoverable errors have occurred since this
   /// object instance was created.
   bool hasUnrecoverableErrorOccurred() const {
-    return Diag.TrapUnrecoverableErrorOccurred;
+    return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
   }
 
   // Set to initial state of "no errors occurred".
   void reset() {
-    Diag.TrapErrorOccurred = false;
-    Diag.TrapUnrecoverableErrorOccurred = false;
+    NumErrors = Diag.TrapNumErrorsOccurred;
+    NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
   }
 };
 
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 38dadce..b82b062 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -92,6 +92,8 @@
   NumWarnings = 0;
   NumErrors = 0;
   NumErrorsSuppressed = 0;
+  TrapNumErrorsOccurred = 0;
+  TrapNumUnrecoverableErrorsOccurred = 0;
   
   CurDiagID = ~0U;
   // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes
diff --git a/lib/Basic/DiagnosticIDs.cpp b/lib/Basic/DiagnosticIDs.cpp
index fbeec27..35b9605 100644
--- a/lib/Basic/DiagnosticIDs.cpp
+++ b/lib/Basic/DiagnosticIDs.cpp
@@ -665,6 +665,13 @@
     Diag.LastDiagLevel = DiagLevel;
   }
 
+  // Update counts for DiagnosticErrorTrap even if a fatal error occurred.
+  if (DiagLevel >= DiagnosticIDs::Error) {
+    ++Diag.TrapNumErrorsOccurred;
+    if (isUnrecoverable(DiagID))
+      ++Diag.TrapNumUnrecoverableErrorsOccurred;
+  }
+
   // If a fatal error has already been emitted, silence all subsequent
   // diagnostics.
   if (Diag.FatalErrorOccurred) {
@@ -685,11 +692,8 @@
     return false;
 
   if (DiagLevel >= DiagnosticIDs::Error) {
-    Diag.TrapErrorOccurred = true;
-    if (isUnrecoverable(DiagID)) {
-      Diag.TrapUnrecoverableErrorOccurred = true;
+    if (isUnrecoverable(DiagID))
       Diag.UnrecoverableErrorOccurred = true;
-    }
     
     if (Diag.Client->IncludeInDiagnosticCounts()) {
       Diag.ErrorOccurred = true;
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index 3a90cc0..d656a07 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -171,3 +171,24 @@
     }
   }
 }
+
+// http://llvm.org/PR10462
+namespace PR10462 {
+enum MyEnum {
+  something_valid,
+  something_invalid
+};
+
+bool recurse() {
+  MyEnum K;
+  switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}}
+    case something_valid:
+    case what_am_i_thinking: // expected-error {{use of undeclared identifier}}
+      int *X = 0;
+      if (recurse()) {
+      }
+
+      break;
+  }
+}
+}