r343279 - [cxx2a] P0624R2: Lambdas with no capture-default are
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 1 10:22:36 PDT 2018
On Mon, 1 Oct 2018, 09:55 David Blaikie via cfe-commits, <
cfe-commits at 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 at 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 at -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 at -2 {{no matching constructor}} expected-note at -3
>> 2{{candidate}}
>> +#else
>> + // expected-warning at -4 {{default construction of lambda is
>> incompatible with C++ standards before C++2a}}
>> +#endif
>> +
>> +void copy_lambda() { Lambda = Lambda; }
>> +#if __cplusplus <= 201703L
>> + // expected-error at -2 {{deleted}} expected-note at -10 {{lambda}}
>> +#else
>> + // expected-warning at -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 at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181001/e8414506/attachment-0001.html>
More information about the cfe-commits
mailing list