Look through using declarations when deciding whether to use an operator

delete for a virtual destructor.  Diagnose ambiguities.

Fixes PR7803.

llvm-svn: 110173
This commit is contained in:
John McCall 2010-08-04 00:31:26 +00:00
parent 4f9c40c521
commit 66a8759400
3 changed files with 76 additions and 11 deletions

View File

@ -2400,6 +2400,8 @@ def err_delete_incomplete_class_type : Warning<
"deleting incomplete class type %0; no conversions to pointer type">;
def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
def err_ambiguous_suitable_delete_member_function_found : Error<
"multiple suitable %0 functions in %1">;
def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;

View File

@ -1298,15 +1298,31 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Found.suppressDiagnostics();
llvm::SmallVector<DeclAccessPair,4> Matches;
for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
F != FEnd; ++F) {
if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
if (Delete->isUsualDeallocationFunction()) {
Operator = Delete;
CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
F.getPair());
return false;
}
CXXMethodDecl *Delete = cast<CXXMethodDecl>((*F)->getUnderlyingDecl());
if (Delete->isUsualDeallocationFunction())
Matches.push_back(F.getPair());
}
// There's exactly one suitable operator; pick it.
if (Matches.size() == 1) {
Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
Matches[0]);
return false;
// We found multiple suitable operators; complain about the ambiguity.
} else if (!Matches.empty()) {
Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
<< Name << RD;
for (llvm::SmallVectorImpl<DeclAccessPair>::iterator
F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
Diag((*F)->getUnderlyingDecl()->getLocation(),
diag::note_member_declared_here) << Name;
return true;
}
// We did find operator delete/operator delete[] declarations, but
@ -1316,10 +1332,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
<< Name << RD;
for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
F != FEnd; ++F) {
Diag((*F)->getLocation(), diag::note_member_declared_here)
<< Name;
}
F != FEnd; ++F)
Diag((*F)->getUnderlyingDecl()->getLocation(),
diag::note_member_declared_here) << Name;
return true;
}

View File

@ -0,0 +1,48 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
typedef typeof(sizeof(int)) size_t;
// PR7803
namespace test0 {
class A {
public:
static void operator delete(void *p) {};
virtual ~A();
};
class B : protected A {
public:
~B();
};
class C : protected B {
public:
using B::operator delete;
~C();
};
// Shouldn't have an error.
C::~C() {}
}
namespace test1 {
class A {
public:
static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}}
virtual ~A();
};
class B : protected A {
public:
static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}
~B();
};
class C : protected B {
public:
using A::operator delete;
using B::operator delete;
~C(); // expected-error {{multiple suitable 'operator delete' functions in 'C'}}
};
}