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

Conversation

cor3ntin
Copy link
Contributor

@cor3ntin cor3ntin commented Sep 5, 2024

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

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
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 5, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 5, 2024

@llvm/pr-subscribers-clang

Author: cor3ntin (cor3ntin)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/107411.diff

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/AST/Expr.cpp (+10)
  • (modified) clang/test/SemaCXX/source_location.cpp (+13)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ab3c3e6049f602..968283a73a7f81 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 ^^^^^^^^^^^^^^^^^^^^^^^^^
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<CXXMethodDecl>(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..60aa19ae995674 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -989,3 +989,16 @@ 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; }();
+}
+}

// 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

@erichkeane erichkeane closed this in 0c8d6df Sep 5, 2024
@erichkeane erichkeane reopened this Sep 5, 2024
@erichkeane
Copy link
Collaborator

Woops! Had the wrong tab open and typed in the wrong 'fixes', did not mean to close this.

The patch was supposed to fix #107052

@zyn0217
Copy link
Contributor

zyn0217 commented Sep 5, 2024

While looking at it, I found another bug where we seem to have problems mangling std::source_location
https://clang.godbolt.org/z/467E19h45

@cor3ntin
Copy link
Contributor Author

cor3ntin commented Sep 5, 2024

While looking at it, I found another bug where we seem to have problems mangling std::source_location https://clang.godbolt.org/z/467E19h45

See #59948 (comment) :)

@cor3ntin cor3ntin merged commit d219c63 into llvm:main Sep 5, 2024
14 checks passed
@cor3ntin cor3ntin deleted the corentin/gh67134 branch September 5, 2024 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Internal Compiler Error 17.0.1 and trunk with NTTP (16 sloc)
4 participants