[clang] 7ac308f - PR52073: Fix equivalence computation for lambda-expressions.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 8 13:54:12 PDT 2021
Author: Richard Smith
Date: 2021-10-08T13:54:01-07:00
New Revision: 7ac308fb8f283249b89851702aa07f3ed9ac86d4
URL: https://github.com/llvm/llvm-project/commit/7ac308fb8f283249b89851702aa07f3ed9ac86d4
DIFF: https://github.com/llvm/llvm-project/commit/7ac308fb8f283249b89851702aa07f3ed9ac86d4.diff
LOG: PR52073: Fix equivalence computation for lambda-expressions.
Distinct lambda expressions are always considered non-equivalent, so two
token-for-token identical function declarations whose signatures involve
lambda-expressions declare distinct functions.
Added:
Modified:
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/StmtProfile.cpp
clang/test/SemaCXX/lambda-unevaluated.cpp
clang/www/cxx_status.html
Removed:
################################################################################
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 34ad2b0b1d043..2d373c15031de 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4181,7 +4181,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
- case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
@@ -4966,6 +4965,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
break;
}
+ case Expr::LambdaExprClass: {
+ // A lambda-expression can't appear in the signature of an
+ // externally-visible declaration, so there's no standard mangling for
+ // this, but mangling as a literal of the closure type seems reasonable.
+ Out << "L";
+ mangleType(Context.getASTContext().getRecordType(cast<LambdaExpr>(E)->getLambdaClass()));
+ Out << "E";
+ }
+
case Expr::PackExpansionExprClass:
NotPrimaryExpr();
Out << "sp";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 9c48491dca712..2184eb7aa0109 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1933,30 +1933,9 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
void
StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
VisitExpr(S);
- for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
- C != CEnd; ++C) {
- if (C->capturesVLAType())
- continue;
-
- ID.AddInteger(C->getCaptureKind());
- switch (C->getCaptureKind()) {
- case LCK_StarThis:
- case LCK_This:
- break;
- case LCK_ByRef:
- case LCK_ByCopy:
- VisitDecl(C->getCapturedVar());
- ID.AddBoolean(C->isPackExpansion());
- break;
- case LCK_VLAType:
- llvm_unreachable("VLA type in explicit captures.");
- }
- }
- // Note: If we actually needed to be able to match lambda
- // expressions, we would have to consider parameters and return type
- // here, among other things.
- VisitStmt(S->getBody());
+ // C++20 [temp.over.link]p5:
+ // Two lambda-expressions are never considered equivalent.
+ VisitDecl(S->getLambdaClass());
}
void
diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index 07fa0d94bc8e4..1a06528a1c063 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -29,3 +29,17 @@ template <class T>
auto g(T) -> decltype([]() { T::invalid; } ());
auto e = g(0); // expected-error{{no matching function for call}}
// expected-note at -2 {{substitution failure}}
+
+namespace PR52073 {
+// OK, these are distinct functions not redefinitions.
+template<typename> void f(decltype([]{})) {} // expected-note {{candidate}}
+template<typename> void f(decltype([]{})) {} // expected-note {{candidate}}
+void use_f() { f<int>({}); } // expected-error {{ambiguous}}
+
+// Same.
+template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
+template<int N> void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}}
+// FIXME: We instantiate the lambdas into the context of the function template,
+// so we think they're dependent and can't evaluate a call to them.
+void use_g() { g<6>(&"hello"); } // expected-error {{no matching function}}
+}
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index f6531ed01e49e..2be1fb4b68738 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1021,11 +1021,7 @@ <h2 id="cxx20">C++20 implementation status</h2>
<tr>
<td>Lambdas in unevaluated contexts</td>
<td><a href="https://wg21.link/p0315r4">P0315R4</a></td>
- <td class="partial" align="center">
- <details><summary>Clang 13</summary>
- [temp.deduct] p9 is not yet implemented.
- </details>
- </td>
+ <td class="partial" align="center">Partial</td>
</tr>
<!-- Jacksonville papers -->
<tr>
More information about the cfe-commits
mailing list