diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-07-26 22:25:31 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-07-26 22:25:31 +0000 |
commit | e52c91478a144f913019591ee1839e1846345f71 (patch) | |
tree | 72258c45368d464e4ed54f271820a2637472e5f5 /lib/Sema/SemaExprCXX.cpp | |
parent | 54562ec9471222010cded42de16bc23286d873cd (diff) |
A couple minor issues with Sema for delete:
1. Attempting to delete an expression of incomplete class type should be an error, not a warning.
2. If someone tries to delete a pointer to an incomplete class type, make sure we actually emit
the delete expression after we warn.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136161 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0225c6629e..a3e3c11c6a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1840,24 +1840,32 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, << Type << Ex.get()->getSourceRange()); QualType Pointee = Type->getAs<PointerType>()->getPointeeType(); + QualType PointeeElem = Context.getBaseElementType(Pointee); + + if (unsigned AddressSpace = Pointee.getAddressSpace()) + return Diag(Ex.get()->getLocStart(), + diag::err_address_space_qualified_delete) + << Pointee.getUnqualifiedType() << AddressSpace; + + CXXRecordDecl *PointeeRD = 0; if (Pointee->isVoidType() && !isSFINAEContext()) { // The C++ standard bans deleting a pointer to a non-object type, which // effectively bans deletion of "void*". However, most compilers support // this, so we treat it as a warning unless we're in a SFINAE context. Diag(StartLoc, diag::ext_delete_void_ptr_operand) << Type << Ex.get()->getSourceRange(); - } else if (Pointee->isFunctionType() || Pointee->isVoidType()) + } else if (Pointee->isFunctionType() || Pointee->isVoidType()) { return ExprError(Diag(StartLoc, diag::err_delete_operand) << Type << Ex.get()->getSourceRange()); - else if (!Pointee->isDependentType() && - RequireCompleteType(StartLoc, Pointee, - PDiag(diag::warn_delete_incomplete) - << Ex.get()->getSourceRange())) - return ExprError(); - else if (unsigned AddressSpace = Pointee.getAddressSpace()) - return Diag(Ex.get()->getLocStart(), - diag::err_address_space_qualified_delete) - << Pointee.getUnqualifiedType() << AddressSpace; + } else if (!Pointee->isDependentType()) { + if (!RequireCompleteType(StartLoc, Pointee, + PDiag(diag::warn_delete_incomplete) + << Ex.get()->getSourceRange())) { + if (const RecordType *RT = PointeeElem->getAs<RecordType>()) + PointeeRD = cast<CXXRecordDecl>(RT->getDecl()); + } + } + // C++ [expr.delete]p2: // [Note: a pointer to a const type can be the operand of a // delete-expression; it is not necessary to cast away the constness @@ -1877,12 +1885,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( ArrayForm ? OO_Array_Delete : OO_Delete); - QualType PointeeElem = Context.getBaseElementType(Pointee); - if (const RecordType *RT = PointeeElem->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - + if (PointeeRD) { if (!UseGlobal && - FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete)) + FindDeallocationFunction(StartLoc, PointeeRD, DeleteName, + OperatorDelete)) return ExprError(); // If we're allocating an array of records, check whether the @@ -1900,8 +1906,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2); } - if (!RD->hasTrivialDestructor()) - if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { + if (!PointeeRD->hasTrivialDestructor()) + if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { MarkDeclarationReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); DiagnoseUseOfDecl(Dtor, StartLoc); @@ -1915,8 +1921,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // behavior is undefined. // // Note: a final class cannot be derived from, no issue there - if (!ArrayForm && RD->isPolymorphic() && !RD->hasAttr<FinalAttr>()) { - CXXDestructorDecl *dtor = RD->getDestructor(); + if (!ArrayForm && PointeeRD->isPolymorphic() && + !PointeeRD->hasAttr<FinalAttr>()) { + CXXDestructorDecl *dtor = PointeeRD->getDestructor(); if (!dtor || !dtor->isVirtual()) Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem; } @@ -1944,9 +1951,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, MarkDeclarationReferenced(StartLoc, OperatorDelete); // Check access and ambiguity of operator delete and destructor. - if (const RecordType *RT = PointeeElem->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { + if (PointeeRD) { + if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, PDiag(diag::err_access_dtor) << PointeeElem); } |