diff options
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 14 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp | 31 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp | 12 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp | 1 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp | 2 |
7 files changed, 67 insertions, 7 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 22d2a20d457..42b102f55a0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -635,6 +635,7 @@ DeclContext *Sema::getFunctionLevelDeclContext() { if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) { DC = DC->getParent(); } else if (isa<CXXMethodDecl>(DC) && + cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call && cast<CXXRecordDecl>(DC->getParent())->isLambda()) { DC = DC->getParent()->getParent(); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 467cf43797e..b8ea85bea96 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4340,6 +4340,13 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) { switch (CSM) { case CXXDefaultConstructor: IsConstructor = true; + + // C++11 [expr.lambda.prim]p19: + // The closure type associated with a lambda-expression has a + // deleted (8.4.3) default constructor. + if (RD->isLambda()) + return true; + break; case CXXCopyConstructor: IsConstructor = true; @@ -4621,6 +4628,12 @@ bool Sema::ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD) { if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) return false; + // C++11 [expr.lambda.prim]p19: + // The closure type associated with a lambda-expression has a + // [...] deleted copy assignment operator. + if (RD->isLambda()) + return true; + SourceLocation Loc = MD->getLocation(); // Do access control from the constructor diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index e82654ef06d..2bd69edb07c 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -406,6 +406,13 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, CallOperator->setType(FunctionTy); } + // C++ [expr.prim.lambda]p7: + // The lambda-expression's compound-statement yields the + // function-body (8.4) of the function call operator [...]. + ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false); + CallOperator->setLexicalDeclContext(Class); + Class->addDecl(CallOperator); + // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture // has a public non-virtual non-explicit const conversion function @@ -450,15 +457,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Class->addDecl(Conversion); } - // C++ [expr.prim.lambda]p7: - // The lambda-expression's compound-statement yields the - // function-body (8.4) of the function call operator [...]. - ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false); - // Finalize the lambda class. SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); - CallOperator->setLexicalDeclContext(Class); - Class->addDecl(CallOperator); ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), 0); CheckCompletedCXXClass(Class); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp new file mode 100644 index 00000000000..b5a445cd9ec --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +struct MoveOnly { + MoveOnly(MoveOnly&&); + MoveOnly(const MoveOnly&); +}; + +template<typename T> T &&move(T&); +void test_special_member_functions(MoveOnly mo, int i) { + // FIXME: terrible note + auto lambda1 = [i]() { }; // expected-note{{function has been explicitly marked deleted here}} \ + // expected-note{{the implicit copy assignment operator}} \ + // expected-note{{the implicit move assignment operator}} \ + + // Default constructor + decltype(lambda1) lambda2; // expected-error{{call to deleted constructor}} + + // Copy assignment operator + lambda1 = lambda1; // expected-error{{overload resolution selected deleted operator '='}} + + // Move assignment operator + lambda1 = move(lambda1); + + // Copy constructor + decltype(lambda1) lambda3 = lambda1; + decltype(lambda1) lambda4(lambda1); + + // Move constructor + decltype(lambda1) lambda5 = move(lambda1); + decltype(lambda1) lambda6(move(lambda1)); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp new file mode 100644 index 00000000000..4487cfc4ba2 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T> +void destroy(T* ptr) { + ptr->~T(); + (*ptr).~T(); +} + +void destructor() { + auto lambda = []{}; + destroy(&lambda); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp index 74003431c68..581dbca309f 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -8,6 +8,7 @@ void test_attributes() { template<typename T> struct bogus_override_if_virtual : public T { + bogus_override_if_virtual() : T(*(T*)0) { } int operator()() const; }; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp index 8fa3837214d..627071343e0 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp @@ -45,9 +45,11 @@ void test_capture_constness(int i, const int ic) { struct S1 { int x, y; + S1 &operator=(int*); int operator()(int); void f() { [&]()->int { + S1 &s1 = operator=(&this->x); return operator()(this->x + y); }(); } |