r343279 - [cxx2a] P0624R2: Lambdas with no capture-default are

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 1 10:23:17 PDT 2018


Excellent, excellent - thanks!

On Mon, Oct 1, 2018 at 10:22 AM Richard Smith <richard at metafoo.co.uk> wrote:

> 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/d2c92d2e/attachment-0001.html>


More information about the cfe-commits mailing list