diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-04 22:20:51 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-04 22:20:51 +0000 |
commit | 7f6623914e779e41eb3d85f9a2dc3affea5de1e8 (patch) | |
tree | f6d8d69b4fb67376fc1144b1d10c0067ba9bbf3c /lib | |
parent | 271b7af521b784ec505a37a29ac36ec596954a08 (diff) |
Code cleanup in new handling.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60557 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 196 |
2 files changed, 90 insertions, 109 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 150b32ec51..f82651bd28 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -840,6 +840,9 @@ public: 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); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 72ca8df5e8..1e9b945a18 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -381,128 +381,106 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, bool UseGlobal, 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; + } - case OR_Ambiguous: - // FIXME: Bad location information. - Diag(StartLoc, diag::err_ovl_ambiguous_oper) - << (IsArray ? "new[]" : "new"); - PrintOverloadCandidates(GlobalNewCandidates, /*OnlyViable=*/true); - return true; + 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); } } - AllocArgs[0]->Destroy(Context); - return false; + // 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; + } + + 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 |