aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Lex/PPMacroExpansion.cpp2
-rw-r--r--lib/Parse/ParseDeclCXX.cpp1
-rw-r--r--lib/Sema/SemaDecl.cpp2
-rw-r--r--lib/Sema/SemaDeclCXX.cpp27
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp62
-rw-r--r--test/Lexer/has_feature_cxx0x.cpp9
6 files changed, 87 insertions, 16 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 8bc1351f6e..d0828d0d5d 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -619,7 +619,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_deleted_functions", LangOpts.CPlusPlus0x)
.Case("cxx_explicit_conversions", LangOpts.CPlusPlus0x)
//.Case("cxx_generalized_initializers", LangOpts.CPlusPlus0x)
- //.Case("cxx_implicit_moves", false)
+ .Case("cxx_implicit_moves", LangOpts.CPlusPlus0x)
//.Case("cxx_inheriting_constructors", false)
.Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x)
//.Case("cxx_lambdas", false)
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index f1dec4ab3f..385683abd6 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1979,7 +1979,6 @@ ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction,
return ExprResult();
}
} else if (Tok.is(tok::kw_default)) {
- Diag(ConsumeToken(), diag::err_default_special_members);
if (IsFunction)
Diag(Tok, diag::err_default_delete_in_multiple_declaration)
<< 0 /* default */;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index dc16dcae72..e0b6981424 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1529,6 +1529,8 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
return Sema::CXXDestructor;
} else if (MD->isCopyAssignmentOperator()) {
return Sema::CXXCopyAssignment;
+ } else if (MD->isMoveAssignmentOperator()) {
+ return Sema::CXXMoveAssignment;
}
return Sema::CXXInvalid;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f35fdeda38..04868cee57 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1984,7 +1984,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
BasePath.push_back(BaseSpec);
CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
CK_UncheckedDerivedToBase,
- Moving ? VK_RValue : VK_LValue,
+ Moving ? VK_XValue : VK_LValue,
&BasePath).take();
InitializationKind InitKind
@@ -2055,7 +2055,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
: cast<ValueDecl>(Field), AS_public);
MemberLookup.resolveKind();
- ExprResult CopyCtorArg
+ ExprResult CtorArg
= SemaRef.BuildMemberReferenceExpr(MemberExprBase,
ParamType, Loc,
/*IsArrow=*/false,
@@ -2063,14 +2063,14 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
/*FirstQualifierInScope=*/0,
MemberLookup,
/*TemplateArgs=*/0);
- if (CopyCtorArg.isInvalid())
+ if (CtorArg.isInvalid())
return true;
// C++11 [class.copy]p15:
// - if a member m has rvalue reference type T&&, it is direct-initialized
// with static_cast<T&&>(x.m);
- if (RefersToRValueRef(CopyCtorArg.get())) {
- CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg.take());
+ if (RefersToRValueRef(CtorArg.get())) {
+ CtorArg = CastForMoving(SemaRef, CtorArg.take());
}
// When the field we are copying is an array, create index variables for
@@ -2104,13 +2104,12 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc);
assert(!IterationVarRef.isInvalid() &&
"Reference to invented variable cannot fail!");
-
+
// Subscript the array with this iteration variable.
- CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CopyCtorArg.take(),
- Loc,
+ CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.take(), Loc,
IterationVarRef.take(),
- Loc);
- if (CopyCtorArg.isInvalid())
+ Loc);
+ if (CtorArg.isInvalid())
return true;
BaseType = Array->getElementType();
@@ -2118,7 +2117,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// The array subscript expression is an lvalue, which is wrong for moving.
if (Moving && InitializingArray)
- CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg.take());
+ CtorArg = CastForMoving(SemaRef, CtorArg.take());
// Construct the entity that we will be initializing. For an array, this
// will be first element in the array, which may require several levels
@@ -2138,13 +2137,13 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationKind InitKind =
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
- Expr *CopyCtorArgE = CopyCtorArg.takeAs<Expr>();
+ Expr *CtorArgE = CtorArg.takeAs<Expr>();
InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
- &CopyCtorArgE, 1);
+ &CtorArgE, 1);
ExprResult MemberInit
= InitSeq.Perform(SemaRef, Entities.back(), InitKind,
- MultiExprArg(&CopyCtorArgE, 1));
+ MultiExprArg(&CtorArgE, 1));
MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
if (MemberInit.isInvalid())
return true;
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp
new file mode 100644
index 0000000000..6b964dba31
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// FIXME: test with non-std qualifiers
+
+namespace move {
+ struct Const {
+ Const(const Const&&) = default; // expected-error {{the parameter for an explicitly-defaulted move constructor may not be const}}
+ Const& operator=(const Const&&) = default; // expected-error {{the parameter for an explicitly-defaulted move assignment operator may not be const}}
+ };
+
+ struct Volatile {
+ Volatile(volatile Volatile&&) = default; // expected-error {{the parameter for an explicitly-defaulted move constructor may not be volatile}}
+ Volatile& operator=(volatile Volatile&&) = default; // expected-error {{the parameter for an explicitly-defaulted move assignment operator may not be volatile}}
+ };
+
+ struct AssignmentRet1 {
+ AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}}
+ };
+
+ struct AssignmentRet2 {
+ const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}}
+ };
+
+ struct ConstAssignment {
+ ConstAssignment& operator=(ConstAssignment&&) const = default; // expected-error {{an explicitly-defaulted move assignment operator may not have 'const' or 'volatile' qualifiers}}
+ };
+}
+
+namespace copy {
+ struct Volatile {
+ Volatile(const volatile Volatile&) = default; // expected-error {{the parameter for an explicitly-defaulted copy constructor may not be volatile}}
+ Volatile& operator=(const volatile Volatile&) = default; // expected-error {{the parameter for an explicitly-defaulted copy assignment operator may not be volatile}}
+ };
+
+ struct Const {
+ Const(const Const&) = default;
+ Const& operator=(const Const&) = default;
+ };
+
+ struct NonConst {
+ NonConst(NonConst&) = default;
+ NonConst& operator=(NonConst&) = default;
+ };
+
+ struct BadConst {
+ NonConst nc; // makes implicit copy non-const
+ BadConst(const BadConst&) = default; // expected-error {{is const, but}}
+ BadConst& operator=(const BadConst&) = default; // expected-error {{is const, but}}
+ };
+
+ struct AssignmentRet1 {
+ AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}}
+ };
+
+ struct AssignmentRet2 {
+ const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}}
+ };
+
+ struct ConstAssignment {
+ ConstAssignment& operator=(const ConstAssignment&) const = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
+ };
+}
diff --git a/test/Lexer/has_feature_cxx0x.cpp b/test/Lexer/has_feature_cxx0x.cpp
index ca5f868d9b..7625430384 100644
--- a/test/Lexer/has_feature_cxx0x.cpp
+++ b/test/Lexer/has_feature_cxx0x.cpp
@@ -164,3 +164,12 @@ int no_alias_templates();
// CHECK-0X: has_alias_templates
// CHECK-NO-0X: no_alias_templates
+
+#if __has_feature(cxx_implicit_moves)
+int has_implicit_moves();
+#else
+int no_implicit_moves();
+#endif
+
+// CHECK-0X: has_implicit_moves
+// CHECK-NO-0X: no_implicit_moves