aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-02 19:38:47 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-02 19:38:47 +0000
commit0ab5b4c438b40c72252933072d4c9e9a948106f0 (patch)
treef64592879ef615a3dc335452ddbe1e76fe6d0de8 /lib/Sema/SemaDeclCXX.cpp
parent0c70181854a95fca0e0d56dfa1203eb2216052ea (diff)
If a defaulted special member is implicitly deleted, check whether it's
overriding a non-deleted virtual function. The existing check for this doesn't catch this case, because it fires before we mark the method as deleted. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178563 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp37
1 files changed, 30 insertions, 7 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d986635746..989edc6a45 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4403,7 +4403,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
if (ShouldDeleteSpecialMember(MD, CSM)) {
if (First) {
- MD->setDeletedAsWritten();
+ SetDeclDeleted(MD, MD->getLocation());
} else {
// C++11 [dcl.fct.def.default]p4:
// [For a] user-provided explicitly-defaulted function [...] if such a
@@ -7586,7 +7586,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
- DefaultCon->setDeletedAsWritten();
+ SetDeclDeleted(DefaultCon, ClassLoc);
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
@@ -7794,7 +7794,7 @@ void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
// Core issue (no number): if the same inheriting constructor is
// produced by multiple base class constructors from the same base
// class, the inheriting constructor is defined as deleted.
- result.first->second.second->setDeletedAsWritten();
+ SetDeclDeleted(result.first->second.second, UsingLoc);
}
continue;
}
@@ -7830,7 +7830,7 @@ void Sema::DeclareInheritingConstructors(CXXRecordDecl *ClassDecl) {
NewCtor->setParams(ParamDecls);
NewCtor->setInheritedConstructor(BaseCtor);
if (BaseCtor->isDeleted())
- NewCtor->setDeletedAsWritten();
+ SetDeclDeleted(NewCtor, UsingLoc);
ClassDecl->addDecl(NewCtor);
result.first->second.second = NewCtor;
@@ -7954,7 +7954,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
- Destructor->setDeletedAsWritten();
+ SetDeclDeleted(Destructor, ClassLoc);
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -8474,7 +8474,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// there is no user-declared move assignment operator, a copy assignment
// operator is implicitly declared as defaulted.
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
- CopyAssignment->setDeletedAsWritten();
+ SetDeclDeleted(CopyAssignment, ClassLoc);
// Note that we have added this copy-assignment operator.
++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
@@ -9277,7 +9277,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// user-declared move assignment operator, a copy constructor is implicitly
// declared as defaulted.
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
- CopyConstructor->setDeletedAsWritten();
+ SetDeclDeleted(CopyConstructor, ClassLoc);
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
@@ -10983,6 +10983,7 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
Diag(DelLoc, diag::err_deleted_non_function);
return;
}
+
if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
// Don't consider the implicit declaration we generate for explicit
// specializations. FIXME: Do not generate these implicit declarations.
@@ -10993,7 +10994,29 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
}
// If the declaration wasn't the first, we delete the function anyway for
// recovery.
+ Fn = Fn->getCanonicalDecl();
+ }
+
+ if (Fn->isDeleted())
+ return;
+
+ // See if we're deleting a function which is already known to override a
+ // non-deleted virtual function.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
+ bool IssuedDiagnostic = false;
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I) {
+ if (!(*MD->begin_overridden_methods())->isDeleted()) {
+ if (!IssuedDiagnostic) {
+ Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
+ IssuedDiagnostic = true;
+ }
+ Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
+ }
+ }
}
+
Fn->setDeletedAsWritten();
}