Skip to content

Commit b2cd9db

Browse files
committed
[clang][Sema] Remove irrelevant diagnostics from constraint satisfaction failure
BEFORE this patch, when clang handles constraints like C1 || C2 where C1 evaluates to false and C2 evaluates to true, it emitted irrelevant diagnostics about the falsity of C1. This patch removes the irrelevant diagnostic information generated during the evaluation of C1 if C2 evaluates to true. Fixes llvm#54678 Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D157526
1 parent dd55ece commit b2cd9db

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ Improvements to Clang's diagnostics
169169
Also clang no longer emits false positive warnings about the output length of
170170
``%g`` format specifier and about ``%o, %x, %X`` with ``#`` flag.
171171
- Clang now emits ``-Wcast-qual`` for functional-style cast expressions.
172+
- Clang no longer emits irrelevant notes about unsatisfied constraint expressions
173+
on the left-hand side of ``||`` when the right-hand side constraint is satisfied.
174+
(`#54678: <https://github.com/llvm/llvm-project/issues/54678>`_).
172175

173176
Bug Fixes in This Version
174177
-------------------------

clang/lib/Sema/SemaConcept.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
185185
ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
186186

187187
if (LogicalBinOp BO = ConstraintExpr) {
188+
auto EffectiveDetailEnd = Satisfaction.Details.end();
188189
ExprResult LHSRes = calculateConstraintSatisfaction(
189190
S, BO.getLHS(), Satisfaction, Evaluator);
190191

@@ -218,6 +219,19 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
218219
if (RHSRes.isInvalid())
219220
return ExprError();
220221

222+
bool IsRHSSatisfied = Satisfaction.IsSatisfied;
223+
// Current implementation adds diagnostic information about the falsity
224+
// of each false atomic constraint expression when it evaluates them.
225+
// When the evaluation results to `false || true`, the information
226+
// generated during the evaluation of left-hand side is meaningless
227+
// because the whole expression evaluates to true.
228+
// The following code removes the irrelevant diagnostic information.
229+
// FIXME: We should probably delay the addition of diagnostic information
230+
// until we know the entire expression is false.
231+
if (BO.isOr() && IsRHSSatisfied)
232+
Satisfaction.Details.erase(EffectiveDetailEnd,
233+
Satisfaction.Details.end());
234+
221235
return BO.recreateBinOp(S, LHSRes, RHSRes);
222236
}
223237

clang/test/SemaTemplate/concepts.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,3 +994,40 @@ void test_params() {
994994
}
995995

996996
}
997+
998+
namespace GH54678 {
999+
template<class>
1000+
concept True = true;
1001+
1002+
template<class>
1003+
concept False = false; // expected-note 9 {{'false' evaluated to false}}
1004+
1005+
template<class>
1006+
concept Irrelevant = false;
1007+
1008+
template <typename T>
1009+
concept ErrorRequires = requires(ErrorRequires auto x) { x; }; // expected-error {{unknown type name 'ErrorRequires'}}
1010+
1011+
template<class T> void aaa(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1012+
requires (False<T> || False<T>) || False<T> {} // expected-note 3 {{'int' does not satisfy 'False'}}
1013+
template<class T> void bbb(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1014+
requires (False<T> || False<T>) && True<T> {} // expected-note 2 {{'long' does not satisfy 'False'}}
1015+
template<class T> void ccc(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1016+
requires (True<T> || Irrelevant<T>) && False<T> {} // expected-note {{'unsigned long' does not satisfy 'False'}}
1017+
template<class T> void ddd(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1018+
requires (Irrelevant<T> || True<T>) && False<T> {} // expected-note {{'int' does not satisfy 'False'}}
1019+
template<class T> void eee(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1020+
requires (Irrelevant<T> || Irrelevant<T> || True<T>) && False<T> {} // expected-note {{'long' does not satisfy 'False'}}
1021+
1022+
template<class T> void fff(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
1023+
requires((ErrorRequires<T> || False<T> || True<T>) && False<T>) {} // expected-note {{'unsigned long' does not satisfy 'False'}}
1024+
1025+
void test() {
1026+
aaa(42); // expected-error {{no matching function}}
1027+
bbb(42L); // expected-error{{no matching function}}
1028+
ccc(42UL); // expected-error {{no matching function}}
1029+
ddd(42); // expected-error {{no matching function}}
1030+
eee(42L); // expected-error {{no matching function}}
1031+
fff(42UL); // expected-error {{no matching function}}
1032+
}
1033+
}

0 commit comments

Comments
 (0)