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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98818 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 9251ab7..6c655e5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2628,6 +2628,11 @@
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);
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 6c01fee..3737c50 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -591,6 +591,24 @@
}
+/// 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,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index e1e5efa..2a55894 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -912,6 +912,8 @@
= 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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
<< 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 @@
// 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 @@
return true;
}
Operator = FnDecl;
+ CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
+ FnDecl, Best->getAccess());
return false;
}
diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp
index d6244aa..d101dcb 100644
--- a/test/CXX/class.access/p4.cpp
+++ b/test/CXX/class.access/p4.cpp
@@ -233,3 +233,20 @@
}
};
}
+
+// 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();
+ }
+}