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@-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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits