From af9b88da83a7f2954a3a8ddc5f4796f2017ceaec Mon Sep 17 00:00:00 2001 From: ebinjose02 Date: Fri, 28 Nov 2025 06:46:40 +0000 Subject: [PATCH 1/3] Fixes #165386 Nested requirements in requires-expressions must be constant expressions. Previously, using an invented parameter in a nested requirement caused a crash. Now emit a clear diagnostic and recover. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaExprCXX.cpp | 8 ++++++++ clang/test/SemaCXX/requires-nested-non-constant.cpp | 11 +++++++++++ 3 files changed, 21 insertions(+) create mode 100644 clang/test/SemaCXX/requires-nested-non-constant.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4a145fd71eedd..8083fde95f2ab 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3190,6 +3190,8 @@ def note_ambiguous_atomic_constraints_similar_expression : Note< def err_unsupported_placeholder_constraint : Error< "constrained placeholder types other than simple 'auto' on non-type template " "parameters not supported yet">; +def err_nested_requirement_not_constant : Error< + "nested requirement is not a constant expression">; def err_template_different_requires_clause : Error< "requires clause differs in template redeclaration">; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d6f70e728be29..490ce09e75208 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7922,6 +7922,14 @@ concepts::Requirement *Sema::ActOnNestedRequirement(Expr *Constraint) { concepts::NestedRequirement * Sema::BuildNestedRequirement(Expr *Constraint) { + if (!Constraint->isValueDependent() && + !Constraint->isInstantiationDependent()) { + Expr::EvalResult Result; + if (!Constraint->EvaluateAsConstantExpr(Result, Context)) { + Diag(Constraint->getExprLoc(), diag::err_nested_requirement_not_constant); + return nullptr; + } + } ConstraintSatisfaction Satisfaction; if (!Constraint->isInstantiationDependent() && CheckConstraintSatisfaction(nullptr, AssociatedConstraint(Constraint), diff --git a/clang/test/SemaCXX/requires-nested-non-constant.cpp b/clang/test/SemaCXX/requires-nested-non-constant.cpp new file mode 100644 index 0000000000000..acb516392e616 --- /dev/null +++ b/clang/test/SemaCXX/requires-nested-non-constant.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s + +template class A { + void f() { + auto result = []() constexpr { + return requires (int x) { + requires (x > 0) && (x < 10); // expected-error {{nested requirement is not a constant expression}} + }; + }(); + } +}; From 2de5ef4d02f9d0aed61cebacb14517381aeeb9e7 Mon Sep 17 00:00:00 2001 From: ebinjose02 Date: Tue, 2 Dec 2025 09:22:10 +0000 Subject: [PATCH 2/3] Modified implementation to use instantationscope --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 -- clang/lib/Sema/SemaExprCXX.cpp | 10 ++-------- clang/test/SemaCXX/requires-nested-non-constant.cpp | 6 ++++-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8083fde95f2ab..4a145fd71eedd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3190,8 +3190,6 @@ def note_ambiguous_atomic_constraints_similar_expression : Note< def err_unsupported_placeholder_constraint : Error< "constrained placeholder types other than simple 'auto' on non-type template " "parameters not supported yet">; -def err_nested_requirement_not_constant : Error< - "nested requirement is not a constant expression">; def err_template_different_requires_clause : Error< "requires clause differs in template redeclaration">; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 490ce09e75208..f915caffa3487 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7922,16 +7922,10 @@ concepts::Requirement *Sema::ActOnNestedRequirement(Expr *Constraint) { concepts::NestedRequirement * Sema::BuildNestedRequirement(Expr *Constraint) { - if (!Constraint->isValueDependent() && - !Constraint->isInstantiationDependent()) { - Expr::EvalResult Result; - if (!Constraint->EvaluateAsConstantExpr(Result, Context)) { - Diag(Constraint->getExprLoc(), diag::err_nested_requirement_not_constant); - return nullptr; - } - } ConstraintSatisfaction Satisfaction; + LocalInstantiationScope Scope(*this); if (!Constraint->isInstantiationDependent() && + !Constraint->isValueDependent() && CheckConstraintSatisfaction(nullptr, AssociatedConstraint(Constraint), /*TemplateArgs=*/{}, Constraint->getSourceRange(), Satisfaction)) diff --git a/clang/test/SemaCXX/requires-nested-non-constant.cpp b/clang/test/SemaCXX/requires-nested-non-constant.cpp index acb516392e616..b5b8bdbf5a9dc 100644 --- a/clang/test/SemaCXX/requires-nested-non-constant.cpp +++ b/clang/test/SemaCXX/requires-nested-non-constant.cpp @@ -3,8 +3,10 @@ template class A { void f() { auto result = []() constexpr { - return requires (int x) { - requires (x > 0) && (x < 10); // expected-error {{nested requirement is not a constant expression}} + return requires (int x) { // expected-note {{declared here}} + requires (x > 0) && (x < 10); // expected-error {{substitution into constraint expression resulted in a non-constant expression}} \ + // expected-note {{while checking the satisfaction of nested requirement requested here}} \ + // expected-note {{function parameter 'x' with unknown value cannot be used in a constant expression}} }; }(); } From 113a1afe2d9fb3d1652dbd1bc49e71d678ea94b4 Mon Sep 17 00:00:00 2001 From: ebinjose02 Date: Wed, 3 Dec 2025 04:50:32 +0000 Subject: [PATCH 3/3] Added documentation in ReleaseNotes.rst --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c6a79ed71ca2f..4404ddc9f7e45 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Crash and bug fixes ``[[assume(expr)]]`` attribute was enclosed in parentheses. (#GH151529) - Fixed a crash when parsing ``#embed`` parameters with unmatched closing brackets. (#GH152829) - Fixed a crash when compiling ``__real__`` or ``__imag__`` unary operator on scalar value with type promotion. (#GH160583) +- Fixed a crash when evaluating nested requirements in requires-expressions that + reference invented parameters. (#GH166325) Improvements ^^^^^^^^^^^^