[clang] 9fe5aa3 - [clang][Sema] Skip the RequiresExprBodyDecls for lambda dependencies (#83997)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 6 17:49:06 PST 2024
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.
More information about the cfe-commits
mailing list