Author: Younan Zhang Date: 2024-03-07T09:49:02+08:00 New Revision: 9fe5aa31eccff49632e40bcdad6e64fc00190889
URL: https://github.com/llvm/llvm-project/commit/9fe5aa31eccff49632e40bcdad6e64fc00190889 DIFF: https://github.com/llvm/llvm-project/commit/9fe5aa31eccff49632e40bcdad6e64fc00190889.diff LOG: [clang][Sema] Skip the RequiresExprBodyDecls for lambda dependencies (#83997) The dependency of a lambda inside of a `RequiresExprBodyDecl` was previously affected by its parent, e.g., `ClassTemplateSpecializationDecl`. This made the lambda always dependent regardless of the template arguments we had, which caused some crashes on the constraint evaluation later. This fixes https://github.com/llvm/llvm-project/issues/56556, fixes https://github.com/llvm/llvm-project/issues/82849 and a case demonstrated by https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/TreeTransform.h clang/test/SemaTemplate/concepts-lambda.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 942820a5268576..8300a8484585ae 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 7389a48fe56fcc..409aee73d960eb 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13649,10 +13649,29 @@ TreeTransform<Derived>::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 <typename> + // concept C = requires { [] {}; }; + // + // template <class F> + // struct Widget; + // + // template <C F> + // struct Widget<F> {}; + // + // While we are substituting Widget<F>, 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 0b7580f91043c7..fac790d09f9cf2 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -90,6 +90,64 @@ struct Foo { static_assert(ConstructibleWithN<Foo>); +namespace GH56556 { + +template <typename It> +inline constexpr It declare (); + +template <typename It, template <typename> typename Template> +concept D = requires { + { [] <typename T1> (Template<T1> &) {}(declare<It &>()) }; +}; + +template <typename T> +struct B {}; + +template <typename T> +struct Adapter; + +template <D<B> T> +struct Adapter<T> {}; + +template struct Adapter<B<int>>; + +} // namespace GH56556 + +namespace GH82849 { + +template <class T> +concept C = requires(T t) { + requires requires (T u) { + []<class V>(V) { + return requires(V v) { + [](V w) {}(v); + }; + }(t); + }; +}; + +template <class From> +struct Widget; + +template <C F> +struct Widget<F> { + static F create(F from) { + return from; + } +}; + +template <class> +bool foo() { + return C<int>; +} + +void bar() { + // https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972 + Widget<char>::create(0); +} + +} // namespace GH82849 + } // GH60642 reported an assert being hit, make sure we don't assert. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits