diff options
author | Anders Carlsson <andersca@mac.com> | 2009-11-15 18:45:20 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-11-15 18:45:20 +0000 |
commit | e1d34ba0e4ca15ff298f73cafc6b775fd0f3e231 (patch) | |
tree | a342eba32cfff81aa7830d71a76ce2f5ff5de979 /clang/lib/Sema/SemaExprCXX.cpp | |
parent | a46efbb857c6dc7dee491b48c44f5427341b7e0e (diff) | |
download | bcm5719-llvm-e1d34ba0e4ca15ff298f73cafc6b775fd0f3e231.tar.gz bcm5719-llvm-e1d34ba0e4ca15ff298f73cafc6b775fd0f3e231.zip |
Factor finding a deallocation function for a record type out into a separate function.
llvm-svn: 88857
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 102 |
1 files changed, 62 insertions, 40 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f5ce44e1063..d0279538e3a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -753,6 +753,59 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, ((DeclContext *)TUScope->getEntity())->addDecl(Alloc); } +bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, + FunctionDecl* &Operator) { + LookupResult Found; + // Try to find operator delete/operator delete[] in class scope. + LookupQualifiedName(Found, RD, Name, LookupOrdinaryName); + + if (Found.isAmbiguous()) { + DiagnoseAmbiguousLookup(Found, Name, StartLoc); + return true; + } + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F)) + if (Delete->isUsualDeallocationFunction()) { + Operator = Delete; + return false; + } + } + + // We did find operator delete/operator delete[] declarations, but + // none of them were suitable. + if (!Found.empty()) { + Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) + << Name << RD; + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + Diag((*F)->getLocation(), + diag::note_delete_member_function_declared_here) + << Name; + } + + return true; + } + + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + + CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation()); + Expr* DeallocArgs[1]; + DeallocArgs[0] = &Null; + if (FindAllocationOverload(StartLoc, SourceRange(), Name, + DeallocArgs, 1, TUDecl, /*AllowMissing=*/false, + Operator)) + return true; + + assert(Operator && "Did not find a deallocation function!"); + return false; +} + /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: /// @code ::delete ptr; @endcode /// or @@ -844,52 +897,21 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( ArrayForm ? OO_Array_Delete : OO_Delete); - LookupResult Found; - if (Pointee->isRecordType() && !UseGlobal) { - CXXRecordDecl *Record - = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl()); - - // Try to find operator delete/operator delete[] in class scope. - LookupQualifiedName(Found, Record, DeleteName, LookupOrdinaryName); - - if (Found.isAmbiguous()) { - DiagnoseAmbiguousLookup(Found, DeleteName, StartLoc); - return ExprError(); - } - - // FIXME: Diagnose ambiguity properly - for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); - F != FEnd; ++F) { - if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F)) - if (Delete->isUsualDeallocationFunction()) { - OperatorDelete = Delete; - break; - } - } - - if (!OperatorDelete && !Found.empty()) { - // We did find operator delete/operator delete[] declarations, but - // none of them were suitable. - Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) - << DeleteName << Record; - - for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); - F != FEnd; ++F) { - Diag((*F)->getLocation(), - diag::note_delete_member_function_declared_here) - << DeleteName; - } + if (const RecordType *RT = Pointee->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + if (!UseGlobal && + FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete)) return ExprError(); - } - if (!Record->hasTrivialDestructor()) - if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context)) + if (!RD->hasTrivialDestructor()) + if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context)) MarkDeclarationReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); } - + if (!OperatorDelete) { - // Didn't find a member overload. Look for a global one. + // Look for a global declaration. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, |