[cfe-commits] r60557 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp test/SemaCXX/new-delete.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Thu Dec 4 14:20:59 PST 2008
Author: cornedbee
Date: Thu Dec 4 16:20:51 2008
New Revision: 60557
URL: http://llvm.org/viewvc/llvm-project?rev=60557&view=rev
Log:
Code cleanup in new handling.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/new-delete.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=60557&r1=60556&r2=60557&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Dec 4 16:20:51 2008
@@ -840,6 +840,9 @@
Expr **PlaceArgs, unsigned NumPlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete);
+ bool FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
+ Expr** Args, unsigned NumArgs, DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
QualType Argument);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=60557&r1=60556&r2=60557&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Dec 4 16:20:51 2008
@@ -381,128 +381,106 @@
DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
IsArray ? OO_Array_New : OO_New);
if (AllocType->isRecordType() && !UseGlobal) {
- OverloadCandidateSet MemberNewCandidates;
- const CXXRecordType *Record = cast<CXXRecordType>(
- AllocType->getAsRecordType());
- IdentifierResolver::iterator I =
- IdResolver.begin(NewName, Record->getDecl(), /*LookInParentCtx=*/false);
- NamedDecl *Decl = (I == IdResolver.end()) ? 0 : *I;
- // Member operator new is implicitly treated as static, so don't use
- // AddMemberCandidate.
- if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(Decl))
- AddOverloadCandidate(Method, &AllocArgs[0], AllocArgs.size(),
- MemberNewCandidates,
- /*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(Decl)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*F))
- AddOverloadCandidate(Method, &AllocArgs[0], AllocArgs.size(),
- MemberNewCandidates,
- /*SuppressUserConversions=*/false);
- }
- }
-
- // Do the resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(MemberNewCandidates, Best)) {
- case OR_Success: {
- // Got one!
- FunctionDecl *FnDecl = Best->Function;
- // The first argument is size_t, and the first parameter must be size_t,
- // too.
- for (unsigned i = 1; i < AllocArgs.size(); ++i) {
- // FIXME: Passing word to diagnostic.
- // This might modify the argument expression, so pass the one in
- // PlaceArgs.
- if (PerformCopyInitialization(PlaceArgs[i-1],
- FnDecl->getParamDecl(i)->getType(),
- "passing"))
- return true;
- }
- OperatorNew = FnDecl;
- break;
- }
-
- case OR_No_Viable_Function:
- // No viable function; look something up in the global scope instead.
- break;
-
- case OR_Ambiguous:
- // FIXME: Bad location information.
- Diag(StartLoc, diag::err_ovl_ambiguous_oper)
- << (IsArray ? "new[]" : "new");
- PrintOverloadCandidates(MemberNewCandidates, /*OnlyViable=*/true);
+ CXXRecordDecl *Record = cast<CXXRecordType>(AllocType->getAsRecordType())
+ ->getDecl();
+ // FIXME: We fail to find inherited overloads.
+ if (FindAllocationOverload(StartLoc, NewName, &AllocArgs[0],
+ AllocArgs.size(), Record, /*AllowMissing=*/true,
+ OperatorNew))
return true;
- }
}
if (!OperatorNew) {
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
- OverloadCandidateSet GlobalNewCandidates;
- IdentifierResolver::iterator I =
- IdResolver.begin(NewName, Context.getTranslationUnitDecl(),
- /*LookInParentCtx=*/false);
- NamedDecl *Decl = (I == IdResolver.end()) ? 0 : *I;
- if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
- AddOverloadCandidate(Fn, &AllocArgs[0], AllocArgs.size(),
- GlobalNewCandidates,
- /*SuppressUserConversions=*/false);
- else if (OverloadedFunctionDecl *Ovl
- = dyn_cast_or_null<OverloadedFunctionDecl>(Decl)) {
- for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
- FEnd = Ovl->function_end();
- F != FEnd; ++F) {
- if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*F))
- AddOverloadCandidate(Fn, &AllocArgs[0], AllocArgs.size(),
- GlobalNewCandidates,
- /*SuppressUserConversions=*/false);
- }
- }
+ DeclContext *TUDecl = Context.getTranslationUnitDecl();
+ if (FindAllocationOverload(StartLoc, NewName, &AllocArgs[0],
+ AllocArgs.size(), TUDecl, /*AllowMissing=*/false,
+ OperatorNew))
+ return true;
+ }
- // Do the resolution.
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(GlobalNewCandidates, Best)) {
- case OR_Success: {
- // Got one!
- FunctionDecl *FnDecl = Best->Function;
- // The first argument is size_t, and the first parameter must be size_t,
- // too. This is checked on declaration and can be assumed.
- for (unsigned i = 1; i < AllocArgs.size(); ++i) {
- // FIXME: Passing word to diagnostic.
- // This might modify the argument expression, so pass the one in
- // PlaceArgs.
- if (PerformCopyInitialization(PlaceArgs[i-1],
- FnDecl->getParamDecl(i)->getType(),
- "passing"))
- return true;
- }
- OperatorNew = FnDecl;
- break;
- }
+ // FIXME: This is leaked on error. But so much is currently in Sema that it's
+ // easier to clean it in one go.
+ AllocArgs[0]->Destroy(Context);
+ return false;
+}
- case OR_No_Viable_Function:
- // FIXME: Bad location information.
- Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
- << NewName << (unsigned)GlobalNewCandidates.size();
- PrintOverloadCandidates(GlobalNewCandidates, /*OnlyViable=*/false);
- return true;
+/// FindAllocationOverload - Find an fitting overload for the allocation
+/// function in the specified scope.
+bool Sema::FindAllocationOverload(SourceLocation StartLoc, DeclarationName Name,
+ Expr** Args, unsigned NumArgs,
+ DeclContext *Ctx, bool AllowMissing,
+ FunctionDecl *&Operator)
+{
+ IdentifierResolver::iterator I =
+ IdResolver.begin(Name, Ctx, /*LookInParentCtx=*/false);
+ if (I == IdResolver.end()) {
+ if (AllowMissing)
+ return false;
+ // FIXME: Bad location information.
+ return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+ << Name << 0;
+ }
+
+ OverloadCandidateSet Candidates;
+ NamedDecl *Decl = *I;
+ // Even member operator new/delete are implicitly treated as static, so don't
+ // use AddMemberCandidate.
+ if (FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Decl))
+ AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
+ /*SuppressUserConversions=*/false);
+ else if (OverloadedFunctionDecl *Ovl
+ = dyn_cast_or_null<OverloadedFunctionDecl>(Decl)) {
+ for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+ FEnd = Ovl->function_end();
+ F != FEnd; ++F) {
+ if (FunctionDecl *Fn = *F)
+ AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+ }
- case OR_Ambiguous:
- // FIXME: Bad location information.
- Diag(StartLoc, diag::err_ovl_ambiguous_oper)
- << (IsArray ? "new[]" : "new");
- PrintOverloadCandidates(GlobalNewCandidates, /*OnlyViable=*/true);
- return true;
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch(BestViableFunction(Candidates, Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ // 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.)
+ for (unsigned i = 1; i < NumArgs; ++i) {
+ // FIXME: Passing word to diagnostic.
+ if (PerformCopyInitialization(Args[i-1],
+ FnDecl->getParamDecl(i)->getType(),
+ "passing"))
+ return true;
}
+ Operator = FnDecl;
+ return false;
}
- AllocArgs[0]->Destroy(Context);
- return false;
+ case OR_No_Viable_Function:
+ if (AllowMissing)
+ return false;
+ // FIXME: Bad location information.
+ Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
+ << Name << (unsigned)Candidates.size();
+ PrintOverloadCandidates(Candidates, /*OnlyViable=*/false);
+ return true;
+
+ case OR_Ambiguous:
+ // FIXME: Bad location information.
+ Diag(StartLoc, diag::err_ovl_ambiguous_call)
+ << Name;
+ PrintOverloadCandidates(Candidates, /*OnlyViable=*/true);
+ return true;
+ }
+ assert(false && "Unreachable, bad result from BestViableFunction");
+ return true;
}
+
/// DeclareGlobalNewDelete - Declare the global forms of operator new and
/// delete. These are:
/// @code
Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=60557&r1=60556&r2=60557&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Thu Dec 4 16:20:51 2008
@@ -14,6 +14,9 @@
// A special new, to verify that the global version isn't used.
void* operator new(size_t, S*);
};
+struct V : U
+{
+};
void* operator new(size_t); // expected-note {{candidate}}
void* operator new(size_t, int*); // expected-note {{candidate}}
@@ -34,6 +37,8 @@
ia4 *pai = new (int[3][4]);
pi = ::new int;
U *pu = new (ps) U;
+ // This is xfail. Inherited functions are not looked up currently.
+ //V *pv = new (ps) V;
}
void bad_news(int *ip)
@@ -56,7 +61,7 @@
(void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}}
(void)::S::new int; // expected-error {{expected unqualified-id}}
(void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
- (void)new (0L) int; // expected-error {{use of overloaded operator 'new' is ambiguous}}
+ (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
// This must fail, because the member version shouldn't be found.
(void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
// Some lacking cases due to lack of sema support.
More information about the cfe-commits
mailing list