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(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 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 void f(decltype([]{})) {} // expected-note {{candidate}} +template void f(decltype([]{})) {} // expected-note {{candidate}} +void use_f() { f({}); } // expected-error {{ambiguous}} + +// Same. +template void g(const char (*)[([]{ return N; })()]) {} // expected-note {{candidate}} +template 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 @@

C++20 implementation status

Lambdas in unevaluated contexts P0315R4 - -
Clang 13 - [temp.deduct] p9 is not yet implemented. -
- + Partial