From 69414d7352b170f6fcff22c6f5dfa91cc76b0b58 Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Tue, 5 Mar 2024 19:56:59 +0800 Subject: [PATCH 1/3] gh56556 --- clang/lib/Sema/TreeTransform.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7389a48fe56fc..c96ffcb97a759 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13649,10 +13649,12 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { // use evaluation contexts to distinguish the function parameter case. CXXRecordDecl::LambdaDependencyKind DependencyKind = CXXRecordDecl::LDK_Unknown; + DeclContext *DC = getSema().CurContext; + if (DC->getDeclKind() == Decl::Kind::RequiresExprBody) + DC = DC->getParent(); if ((getSema().isUnevaluatedContext() || getSema().isConstantEvaluatedContext()) && - (getSema().CurContext->isFileContext() || - !getSema().CurContext->getParent()->isDependentContext())) + (DC->isFileContext() || !DC->getParent()->isDependentContext())) DependencyKind = CXXRecordDecl::LDK_NeverDependent; CXXRecordDecl *OldClass = E->getLambdaClass(); From b905083e5d5186ad08ac3d553be3e8f47dabc1b6 Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Wed, 6 Mar 2024 13:46:43 +0800 Subject: [PATCH 2/3] Tests & release notes --- clang/docs/ReleaseNotes.rst | 2 + clang/lib/Sema/TreeTransform.h | 17 +++++++ clang/test/SemaTemplate/concepts-lambda.cpp | 52 +++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d4e6bcf661da1..141099fb68a20 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -302,6 +302,8 @@ Bug Fixes to C++ Support our attention by an attempt to fix in (#GH77703). Fixes (#GH83385). - Fix evaluation of some immediate calls in default arguments. Fixes (#GH80630) +- Fixed an issue where the ``RequiresExprBody`` was involved in the lambda dependency + calculation. (#GH56556), (#GH82849). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c96ffcb97a759..84348e13567e7 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13650,6 +13650,23 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { CXXRecordDecl::LambdaDependencyKind DependencyKind = CXXRecordDecl::LDK_Unknown; DeclContext *DC = getSema().CurContext; + // A RequiresExprBodyDecl is not interesting for dependencies. + // For the following case, + // + // template + // concept C = requires { [] {}; }; + // + // template + // struct Widget; + // + // template + // struct Widget {}; + // + // While we are here in substitution for Widget, the parent of DC would be + // the template specialization itself. Thus, the lambda expression + // will be deemed as dependent even if we have non-dependent template + // arguments. + // (A ClassTemplateSpecializationDecl is always a dependent context.) if (DC->getDeclKind() == Decl::Kind::RequiresExprBody) DC = DC->getParent(); if ((getSema().isUnevaluatedContext() || diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 0b7580f91043c..ef04cad4eef98 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -90,6 +90,58 @@ struct Foo { static_assert(ConstructibleWithN); +namespace GH56556 { + +template +inline constexpr It declare (); + +template typename Template> +concept D = requires { + { [] (Template &) {}(declare()) }; +}; + +template +struct B {}; + +template +struct Adapter; + +template T> +struct Adapter {}; + +template struct Adapter>; + +} // namespace GH56556 + +namespace GH82849 { + +template +concept C = requires(T t) { + [](T) {}(t); +}; + +template +struct Widget; + +template +struct Widget { + static F create(F from) { + return from; + } +}; + +template +bool foo() { + return C; +} + +void bar() { + // https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972 + Widget::create(0); +} + +} // namespace GH82849 + } // GH60642 reported an assert being hit, make sure we don't assert. From 6b36f74b6aede38766674c99a803c86becacd01d Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Wed, 6 Mar 2024 18:56:53 +0800 Subject: [PATCH 3/3] Address Corentin's comments --- clang/lib/Sema/TreeTransform.h | 6 +++--- clang/test/SemaTemplate/concepts-lambda.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 84348e13567e7..409aee73d960e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13662,12 +13662,12 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { // template // struct Widget {}; // - // While we are here in substitution for Widget, the parent of DC would be + // While we are substituting Widget, the parent of DC would be // the template specialization itself. Thus, the lambda expression - // will be deemed as dependent even if we have non-dependent template + // will be deemed as dependent even if there are no dependent template // arguments. // (A ClassTemplateSpecializationDecl is always a dependent context.) - if (DC->getDeclKind() == Decl::Kind::RequiresExprBody) + while (DC->getDeclKind() == Decl::Kind::RequiresExprBody) DC = DC->getParent(); if ((getSema().isUnevaluatedContext() || getSema().isConstantEvaluatedContext()) && diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index ef04cad4eef98..fac790d09f9cf 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -117,7 +117,13 @@ namespace GH82849 { template concept C = requires(T t) { - [](T) {}(t); + requires requires (T u) { + [](V) { + return requires(V v) { + [](V w) {}(v); + }; + }(t); + }; }; template