forked from OSchip/llvm-project
from code inspection, we were treating placement news with one argument as
non-placement news when selecting the corresponding operator delete; this is fixed. Access and ambiguity control for calls to operator new and delete. Also AFAICT llvm-svn: 98818
This commit is contained in:
parent
5497e49ae4
commit
fb6f52671a
|
@ -2628,6 +2628,11 @@ public:
|
|||
AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
|
||||
NamedDecl *D,
|
||||
AccessSpecifier Access);
|
||||
AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
|
||||
SourceRange PlacementRange,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NamedDecl *Allocator,
|
||||
AccessSpecifier Access);
|
||||
AccessResult CheckConstructorAccess(SourceLocation Loc,
|
||||
CXXConstructorDecl *D,
|
||||
AccessSpecifier Access);
|
||||
|
|
|
@ -591,6 +591,24 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
|
|||
}
|
||||
|
||||
|
||||
/// Checks access to an overloaded operator new or delete.
|
||||
Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
|
||||
SourceRange PlacementRange,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NamedDecl *Fn,
|
||||
AccessSpecifier Access) {
|
||||
if (!getLangOptions().AccessControl ||
|
||||
!NamingClass ||
|
||||
Access == AS_public)
|
||||
return AR_accessible;
|
||||
|
||||
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Fn);
|
||||
Entity.setDiag(diag::err_access)
|
||||
<< PlacementRange;
|
||||
|
||||
return CheckAccess(*this, OpLoc, Entity);
|
||||
}
|
||||
|
||||
/// Checks access to an overloaded member operator, including
|
||||
/// conversion operators.
|
||||
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
|
||||
|
|
|
@ -912,6 +912,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
= cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl());
|
||||
LookupQualifiedName(FoundDelete, RD);
|
||||
}
|
||||
if (FoundDelete.isAmbiguous())
|
||||
return true; // FIXME: clean up expressions?
|
||||
|
||||
if (FoundDelete.empty()) {
|
||||
DeclareGlobalNewDelete();
|
||||
|
@ -919,8 +921,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
}
|
||||
|
||||
FoundDelete.suppressDiagnostics();
|
||||
llvm::SmallVector<NamedDecl *, 4> Matches;
|
||||
if (NumPlaceArgs > 1) {
|
||||
UnresolvedSet<4> Matches;
|
||||
if (NumPlaceArgs > 0) {
|
||||
// C++ [expr.new]p20:
|
||||
// A declaration of a placement deallocation function matches the
|
||||
// declaration of a placement allocation function if it has the
|
||||
|
@ -962,7 +964,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
|
||||
|
||||
if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
|
||||
Matches.push_back(Fn);
|
||||
Matches.addDecl(Fn, D.getAccess());
|
||||
}
|
||||
} else {
|
||||
// C++ [expr.new]p20:
|
||||
|
@ -973,7 +975,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
D != DEnd; ++D) {
|
||||
if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
|
||||
if (isNonPlacementDeallocationFunction(Fn))
|
||||
Matches.push_back(*D);
|
||||
Matches.addDecl(D.getDecl(), D.getAccess());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -982,7 +984,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
// function, that function will be called; otherwise, no
|
||||
// deallocation function will be called.
|
||||
if (Matches.size() == 1) {
|
||||
// FIXME: Drops access, using-declaration info!
|
||||
OperatorDelete = cast<FunctionDecl>(Matches[0]->getUnderlyingDecl());
|
||||
|
||||
// C++0x [expr.new]p20:
|
||||
|
@ -998,6 +999,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
|||
PlaceArgs[NumPlaceArgs - 1]->getLocEnd());
|
||||
Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
|
||||
<< DeleteName;
|
||||
} else {
|
||||
CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
|
||||
Matches[0].getDecl(), Matches[0].getAccess());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1023,10 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
|
|||
<< Name << Range;
|
||||
}
|
||||
|
||||
// FIXME: handle ambiguity
|
||||
if (R.isAmbiguous())
|
||||
return true;
|
||||
|
||||
R.suppressDiagnostics();
|
||||
|
||||
OverloadCandidateSet Candidates(StartLoc);
|
||||
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
|
||||
|
@ -1050,7 +1057,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
|
|||
// The first argument is size_t, and the first parameter must be size_t,
|
||||
// too. This is checked on declaration and can be assumed. (It can't be
|
||||
// asserted on, though, since invalid decls are left in there.)
|
||||
// Whatch out for variadic allocator function.
|
||||
// Watch out for variadic allocator function.
|
||||
unsigned NumArgsInFnDecl = FnDecl->getNumParams();
|
||||
for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
|
||||
if (PerformCopyInitialization(Args[i],
|
||||
|
@ -1059,6 +1066,8 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
|
|||
return true;
|
||||
}
|
||||
Operator = FnDecl;
|
||||
CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
|
||||
FnDecl, Best->getAccess());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -233,3 +233,20 @@ namespace test7 {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Ignored operator new and delete overloads are not
|
||||
namespace test8 {
|
||||
typedef __typeof__(sizeof(int)) size_t;
|
||||
|
||||
class A {
|
||||
void *operator new(size_t s);
|
||||
void operator delete(void *p);
|
||||
public:
|
||||
void *operator new(size_t s, int n);
|
||||
void operator delete(void *p, int n);
|
||||
};
|
||||
|
||||
void test() {
|
||||
new (2) A();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue