diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -169,6 +169,9 @@ Also clang no longer emits false positive warnings about the output length of ``%g`` format specifier and about ``%o, %x, %X`` with ``#`` flag. - Clang now emits ``-Wcast-qual`` for functional-style cast expressions. +- Clang no longer emits irrelevant notes about unsatisfied constraint expressions + on the left-hand side of ``||`` when the right-hand side constraint is satisfied. + (`#54678: `_). Bug Fixes in This Version ------------------------- diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -185,6 +185,7 @@ ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); if (LogicalBinOp BO = ConstraintExpr) { + auto EffectiveDetailEnd = Satisfaction.Details.end(); ExprResult LHSRes = calculateConstraintSatisfaction( S, BO.getLHS(), Satisfaction, Evaluator); @@ -218,6 +219,19 @@ if (RHSRes.isInvalid()) return ExprError(); + bool IsRHSSatisfied = Satisfaction.IsSatisfied; + // Current implementation adds diagnostic information about the falsity + // of each false atomic constraint expression when it evaluates them. + // When the evaluation results to `false || true`, the information + // generated during the evaluation of left-hand side is meaningless + // because the whole expression evaluates to true. + // The following code removes the irrelevant diagnostic information. + // FIXME: We should probably delay the addition of diagnostic information + // until we know the entire expression is false. + if (BO.isOr() && IsRHSSatisfied) + Satisfaction.Details.erase(EffectiveDetailEnd, + Satisfaction.Details.end()); + return BO.recreateBinOp(S, LHSRes, RHSRes); } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -994,3 +994,40 @@ } } + +namespace GH54678 { +template +concept True = true; + +template +concept False = false; // expected-note 9 {{'false' evaluated to false}} + +template +concept Irrelevant = false; + +template +concept ErrorRequires = requires(ErrorRequires auto x) { x; }; // expected-error {{unknown type name 'ErrorRequires'}} + +template void aaa(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires (False || False) || False {} // expected-note 3 {{'int' does not satisfy 'False'}} +template void bbb(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires (False || False) && True {} // expected-note 2 {{'long' does not satisfy 'False'}} +template void ccc(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires (True || Irrelevant) && False {} // expected-note {{'unsigned long' does not satisfy 'False'}} +template void ddd(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires (Irrelevant || True) && False {} // expected-note {{'int' does not satisfy 'False'}} +template void eee(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires (Irrelevant || Irrelevant || True) && False {} // expected-note {{'long' does not satisfy 'False'}} + +template void fff(T t) // expected-note {{candidate template ignored: constraints not satisfied}} +requires((ErrorRequires || False || True) && False) {} // expected-note {{'unsigned long' does not satisfy 'False'}} + +void test() { + aaa(42); // expected-error {{no matching function}} + bbb(42L); // expected-error{{no matching function}} + ccc(42UL); // expected-error {{no matching function}} + ddd(42); // expected-error {{no matching function}} + eee(42L); // expected-error {{no matching function}} + fff(42UL); // expected-error {{no matching function}} +} +}