summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-05-04 13:56:51 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-05-04 13:56:51 +0000
commitce4518f21d55eee34d891db39baaeb471ee79397 (patch)
tree2ecb31b59758120d7cf3edf2fff626e304c0a9be
parent66af84bfc008ca9fce242310724a2e8313386049 (diff)
downloadbcm5719-llvm-ce4518f21d55eee34d891db39baaeb471ee79397.tar.gz
bcm5719-llvm-ce4518f21d55eee34d891db39baaeb471ee79397.zip
DiagnosticsEngine should clear DelayedDiagID before reporting the
delayed diagnostic This fix avoids an infinite recursion that was uncovered in one of our internal tests by r301992. The testcase is the most reduced version of that auto-generated test. This is an improved version of the reverted commit r302037. The previous fix actually managed to expose another subtle bug whereby `fatal_too_many_errors` error was reported twice, with the second report setting the `FatalErrorOccurred` flag. That prevented the notes that followed the diagnostic the caused `fatal_too_many_errors` to be emitted. This commit ensures that notes that follow `fatal_too_many_errors` but that belong to the diagnostic that caused `fatal_too_many_errors` won't be emitted by setting the `FatalErrorOccurred` when emitting `fatal_too_many_errors`. rdar://31962618 llvm-svn: 302151
-rw-r--r--clang/lib/Basic/Diagnostic.cpp8
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp4
-rw-r--r--clang/test/Index/KeepGoingWithLotsOfErrors.mm29
3 files changed, 36 insertions, 5 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 6bdef78c074..c355445dc1e 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -146,10 +146,9 @@ void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
}
void DiagnosticsEngine::ReportDelayed() {
- Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2;
+ unsigned ID = DelayedDiagID;
DelayedDiagID = 0;
- DelayedDiagArg1.clear();
- DelayedDiagArg2.clear();
+ Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
}
void DiagnosticsEngine::DiagStateMap::appendFirst(
@@ -420,11 +419,10 @@ bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
}
// Clear out the current diagnostic object.
- unsigned DiagID = CurDiagID;
Clear();
// If there was a delayed diagnostic, emit it now.
- if (!Force && DelayedDiagID && DelayedDiagID != DiagID)
+ if (!Force && DelayedDiagID)
ReportDelayed();
return Emitted;
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 2852b40026c..ce493c1e5ca 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -666,6 +666,10 @@ bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
}
}
+ // Make sure we set FatalErrorOccurred to ensure that the notes from the
+ // diagnostic that caused `fatal_too_many_errors` won't be emitted.
+ if (Diag.CurDiagID == diag::fatal_too_many_errors)
+ Diag.FatalErrorOccurred = true;
// Finally, report it.
EmitDiag(Diag, DiagLevel);
return true;
diff --git a/clang/test/Index/KeepGoingWithLotsOfErrors.mm b/clang/test/Index/KeepGoingWithLotsOfErrors.mm
new file mode 100644
index 00000000000..078ea6e2ea1
--- /dev/null
+++ b/clang/test/Index/KeepGoingWithLotsOfErrors.mm
@@ -0,0 +1,29 @@
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -code-completion-at=%s:25:1 %s
+// Shouldn't crash!
+// This is the minimized test that triggered an infinite recursion:
+
++(BOOL) onEntity {
+}
+
+-(const Object &) a_200 {
+}
+
+-(int) struct {
+}
+
+-(int) bar {
+}
+
+-(int) part {
+}
+
++(some_type_t) piece {
+}
+
++(void) z_Z_42 {
+ ([self onEntity: [] { 42];
+ } class: ^ { }
+];
+ [super];
+ BOOL struct;
+}
OpenPOWER on IntegriCloud