[clang] [clang][Sema] Skip the RequiresExprBodyDecls for lambda dependencies (PR #83997)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 5 22:03:16 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Younan Zhang (zyn0217)
<details>
<summary>Changes</summary>
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, https://github.com/llvm/llvm-project/issues/82849 and a case demonstrated by https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972.
---
Full diff: https://github.com/llvm/llvm-project/pull/83997.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/lib/Sema/TreeTransform.h (+21-2)
- (modified) clang/test/SemaTemplate/concepts-lambda.cpp (+52)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5e0352a7eaf6cd..9c64cd2b5f6a10 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -311,6 +311,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).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7389a48fe56fcc..84348e13567e71 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 here in substitution for Widget<F>, 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() ||
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..ef04cad4eef98b 100644
--- a/clang/test/SemaTemplate/concepts-lambda.cpp
+++ b/clang/test/SemaTemplate/concepts-lambda.cpp
@@ -90,6 +90,58 @@ 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) {
+ [](T) {}(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.
``````````
</details>
https://github.com/llvm/llvm-project/pull/83997
More information about the cfe-commits
mailing list