From 1e68aacb52d8212b687d74c1ea04e049ec0824b8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 16 Nov 2016 00:03:24 +0000 Subject: [PATCH] PR23281: Fix implementation of DR1891 to implement the intent: that is, a lambda-expression does not have a move-assignment operator. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@287057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 6 +++- test/CXX/drs/dr18xx.cpp | 11 +++++-- .../expr/expr.prim/expr.prim.lambda/p19.cpp | 4 +-- test/SemaCXX/lambda-expressions.cpp | 33 +++++++++++++++++++ www/cxx_dr_status.html | 2 +- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 357e075786..b40ca28cef 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -993,7 +993,11 @@ public: !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveConstructor() && - !hasUserDeclaredDestructor(); + !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(); } /// \brief Determine whether we need to eagerly declare a move assignment diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp index bc72b67d1e..436bccc8e4 100644 --- a/test/CXX/drs/dr18xx.cpp +++ b/test/CXX/drs/dr18xx.cpp @@ -7,11 +7,11 @@ // expected-no-diagnostics #endif -void dr1891() { // dr1891: 3.6 +void dr1891() { // dr1891: 4.0 #if __cplusplus >= 201103L int n; - auto a = []{}; // expected-note 2{{candidate}} - auto b = [=]{ return n; }; // expected-note 2{{candidate}} + auto a = []{}; // expected-note 2{{candidate}} expected-note 2{{here}} + auto b = [=]{ return n; }; // expected-note 2{{candidate}} expected-note 2{{here}} typedef decltype(a) A; typedef decltype(b) B; @@ -20,5 +20,10 @@ void dr1891() { // dr1891: 3.6 A x; // expected-error {{no matching constructor}} B y; // expected-error {{no matching constructor}} + + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast(a); // expected-error {{copy assignment operator is implicitly deleted}} + b = b; // expected-error {{copy assignment operator is implicitly deleted}} + b = static_cast(b); // expected-error {{copy assignment operator is implicitly deleted}} #endif } diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp index 40360e4069..1dbcbf4980 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -7,7 +7,7 @@ struct MoveOnly { template T &&move(T&); void test_special_member_functions(MoveOnly mo, int i) { - auto lambda1 = [i]() { }; // expected-note {{lambda expression begins here}} expected-note 2{{candidate}} + auto lambda1 = [i]() { }; // expected-note 2{{lambda expression begins here}} expected-note 2{{candidate}} // Default constructor decltype(lambda1) lambda2; // expected-error{{no matching constructor}} @@ -16,7 +16,7 @@ void test_special_member_functions(MoveOnly mo, int i) { lambda1 = lambda1; // expected-error{{copy assignment operator is implicitly deleted}} // Move assignment operator - lambda1 = move(lambda1); + lambda1 = move(lambda1); // expected-error{{copy assignment operator is implicitly deleted}} // Copy constructor decltype(lambda1) lambda3 = lambda1; diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 5fffe41117..4d06fdf089 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -95,6 +95,39 @@ namespace ImplicitCapture { } } +namespace SpecialMembers { + void f() { + auto a = []{}; // expected-note 2{{here}} expected-note 2{{candidate}} + decltype(a) b; // expected-error {{no matching constructor}} + decltype(a) c = a; + decltype(a) d = static_cast(a); + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast(a); // expected-error {{copy assignment operator is implicitly deleted}} + } + struct P { + P(const P&) = delete; // expected-note {{deleted here}} + }; + struct Q { + ~Q() = delete; // expected-note {{deleted here}} + }; + struct R { + R(const R&) = default; + R(R&&) = delete; + R &operator=(const R&) = delete; + R &operator=(R&&) = delete; + }; + void g(P &p, Q &q, R &r) { + auto pp = [p]{}; // expected-error {{deleted constructor}} + auto qq = [q]{}; // expected-error {{deleted function}} expected-note {{because}} + + auto a = [r]{}; // expected-note 2{{here}} + decltype(a) b = a; + decltype(a) c = static_cast(a); // ok, copies R + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast(a); // expected-error {{copy assignment operator is implicitly deleted}} + } +} + namespace PR12031 { struct X { template diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index ad73e7e4fb..293535238b 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -11161,7 +11161,7 @@ and POD class 1891 DRWP Move constructor/assignment for closure class - Clang 3.6 + SVN 1892 -- 2.40.0