From d219c63b16851ba264b6495e3f63016d1c8b2aac Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Thu, 5 Sep 2024 20:45:31 +0200 Subject: [PATCH] [Clang] Fix crash with `source_location` in lambda declarators. (#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 #67134 --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/Expr.cpp | 10 ++++++++++ clang/test/SemaCXX/source_location.cpp | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ebd0b7371e1bed..a2e91fd648cce2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 96c6276f3f34c1..27930db019a172 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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" @@ -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(Context); + D && D->getFunctionTypeLoc().isNull() && isLambdaCallOperator(D)) + Context = D->getParent()->getParent(); + PresumedLoc PLoc = Ctx.getSourceManager().getPresumedLoc( Ctx.getSourceManager().getExpansionRange(Loc).getEnd()); diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp index 34177bfe287fc3..8b3a5d8dd3327d 100644 --- a/clang/test/SemaCXX/source_location.cpp +++ b/clang/test/SemaCXX/source_location.cpp @@ -989,3 +989,26 @@ void Test() { } #endif + + +namespace GH67134 { +template +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()) { return 0; }(); +#endif + return []() -> decltype(f()) { return 0; }(); +} + +#if __cplusplus >= 202002L +template +int Var = requires { []() -> decltype(f()){}; }; +int h = Var; +#endif + + +}