Skip to content

Commit

Permalink
[clang][Sema] Skip the RequiresExprBodyDecls for lambda dependencies (#…
Browse files Browse the repository at this point in the history
…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 #56556, fixes
#82849 and a case
demonstrated by
#49570 (comment).
  • Loading branch information
zyn0217 committed Mar 7, 2024
1 parent 84842f4 commit 9fe5aa3
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 21 additions & 2 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
58 changes: 58 additions & 0 deletions clang/test/SemaTemplate/concepts-lambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 9fe5aa3

Please sign in to comment.