From: Richard Smith Date: Thu, 30 Nov 2017 08:18:21 +0000 (+0000) Subject: Preserve the "last diagnostic was suppressed" flag across SFINAE checks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7af18205334679598a4e9792cbeabd055d7181a;p=clang Preserve the "last diagnostic was suppressed" flag across SFINAE checks. Sometimes we check the validity of some construct between producing a diagnostic and producing its notes. Ideally, we wouldn't do that, but in practice running code that "cannot possibly produce a diagnostic" in such a situation should be safe, and reasonable factoring of some code requires it with our current diagnostics infrastruture. If this does happen, a diagnostic that's suppressed due to SFINAE should not cause notes connected to the prior diagnostic to be suppressed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319408 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 22cded21c1..a7458d4561 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -575,13 +575,15 @@ public: OverloadsShown getShowOverloads() const { return ShowOverloads; } /// \brief Pretend that the last diagnostic issued was ignored, so any - /// subsequent notes will be suppressed. + /// subsequent notes will be suppressed, or restore a prior ignoring + /// state after ignoring some diagnostics and their notes, possibly in + /// the middle of another diagnostic. /// /// This can be used by clients who suppress diagnostics themselves. - void setLastDiagnosticIgnored() { + void setLastDiagnosticIgnored(bool Ignored = true) { if (LastDiagLevel == DiagnosticIDs::Fatal) FatalErrorOccurred = true; - LastDiagLevel = DiagnosticIDs::Ignored; + LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; } /// \brief Determine whether the previous diagnostic was ignored. This can diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 376df4ad66..4ca56ab101 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7428,13 +7428,16 @@ public: unsigned PrevSFINAEErrors; bool PrevInNonInstantiationSFINAEContext; bool PrevAccessCheckingSFINAE; + bool PrevLastDiagnosticIgnored; public: explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), PrevInNonInstantiationSFINAEContext( SemaRef.InNonInstantiationSFINAEContext), - PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE) + PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE), + PrevLastDiagnosticIgnored( + SemaRef.getDiagnostics().isLastDiagnosticIgnored()) { if (!SemaRef.isSFINAEContext()) SemaRef.InNonInstantiationSFINAEContext = true; @@ -7446,6 +7449,8 @@ public: SemaRef.InNonInstantiationSFINAEContext = PrevInNonInstantiationSFINAEContext; SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; + SemaRef.getDiagnostics().setLastDiagnosticIgnored( + PrevLastDiagnosticIgnored); } /// \brief Determine whether any SFINAE errors have been trapped. diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index 2e6a261ad0..d27adc428d 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -22,6 +22,9 @@ namespace dr401 { // dr401: yes class B { protected: typedef int type; // expected-note {{protected}} +#if __cplusplus == 199711L + // expected-note@-2 {{protected}} +#endif }; class C { diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 0e3a9ee50b..0c4bba5027 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -658,3 +658,11 @@ namespace StringLiteralToCharAmbiguity { // expected-note@-5 {{candidate function}} #endif } + +namespace ProduceNotesAfterSFINAEFailure { + struct A { + template A(T); // expected-warning 0-1{{extension}} + }; + void f(void*, A); // expected-note {{candidate function not viable}} + void g() { f(1, 2); } // expected-error {{no matching function}} +}