Skip to content

Commit

Permalink
[Clang] Fix crash with source_location in lambda declarators. (llvm…
Browse files Browse the repository at this point in the history
…#107411)

Parsing lambdas require pushing a declaration context for the lambda, so
that parameters can be attached to it, before its trailing type is
parsed. DAt that point, partially-parsed lambda don't have a name that
can be computed for then.
This would cause source_location::current() to crash when use in the
decltype of a lambda().
We work around this by producing a source_location for an enclosing
scope in that scenario.

Fixes llvm#67134
  • Loading branch information
cor3ntin authored Sep 5, 2024
1 parent 92e75c0 commit d219c63
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,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();

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


}

0 comments on commit d219c63

Please sign in to comment.