diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-02 20:59:25 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-02 20:59:25 +0000 |
commit | 5bdaac5454d93d1dcdc2319818497b685be56fcf (patch) | |
tree | fbf67c57fa5cdd443d079a9f6f149baf2535f57a /lib/Sema | |
parent | 460ef136eb96b879f149c8703938a13c35b4bc68 (diff) |
Finish PR10217: Ensure we say that a special member was implicitly, not
explicitly, deleted in all relevant cases, and explain why.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153894 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 11 |
3 files changed, 28 insertions, 22 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 856f921a78..216663607c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4636,6 +4636,13 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return true; } + // For an anonymous struct or union, the copy and assignment special members + // will never be used, so skip the check. For an anonymous union declared at + // namespace scope, the constructor and destructor are used. + if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && + RD->isAnonymousStructOrUnion()) + return false; + // C++11 [class.copy]p7, p18: // If the class definition declares a move constructor or move assignment // operator, an implicitly declared copy constructor or copy assignment @@ -4667,6 +4674,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } } + // Do access control from the special member function + ContextRAII MethodContext(*this, MD); + // C++11 [class.dtor]p5: // -- for a virtual destructor, lookup of the non-array deallocation function // results in an ambiguity or in a function that is deleted or inaccessible @@ -4682,16 +4692,6 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, } } - // For an anonymous struct or union, the copy and assignment special members - // will never be used, so skip the check. For an anonymous union declared at - // namespace scope, the constructor and destructor are used. - if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && - RD->isAnonymousStructOrUnion()) - return false; - - // Do access control from the special member function - ContextRAII MethodContext(*this, MD); - SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose); for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 97cb647229..2478b03449 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -112,15 +112,18 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, void Sema::NoteDeletedFunction(FunctionDecl *Decl) { CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl); - if (Method && Method->isImplicit()) { + if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) { + // If the method was explicitly defaulted, point at that declaration. + if (!Method->isImplicit()) + Diag(Decl->getLocation(), diag::note_implicitly_deleted); + + // Try to diagnose why this special member function was implicitly + // deleted. This might fail, if that reason no longer applies. CXXSpecialMember CSM = getSpecialMember(Method); - // It is possible for us to no longer be able to determine why the special - // member function was deleted, due to a field or base class having acquired - // a new special member function by the addition of a default argument. - // FIXME: Add a test and a special-case diagnostic for this. - if (CSM != CXXInvalid && - ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true)) - return; + if (CSM != CXXInvalid) + ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true); + + return; } Diag(Decl->getLocation(), diag::note_unavailable_here) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e1d32056eb..27b04a7427 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -8237,7 +8237,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) - << FnKind << FnDesc << Fn->isDeleted(); + << FnKind << FnDesc + << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -10086,9 +10087,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, << getSpecialMember(Method) << BinaryOperator::getOpcodeStr(Opc) << getDeletedOrUnavailableSuffix(Best->Function); - - if (Method->getParent()->isLambda()) { - Diag(Method->getParent()->getLocation(), diag::note_lambda_decl); + + if (getSpecialMember(Method) != CXXInvalid) { + // The user probably meant to call this special member. Just + // explain why it's deleted. + NoteDeletedFunction(Method); return ExprError(); } } else { |