Skip to content

[Clang] Fix crash with source_location in lambda declarators. #107411

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
Sep 5, 2024
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
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ Bug Fixes to C++ Support
- Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048)
- Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588)

- Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/DeclCXX.h"
Expand Down Expand Up @@ -2287,6 +2288,15 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx,
Context = getParentContext();
}

// If we are currently parsing a lambda declarator, we might not have a fully
// formed call operator declaration yet, and we could not form a function name
// for it. Because we do not have access to Sema/function scopes here, we
// detect this case by relying on the fact such method doesn't yet have a
// type.
if (const auto *D = dyn_cast<CXXMethodDecl>(Context);
D && D->getFunctionTypeLoc().isNull() && isLambdaCallOperator(D))
Context = D->getParent()->getParent();
Copy link
Collaborator

Choose a reason for hiding this comment

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

So the first getParent should get the lambda object, correct?

Could this cause issues where the parent of the lambda is a TU? Can we have a test for that? Also, there are some goofinesses around variable templates and requires in a lambda, can we have a test for that?

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to make sure we're in an unevaluated context here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ideally yes, I'd assert on it... but we do not have access to that information in constant evaluation


PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc(
Ctx.getSourceManager().getExpansionRange(Loc).getEnd());

Expand Down
23 changes: 23 additions & 0 deletions clang/test/SemaCXX/source_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,3 +989,26 @@ void Test() {
}

#endif


namespace GH67134 {
template <int loc = std::source_location::current().line()>
constexpr auto f(std::source_location loc2 = std::source_location::current()) { return loc; }

int g = []() -> decltype(f()) { return 0; }();

int call() {
#if __cplusplus >= 202002L
return []<decltype(f()) = 0>() -> decltype(f()) { return 0; }();
#endif
return []() -> decltype(f()) { return 0; }();
}

#if __cplusplus >= 202002L
template<typename T>
int Var = requires { []() -> decltype(f()){}; };
int h = Var<int>;
#endif


}
Loading