On Mon, 1 Oct 2018, 09:55 David Blaikie via cfe-commits, < cfe-commits@lists.llvm.org> wrote:
> Awesome - should/does this mean stateless lambdas can be used in > uninitialized contexts? > > std::set<foo, decltype([](const foo& LHS, const foo& RHS) { return ...; > })> s; > > Would be kind of neat/handy (so you didn't have to pass in the comparator > on construction, etc) > Not quite: that also needs p0315r4, but that's coming in C++20 too. On Thu, Sep 27, 2018 at 3:48 PM Richard Smith via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: rsmith >> Date: Thu Sep 27 15:47:04 2018 >> New Revision: 343279 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=343279&view=rev >> Log: >> [cxx2a] P0624R2: Lambdas with no capture-default are >> default-constructible and assignable. >> >> Added: >> cfe/trunk/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp >> Modified: >> cfe/trunk/include/clang/AST/DeclCXX.h >> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> cfe/trunk/lib/AST/DeclCXX.cpp >> cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> cfe/trunk/lib/Sema/SemaExpr.cpp >> cfe/trunk/test/SemaCXX/cxx17-compat.cpp >> cfe/trunk/www/cxx_status.html >> >> Modified: cfe/trunk/include/clang/AST/DeclCXX.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/AST/DeclCXX.h (original) >> +++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Sep 27 15:47:04 2018 >> @@ -974,10 +974,7 @@ public: >> bool needsImplicitDefaultConstructor() const { >> return !data().UserDeclaredConstructor && >> !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) && >> - // C++14 [expr.prim.lambda]p20: >> - // The closure type associated with a lambda-expression has >> no >> - // default constructor. >> - !isLambda(); >> + (!isLambda() || lambdaIsDefaultConstructibleAndAssignable()); >> } >> >> /// Determine whether this class has any user-declared constructors. >> @@ -1167,10 +1164,7 @@ public: >> !hasUserDeclaredCopyAssignment() && >> !hasUserDeclaredMoveConstructor() && >> !hasUserDeclaredDestructor() && >> - // C++1z [expr.prim.lambda]p21: "the closure type has a >> deleted copy >> - // assignment operator". The intent is that this counts as a >> user >> - // declared copy assignment, but we do not model it that way. >> - !isLambda(); >> + (!isLambda() || lambdaIsDefaultConstructibleAndAssignable()); >> } >> >> /// Determine whether we need to eagerly declare a move assignment >> @@ -1210,6 +1204,10 @@ public: >> /// a template). >> bool isGenericLambda() const; >> >> + /// Determine whether this lambda should have an implicit default >> constructor >> + /// and copy and move assignment operators. >> + bool lambdaIsDefaultConstructibleAndAssignable() const; >> + >> /// Retrieve the lambda call operator of the closure type >> /// if this is a closure type. >> CXXMethodDecl *getLambdaCallOperator() const; >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 27 >> 15:47:04 2018 >> @@ -6633,6 +6633,11 @@ let CategoryName = "Lambda Issue" in { >> InGroup<DeprecatedThisCapture>, DefaultIgnore; >> def note_deprecated_this_capture : Note< >> "add an explicit capture of 'this' to capture '*this' by reference">; >> + >> + // C++2a default constructible / assignable lambdas. >> + def warn_cxx17_compat_lambda_def_ctor_assign : Warning< >> + "%select{default construction|assignment}0 of lambda is incompatible >> with " >> + "C++ standards before C++2a">, InGroup<CXXPre2aCompat>, >> DefaultIgnore; >> } >> >> def err_return_in_captured_stmt : Error< >> >> Modified: cfe/trunk/lib/AST/DeclCXX.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/AST/DeclCXX.cpp (original) >> +++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Sep 27 15:47:04 2018 >> @@ -628,6 +628,24 @@ bool CXXRecordDecl::hasSubobjectAtOffset >> return false; >> } >> >> +bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const { >> + assert(isLambda() && "not a lambda"); >> + >> + // C++2a [expr.prim.lambda.capture]p11: >> + // The closure type associated with a lambda-expression has no >> default >> + // constructor if the lambda-expression has a lambda-capture and a >> + // defaulted default constructor otherwise. It has a deleted copy >> + // assignment operator if the lambda-expression has a lambda-capture >> and >> + // defaulted copy and move assignment operators otherwise. >> + // >> + // C++17 [expr.prim.lambda]p21: >> + // The closure type associated with a lambda-expression has no >> default >> + // constructor and a deleted copy assignment operator. >> + if (getLambdaCaptureDefault() != LCD_None) >> + return false; >> + return getASTContext().getLangOpts().CPlusPlus2a; >> +} >> + >> void CXXRecordDecl::addedMember(Decl *D) { >> if (!D->isImplicit() && >> !isa<FieldDecl>(D) && >> >> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 27 15:47:04 2018 >> @@ -7088,7 +7088,8 @@ bool Sema::ShouldDeleteSpecialMember(CXX >> // The closure type associated with a lambda-expression has a >> // deleted (8.4.3) default constructor and a deleted copy >> // assignment operator. >> - if (RD->isLambda() && >> + // C++2a adds back these operators if the lambda has no >> capture-default. >> + if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() >> && >> (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { >> if (Diagnose) >> Diag(RD->getLocation(), diag::note_lambda_decl); >> >> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Sep 27 15:47:04 2018 >> @@ -266,6 +266,17 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl * >> return true; >> } >> >> + if (auto *MD = dyn_cast<CXXMethodDecl>(D)) { >> + // Lambdas are only default-constructible or assignable in C++2a >> onwards. >> + if (MD->getParent()->isLambda() && >> + ((isa<CXXConstructorDecl>(MD) && >> + cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) || >> + MD->isCopyAssignmentOperator() || >> MD->isMoveAssignmentOperator())) { >> + Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign) >> + << !isa<CXXConstructorDecl>(MD); >> + } >> + } >> + >> auto getReferencedObjCProp = [](const NamedDecl *D) -> >> const ObjCPropertyDecl * { >> if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) >> >> Modified: cfe/trunk/test/SemaCXX/cxx17-compat.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx17-compat.cpp?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/cxx17-compat.cpp (original) >> +++ cfe/trunk/test/SemaCXX/cxx17-compat.cpp Thu Sep 27 15:47:04 2018 >> @@ -27,3 +27,18 @@ struct B { >> // expected-warning@-4 {{default member initializer for bit-field >> is incompatible with C++ standards before C++2a}} >> #endif >> }; >> + >> +auto Lambda = []{}; >> +decltype(Lambda) AnotherLambda; >> +#if __cplusplus <= 201703L >> + // expected-error@-2 {{no matching constructor}} expected-note@-3 >> 2{{candidate}} >> +#else >> + // expected-warning@-4 {{default construction of lambda is >> incompatible with C++ standards before C++2a}} >> +#endif >> + >> +void copy_lambda() { Lambda = Lambda; } >> +#if __cplusplus <= 201703L >> + // expected-error@-2 {{deleted}} expected-note@-10 {{lambda}} >> +#else >> + // expected-warning@-4 {{assignment of lambda is incompatible with >> C++ standards before C++2a}} >> +#endif >> >> Added: cfe/trunk/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp?rev=343279&view=auto >> >> ============================================================================== >> --- cfe/trunk/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp (added) >> +++ cfe/trunk/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp Thu Sep >> 27 15:47:04 2018 >> @@ -0,0 +1,37 @@ >> +// RUN: %clang_cc1 -std=c++2a -verify %s >> + >> +auto a = []{}; >> +decltype(a) a2; >> +void f(decltype(a) x, decltype(a) y) { >> + x = y; >> + x = static_cast<decltype(a)&&>(y); >> +} >> + >> +template<typename T> >> +struct X { >> + constexpr X() { T::error; } // expected-error {{'::'}} >> + X(const X&); >> + constexpr X &operator=(const X&) { T::error; } // expected-error >> {{'::'}} >> + constexpr X &operator=(X&&) { T::error; } // expected-error {{'::'}} >> +}; >> +extern X<int> x; >> +auto b = [x = x]{}; // expected-note 3{{in instantiation of}} >> +decltype(b) b2; // expected-note {{in implicit default constructor}} >> +void f(decltype(b) x, decltype(b) y) { >> + x = y; // expected-note {{in implicit copy assignment}} >> + x = static_cast<decltype(b)&&>(y); // expected-note {{in implicit move >> assignment}} >> +} >> + >> +struct Y { >> + Y() = delete; // expected-note {{deleted}} >> + Y(const Y&); >> + Y &operator=(const Y&) = delete; // expected-note 2{{deleted}} >> + Y &operator=(Y&&) = delete; >> +}; >> +extern Y y; >> +auto c = [y = y]{}; // expected-note 3{{deleted because}} >> +decltype(c) c2; // expected-error {{deleted}} >> +void f(decltype(c) x, decltype(c) y) { >> + x = y; // expected-error {{deleted}} >> + x = static_cast<decltype(c)&&>(y); // expected-error {{deleted}} >> +} >> >> Modified: cfe/trunk/www/cxx_status.html >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=343279&r1=343278&r2=343279&view=diff >> >> ============================================================================== >> --- cfe/trunk/www/cxx_status.html (original) >> +++ cfe/trunk/www/cxx_status.html Thu Sep 27 15:47:04 2018 >> @@ -905,7 +905,7 @@ as the draft C++2a standard evolves. >> <tr> >> <td>Default constructible and assignable stateless lambdas</td> >> <td><a href="http://wg21.link/p0624r2">P0624R2</a></td> >> - <td class="none" align="center">No</td> >> + <td class="svn" align="center">SVN</td> >> </tr> >> <tr> >> <td>Lambdas in unevaluated contexts</td> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits