aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 20:59:25 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 20:59:25 +0000
commit5bdaac5454d93d1dcdc2319818497b685be56fcf (patch)
treefbf67c57fa5cdd443d079a9f6f149baf2535f57a /lib/Sema
parent460ef136eb96b879f149c8703938a13c35b4bc68 (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.cpp20
-rw-r--r--lib/Sema/SemaExpr.cpp19
-rw-r--r--lib/Sema/SemaOverload.cpp11
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 {