diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 942820a526857..8300a8484585a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -319,6 +319,8 @@ Bug Fixes to C++ Support Fixes (#GH80630) - Fix a crash when an explicit template argument list is used with a name for which lookup finds a non-template function and a dependent using declarator. +- Fixed an issue where the ``RequiresExprBody`` was involved in the lambda dependency + calculation. (#GH56556), (#GH82849). - Fix a bug where overload resolution falsely reported an ambiguity when it was comparing a member-function against a non member function or a member-function with an explicit object parameter against a member function with no explicit object parameter diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7389a48fe56fc..409aee73d960e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13649,10 +13649,29 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { // use evaluation contexts to distinguish the function parameter case. 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 substituting Widget, the parent of DC would be + // the template specialization itself. Thus, the lambda expression + // will be deemed as dependent even if there are no dependent template + // arguments. + // (A ClassTemplateSpecializationDecl is always a dependent context.) + while (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(); diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 0b7580f91043c..fac790d09f9cf 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -90,6 +90,64 @@ 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) { + requires requires (T u) { + [](V) { + return requires(V v) { + [](V w) {}(v); + }; + }(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.