Skip to content

[Clang] incorrect assertion when checking template template parameter of a lambda #138121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@ Bug Fixes to C++ Support
- Clang now issues an error when placement new is used to modify a const-qualified variable
in a ``constexpr`` function. (#GH131432)
- Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806)
- Fix a crash when checking the template template parameters of a dependent lambda appearing in an alias declaration.
(#GH136432), (#GH137014), (#GH138018)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1696,7 +1696,11 @@ static NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) {
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);

DeclContext::lookup_result Calls = RD.lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");

// This can happen while building the lambda.
if (Calls.empty())
return nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'm REALLY concerned about this. I don't think it is wrong, but just that we need to make sure we handle this value correctly. At least getLambdaStaticInvoker doesn't handle the nullptr correctly (though I guess the other two uses DO, so thats fine).

I wouldn't mind a bit of an audit to make sure that uses of getLambdaStaticInvoker (and perhaps the others, but as they already acknowledged they could return null, i'm mildly less concerned) do a reasonable thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an assert, which hinges on the fact that we don't look at the static invoker in cases where the lambda is incomplete.
I agree that having these various states in lambdas is a bit unfortunate, but it is a consequence of P2036.
If you have a better solution, I'm all ears!


assert(allLookupResultsAreTheSame(Calls) &&
"More than one lambda call operator!");

Expand Down Expand Up @@ -1750,6 +1754,7 @@ CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator() const {

CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
CXXMethodDecl *CallOp = getLambdaCallOperator();
assert(CallOp && "null call operator");
CallingConv CC = CallOp->getType()->castAs<FunctionType>()->getCallConv();
return getLambdaStaticInvoker(CC);
}
Expand Down
16 changes: 16 additions & 0 deletions clang/test/SemaCXX/lambda-unevaluated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,19 @@ void func() {
}

} // namespace GH88081

namespace GH138018 {

template <typename T> struct vec {};

auto structure_to_typelist(auto) {
return []<template <typename> typename T>(T<int>) {
return 0;
}(vec<int>{});
}

template <typename T> using helper = decltype(structure_to_typelist(T{}));
static_assert(__is_same_as(int, helper<int>));


} // namespace GH138018