From: Sean Hunt Date: Wed, 25 May 2011 23:16:36 +0000 (+0000) Subject: Update our diagnostics to properly account for move operations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82713174914bdb927a254c5ee188e35fd79c4948;p=clang Update our diagnostics to properly account for move operations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132096 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7d6c660ae4..f36f3475c1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -611,11 +611,17 @@ def ext_rvalue_to_reference_access_ctor : ExtWarn< "a reference to a temporary; was %select{private|protected}0">, AccessControl, InGroup; def err_access_base_ctor : Error< + // The ERRORs represent other special members that aren't constructors, in + // hopes that someone will bother noticing and reporting if they appear "%select{base class|inherited virtual base class}0 %1 has %select{private|" - "protected}3 %select{|copy }2constructor">, AccessControl; + "protected}3 %select{default |copy |move |*ERROR* |*ERROR* " + "|*ERROR*|}2constructor">, AccessControl; def err_access_field_ctor : Error< + // The ERRORs represent other special members that aren't constructors, in + // hopes that someone will bother noticing and reporting if they appear "field of type %0 has %select{private|protected}2 " - "%select{|copy }1constructor">, AccessControl; + "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">, + AccessControl; def err_access_ctor_field : Error<"field of type %1 has %select{private|protected}2 constructor">, @@ -749,23 +755,27 @@ def note_ivar_decl : Note<"ivar is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_previous_decl : Note<"%0 declared here">; def note_member_synthesized_at : Note< - "implicit default %select{constructor|copy constructor|" - "copy assignment operator|destructor}0 for %1 first required here">; + "implicit default %select{constructor|copy constructor|move constructor|copy " + "assignment operator|move assignment operator|destructor}0 for %1 first " + "required here">; def err_missing_default_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{base class|member}2 %3 which does not have a default " "constructor">; def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " - "%select{constructor|copy constructor|copy assignment operator|destructor}2">; + "%select{constructor|copy constructor|move constructor|copy assignment " + "operator|move assignment operator|destructor}2">; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; def note_nontrivial_has_nontrivial : Note< "because type %0 has a %select{member|base class}1 with a non-trivial " - "%select{constructor|copy constructor|copy assignment operator|destructor}2">; + "%select{constructor|copy constructor|move constructor|copy assignment " + "operator|move assignment operator|destructor}2">; def note_nontrivial_user_defined : Note< "because type %0 has a user-declared %select{constructor|copy constructor|" - "copy assignment operator|destructor}1">; + "move constructor|copy assignment operator|move assignment operator|" + "destructor}1">; def err_static_data_member_not_allowed_in_union_or_anon_struct : Error< "static data member %0 not allowed in %select{anonymous struct|union}1">; def err_union_member_of_reference_type : Error< @@ -1444,7 +1454,9 @@ def note_ovl_candidate : Note<"candidate " "function |function |constructor |" "is the implicit default constructor|" "is the implicit copy constructor|" + "is the implicit move constructor|" "is the implicit copy assignment operator|" + "is the implicit move assignment operator|" "is an inherited constructor}0%1">; def note_ovl_candidate_inherited_constructor : Note<"inherited from here">; @@ -1475,7 +1487,9 @@ def note_ovl_candidate_arity : Note<"candidate " "%select{function|function|constructor|function|function|constructor|" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0 %select{|template }1" "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 " "%plural{1:was|:were}4 provided">; @@ -1495,7 +1509,9 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 " "not viable: cannot convert argument of incomplete type %2 to %3">; def note_ovl_candidate_bad_overload : Note<"candidate " @@ -1503,7 +1519,9 @@ def note_ovl_candidate_bad_overload : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1" " not viable: no overload of %3 matching %2 for %ordinal4 argument">; def note_ovl_candidate_bad_conv : Note<"candidate " @@ -1511,7 +1529,9 @@ def note_ovl_candidate_bad_conv : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1" " not viable: no known conversion from %2 to %3 for " "%select{%ordinal5 argument|object argument}4">; @@ -1520,7 +1540,9 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 not viable: " "%select{%ordinal6|'this'}5 argument (%2) is in " "address space %3, but parameter must be in address space %4">; @@ -1529,7 +1551,9 @@ def note_ovl_candidate_bad_gc : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 not viable: " "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 " "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">; @@ -1544,7 +1568,9 @@ def note_ovl_candidate_bad_cvr : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 not viable: " "%ordinal4 argument (%2) would lose " "%select{const|restrict|const and restrict|volatile|const and volatile|" @@ -1555,7 +1581,9 @@ def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate " "function |function |constructor |" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" "constructor (inherited)}0%1" " not viable: cannot %select{convert from|convert from|bind}2 " "%select{base class pointer|superclass|base class object of type}2 %3 to " @@ -2169,10 +2197,12 @@ def warn_missing_prototype : Warning< def err_redefinition : Error<"redefinition of %0">; def err_definition_of_implicitly_declared_member : Error< "definition of implicitly declared %select{default constructor|copy " - "constructor|copy assignment operator|destructor}1">; + "constructor|move constructor|copy assignment operator|move assignment " + "operator|destructor}1">; def err_definition_of_explicitly_defaulted_member : Error< "definition of explicitly defaulted %select{default constructor|copy " - "constructor|copy assignment operator|destructor}0">; + "constructor|move constructor|copy assignment operator|move assignment " + "operator|destructor}0">; def err_redefinition_extern_inline : Error< "redefinition of a 'extern inline' function %0 is not supported in " "%select{C99 mode|C++}1">; @@ -3679,12 +3709,15 @@ def err_defaulted_copy_assign_quals : Error< "or 'volatile' qualifiers">; def err_incorrect_defaulted_exception_spec : Error< "exception specification of explicitly defaulted %select{default constructor|" - "copy constructor|copy assignment operator|destructor}0 does not match the " + "copy constructor|move constructor|copy assignment operator|move assignment " + "operator|destructor}0 does not match the " "calculated one">; def err_out_of_line_default_deletes : Error< - "defaulting this %select{default constructor|copy constructor|copy " - "assignment operator|destructor}0 would delete it after its first " - "declaration">; + "defaulting this %select{default constructor|copy constructor|move " + "constructor|copy assignment operator|move assignment operator|destructor}0 " + "would delete it after its first declaration">; +def err_defaulted_move_unsupported : Error< + "defaulting move functions not yet supported">; def warn_array_index_precedes_bounds : Warning< "array index of '%0' indexes before the beginning of the array">, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index be76a4a755..236ccd05f1 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1114,13 +1114,13 @@ public: Declarator *D = 0); enum CXXSpecialMember { - CXXInvalid = -1, - CXXDefaultConstructor = 0, - CXXCopyConstructor = 1, - CXXCopyAssignment = 2, - CXXDestructor = 3, - CXXMoveConstructor = 4, - CXXMoveAssignment = 5 + CXXDefaultConstructor, + CXXCopyConstructor, + CXXMoveConstructor, + CXXCopyAssignment, + CXXMoveAssignment, + CXXDestructor, + CXXInvalid }; bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 0eb9854562..add0c5d659 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -1471,16 +1471,14 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, AccessEntity.setDiag(PDiag(diag::err_access_base_ctor) << Entity.isInheritedVirtualBase() << Entity.getBaseSpecifier()->getType() - << (getSpecialMember(Constructor) == - Sema::CXXCopyConstructor)); + << getSpecialMember(Constructor)); break; case InitializedEntity::EK_Member: { const FieldDecl *Field = cast(Entity.getDecl()); AccessEntity.setDiag(PDiag(diag::err_access_field_ctor) << Field->getType() - << (getSpecialMember(Constructor) == - Sema::CXXCopyConstructor)); + << getSpecialMember(Constructor)); break; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8b0ee7057a..dae7ba20b1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1508,15 +1508,16 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { if (Ctor->isCopyConstructor()) return Sema::CXXCopyConstructor; + if (Ctor->isMoveConstructor()) + return Sema::CXXMoveConstructor; + if (Ctor->isDefaultConstructor()) return Sema::CXXDefaultConstructor; - } - - if (isa(MD)) + } else if (isa(MD)) { return Sema::CXXDestructor; - - if (MD->isCopyAssignmentOperator()) + } else if (MD->isCopyAssignmentOperator()) { return Sema::CXXCopyAssignment; + } return Sema::CXXInvalid; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1e3baa26f3..6870f3c46b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3024,6 +3024,11 @@ void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { CheckExplicitlyDefaultedCopyAssignment(*MI); break; + case CXXMoveConstructor: + case CXXMoveAssignment: + Diag(MI->getLocation(), diag::err_defaulted_move_unsupported); + break; + default: // FIXME: Do moves once they exist llvm_unreachable("non-special member explicitly defaulted!"); @@ -3059,7 +3064,7 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) - << 0 /* default constructor */, + << CXXDefaultConstructor, PDiag(), ExceptionType, SourceLocation(), CtorType, CD->getLocation())) { @@ -3082,7 +3087,7 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { CD->setDeletedAsWritten(); } else { Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << 0 /* default constructor */; + << CXXDefaultConstructor; CD->setInvalidDecl(); } } @@ -3126,7 +3131,7 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { if (CtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) - << 1 /* copy constructor */, + << CXXCopyConstructor, PDiag(), ExceptionType, SourceLocation(), CtorType, CD->getLocation())) { @@ -3149,7 +3154,7 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { CD->setDeletedAsWritten(); } else { Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) - << 1 /* copy constructor */; + << CXXCopyConstructor; CD->setInvalidDecl(); } } @@ -3211,7 +3216,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { if (OperType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) - << 2 /* copy assignment operator */, + << CXXCopyAssignment, PDiag(), ExceptionType, SourceLocation(), OperType, MD->getLocation())) { @@ -3235,7 +3240,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { MD->setDeletedAsWritten(); } else { Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) - << 2 /* copy assignment operator */; + << CXXCopyAssignment; MD->setInvalidDecl(); } } @@ -3257,7 +3262,7 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { if (DtorType->hasExceptionSpec()) { if (CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) - << 3 /* destructor */, + << CXXDestructor, PDiag(), ExceptionType, SourceLocation(), DtorType, DD->getLocation())) { @@ -3276,7 +3281,7 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { DD->setDeletedAsWritten(); } else { Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) - << 3 /* destructor */; + << CXXDestructor; DD->setInvalidDecl(); } } @@ -8715,6 +8720,11 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { break; } + case CXXMoveConstructor: + case CXXMoveAssignment: + Diag(Dcl->getLocation(), diag::err_defaulted_move_unsupported); + break; + default: // FIXME: Do the rest once we have move functions break; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c3f330e371..e43c5fbbb5 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6436,7 +6436,9 @@ enum OverloadCandidateKind { oc_constructor_template, oc_implicit_default_constructor, oc_implicit_copy_constructor, + oc_implicit_move_constructor, oc_implicit_copy_assignment, + oc_implicit_move_assignment, oc_implicit_inherited_constructor }; @@ -6458,8 +6460,15 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, if (Ctor->getInheritedConstructor()) return oc_implicit_inherited_constructor; - return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor - : oc_implicit_default_constructor; + if (Ctor->isDefaultConstructor()) + return oc_implicit_default_constructor; + + if (Ctor->isMoveConstructor()) + return oc_implicit_move_constructor; + + assert(Ctor->isCopyConstructor() && + "unexpected sort of implicit constructor"); + return oc_implicit_copy_constructor; } if (CXXMethodDecl *Meth = dyn_cast(Fn)) { @@ -6468,6 +6477,9 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, if (!Meth->isImplicit()) return isTemplate ? oc_method_template : oc_method; + if (Meth->isMoveAssignmentOperator()) + return oc_implicit_move_assignment; + assert(Meth->isCopyAssignmentOperator() && "implicit method is not copy assignment operator?"); return oc_implicit_copy_assignment; diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index f28a3714e7..add3635fa6 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -96,7 +96,7 @@ namespace test2 { A a; // expected-error {{calling a private constructor}} A A::foo; // okay - class B : A { }; // expected-error {{base class 'test2::A' has private constructor}} + class B : A { }; // expected-error {{base class 'test2::A' has private default constructor}} B b; // expected-note{{implicit default constructor}} class C : virtual A { @@ -104,7 +104,7 @@ namespace test2 { C(); }; - class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private constructor}} + class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private default constructor}} D d; // expected-note{{implicit default constructor}} } diff --git a/test/PCH/cxx0x-default-delete.cpp b/test/PCH/cxx0x-default-delete.cpp index 20b0c7f39c..753ac4736c 100644 --- a/test/PCH/cxx0x-default-delete.cpp +++ b/test/PCH/cxx0x-default-delete.cpp @@ -14,7 +14,7 @@ struct foo { #else -foo::foo() { } // expected-error{{definition of explicitly defaulted}} +foo::foo() { } // expected-error{{definition of explicitly defaulted default constructor}} foo f; void fn() { f.bar(); // expected-error{{deleted function}}