diff options
author | Diego Novillo <dnovillo@google.com> | 2015-05-14 20:57:48 +0000 |
---|---|---|
committer | Diego Novillo <dnovillo@google.com> | 2015-05-14 20:57:48 +0000 |
commit | c324b92c3557b0981d38c9ee7920f2c7ab0856c8 (patch) | |
tree | e2e62915de0e13d35ffa8de9696d66af54358fac /clang/lib/Sema | |
parent | 4f0f708bf1a6f2604ce15929ad4deb10f462a85f (diff) | |
download | llvm-c324b92c3557b0981d38c9ee7920f2c7ab0856c8.zip llvm-c324b92c3557b0981d38c9ee7920f2c7ab0856c8.tar.gz llvm-c324b92c3557b0981d38c9ee7920f2c7ab0856c8.tar.bz2 |
Revert "Detect uses of mismatching forms of 'new' and 'delete'"
This reverts commit 742dc9b6c9686ab52860b7da39c3a126d8a97fbc.
This is generating multiple segfaults in our internal builds.
Test case coming up shortly.
llvm-svn: 237391
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 267 |
3 files changed, 9 insertions, 287 deletions
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 9ecb5a7..51a1274 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -212,15 +212,7 @@ void MultiplexExternalSemaSource::ReadUndefinedButUsed( for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadUndefinedButUsed(Undefined); } - -void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions( - llvm::MapVector<FieldDecl *, - llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & - Exprs) { - for (auto &Source : Sources) - Source->ReadMismatchingDeleteExpressions(Exprs); -} - + bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){ for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->LookupUnqualified(R, S); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index dea01ba..6825dfa 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -860,17 +860,6 @@ void Sema::ActOnEndOfTranslationUnit() { } } - if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) { - if (ExternalSource) - ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs); - for (const auto &DeletedFieldInfo : DeleteExprs) { - for (const auto &DeleteExprLoc : DeletedFieldInfo.second) { - AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first, - DeleteExprLoc.second); - } - } - } - // Check we've noticed that we're no longer parsing the initializer for every // variable. If we miss cases, then at best we have a performance issue and // at worst a rejects-valid bug. @@ -1230,9 +1219,6 @@ void ExternalSemaSource::ReadUndefinedButUsed( llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) { } -void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector< - FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {} - void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { SourceLocation Loc = this->Loc; if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); @@ -1481,8 +1467,3 @@ CapturedRegionScopeInfo *Sema::getCurCapturedRegion() { return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back()); } - -const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> & -Sema::getMismatchingDeleteExpressions() const { - return DeleteExprs; -} diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 12f0636..b853eaef 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2339,261 +2339,6 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, return false; } -namespace { -/// \brief Checks whether delete-expression, and new-expression used for -/// initializing deletee have the same array form. -class MismatchingNewDeleteDetector { -public: - enum MismatchResult { - /// Indicates that there is no mismatch or a mismatch cannot be proven. - NoMismatch, - /// Indicates that variable is initialized with mismatching form of \a new. - VarInitMismatches, - /// Indicates that member is initialized with mismatching form of \a new. - MemberInitMismatches, - /// Indicates that 1 or more constructors' definitions could not been - /// analyzed, and they will be checked again at the end of translation unit. - AnalyzeLater - }; - - /// \param EndOfTU True, if this is the final analysis at the end of - /// translation unit. False, if this is the initial analysis at the point - /// delete-expression was encountered. - explicit MismatchingNewDeleteDetector(bool EndOfTU) - : IsArrayForm(false), Field(nullptr), EndOfTU(EndOfTU), - HasUndefinedConstructors(false) {} - - /// \brief Checks whether pointee of a delete-expression is initialized with - /// matching form of new-expression. - /// - /// If return value is \c VarInitMismatches or \c MemberInitMismatches at the - /// point where delete-expression is encountered, then a warning will be - /// issued immediately. If return value is \c AnalyzeLater at the point where - /// delete-expression is seen, then member will be analyzed at the end of - /// translation unit. \c AnalyzeLater is returned iff at least one constructor - /// couldn't be analyzed. If at least one constructor initializes the member - /// with matching type of new, the return value is \c NoMismatch. - MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE); - /// \brief Analyzes a class member. - /// \param Field Class member to analyze. - /// \param DeleteWasArrayForm Array form-ness of the delete-expression used - /// for deleting the \p Field. - MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm); - /// List of mismatching new-expressions used for initialization of the pointee - llvm::SmallVector<const CXXNewExpr *, 4> NewExprs; - /// Indicates whether delete-expression was in array form. - bool IsArrayForm; - FieldDecl *Field; - -private: - const bool EndOfTU; - /// \brief Indicates that there is at least one constructor without body. - bool HasUndefinedConstructors; - /// \brief Returns \c CXXNewExpr from given initialization expression. - /// \param E Expression used for initializing pointee in delete-expression. - /// \param E can be a single-element \c InitListExpr consisting of - /// \param E new-expression. - const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E); - /// \brief Returns whether member is initialized with mismatching form of - /// \c new either by the member initializer or in-class initialization. - /// - /// If bodies of all constructors are not visible at the end of translation - /// unit or at least one constructor initializes member with the matching - /// form of \c new, mismatch cannot be proven, and this function will return - /// \c NoMismatch. - MismatchResult analyzeMemberExpr(const MemberExpr *ME); - /// \brief Returns whether variable is initialized with mismatching form of - /// \c new. - /// - /// If variable is initialized with matching form of \c new or variable is not - /// initialized with a \c new expression, this function will return true. - /// If variable is initialized with mismatching form of \c new, returns false. - /// \param D Variable to analyze. - bool hasMatchingVarInit(const DeclRefExpr *D); - /// \brief Checks whether the constructor initializes pointee with mismatching - /// form of \c new. - /// - /// Returns true, if member is initialized with matching form of \c new in - /// member initializer list. Returns false, if member is initialized with the - /// matching form of \c new in this constructor's initializer or given - /// constructor isn't defined at the point where delete-expression is seen, or - /// member isn't initialized by the constructor. - bool hasMatchingNewInCtor(const CXXConstructorDecl *CD); - /// \brief Checks whether member is initialized with matching form of - /// \c new in member initializer list. - bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI); - /// Checks whether member is initialized with mismatching form of \c new by - /// in-class initializer. - MismatchResult analyzeInClassInitializer(); -}; -} - -MismatchingNewDeleteDetector::MismatchResult -MismatchingNewDeleteDetector::analyzeDeleteExpr(const CXXDeleteExpr *DE) { - NewExprs.clear(); - assert(DE && "Expected delete-expression"); - IsArrayForm = DE->isArrayForm(); - const Expr *E = DE->getArgument()->IgnoreParenImpCasts(); - if (const MemberExpr *ME = dyn_cast<const MemberExpr>(E)) { - return analyzeMemberExpr(ME); - } else if (const DeclRefExpr *D = dyn_cast<const DeclRefExpr>(E)) { - if (!hasMatchingVarInit(D)) - return VarInitMismatches; - } - return NoMismatch; -} - -const CXXNewExpr * -MismatchingNewDeleteDetector::getNewExprFromInitListOrExpr(const Expr *E) { - assert(E != nullptr && "Expected a valid initializer expression"); - E = E->IgnoreParenImpCasts(); - if (const InitListExpr *ILE = dyn_cast<const InitListExpr>(E)) { - if (ILE->getNumInits() == 1) - E = dyn_cast<const CXXNewExpr>(ILE->getInit(0)->IgnoreParenImpCasts()); - } - - return dyn_cast<const CXXNewExpr>(E); -} - -bool MismatchingNewDeleteDetector::hasMatchingNewInCtorInit( - const CXXCtorInitializer *CI) { - const CXXNewExpr *NE = nullptr; - if (Field == CI->getMember() && - (NE = getNewExprFromInitListOrExpr(CI->getInit()))) { - if (NE->isArray() == IsArrayForm) - return true; - else - NewExprs.push_back(NE); - } - return false; -} - -bool MismatchingNewDeleteDetector::hasMatchingNewInCtor( - const CXXConstructorDecl *CD) { - if (CD->isImplicit()) - return false; - const FunctionDecl *Definition = CD; - if (!CD->isThisDeclarationADefinition() && !CD->isDefined(Definition)) { - HasUndefinedConstructors = true; - return EndOfTU; - } - for (const auto *CI : cast<const CXXConstructorDecl>(Definition)->inits()) { - if (hasMatchingNewInCtorInit(CI)) - return true; - } - return false; -} - -MismatchingNewDeleteDetector::MismatchResult -MismatchingNewDeleteDetector::analyzeInClassInitializer() { - assert(Field != nullptr && "This should be called only for members"); - if (const CXXNewExpr *NE = - getNewExprFromInitListOrExpr(Field->getInClassInitializer())) { - if (NE->isArray() != IsArrayForm) { - NewExprs.push_back(NE); - return MemberInitMismatches; - } - } - return NoMismatch; -} - -MismatchingNewDeleteDetector::MismatchResult -MismatchingNewDeleteDetector::analyzeField(FieldDecl *Field, - bool DeleteWasArrayForm) { - assert(Field != nullptr && "Analysis requires a valid class member."); - this->Field = Field; - IsArrayForm = DeleteWasArrayForm; - const CXXRecordDecl *RD = cast<const CXXRecordDecl>(Field->getParent()); - for (const auto *CD : RD->ctors()) { - if (hasMatchingNewInCtor(CD)) - return NoMismatch; - } - if (HasUndefinedConstructors) - return EndOfTU ? NoMismatch : AnalyzeLater; - if (!NewExprs.empty()) - return MemberInitMismatches; - return Field->hasInClassInitializer() ? analyzeInClassInitializer() - : NoMismatch; -} - -MismatchingNewDeleteDetector::MismatchResult -MismatchingNewDeleteDetector::analyzeMemberExpr(const MemberExpr *ME) { - assert(ME != nullptr && "Expected a member expression"); - if (FieldDecl *F = dyn_cast<FieldDecl>(ME->getMemberDecl())) - return analyzeField(F, IsArrayForm); - return NoMismatch; -} - -bool MismatchingNewDeleteDetector::hasMatchingVarInit(const DeclRefExpr *D) { - const CXXNewExpr *NE = nullptr; - if (const VarDecl *VD = dyn_cast<const VarDecl>(D->getDecl())) { - if (VD->hasInit() && (NE = getNewExprFromInitListOrExpr(VD->getInit())) && - NE->isArray() != IsArrayForm) { - NewExprs.push_back(NE); - } - } - return NewExprs.empty(); -} - -static void -DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc, - const MismatchingNewDeleteDetector &Detector) { - SourceLocation EndOfDelete = SemaRef.getLocForEndOfToken(DeleteLoc); - FixItHint H; - if (!Detector.IsArrayForm) - H = FixItHint::CreateInsertion(EndOfDelete, "[]"); - else { - SourceLocation RSquare = Lexer::findLocationAfterToken( - DeleteLoc, tok::l_square, SemaRef.getSourceManager(), - SemaRef.getLangOpts(), true); - if (RSquare.isValid()) - H = FixItHint::CreateRemoval(SourceRange(EndOfDelete, RSquare)); - } - SemaRef.Diag(DeleteLoc, diag::warn_mismatched_delete_new) - << Detector.IsArrayForm << H; - - for (const auto *NE : Detector.NewExprs) - SemaRef.Diag(NE->getExprLoc(), diag::note_allocated_here) - << Detector.IsArrayForm; -} - -void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) { - if (Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) - return; - MismatchingNewDeleteDetector Detector(/*EndOfTU=*/false); - switch (Detector.analyzeDeleteExpr(DE)) { - case MismatchingNewDeleteDetector::VarInitMismatches: - case MismatchingNewDeleteDetector::MemberInitMismatches: { - DiagnoseMismatchedNewDelete(*this, DE->getLocStart(), Detector); - break; - } - case MismatchingNewDeleteDetector::AnalyzeLater: { - DeleteExprs[Detector.Field].push_back( - std::make_pair(DE->getLocStart(), DE->isArrayForm())); - break; - } - case MismatchingNewDeleteDetector::NoMismatch: - break; - } -} - -void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, - bool DeleteWasArrayForm) { - MismatchingNewDeleteDetector Detector(/*EndOfTU=*/true); - switch (Detector.analyzeField(Field, DeleteWasArrayForm)) { - case MismatchingNewDeleteDetector::VarInitMismatches: - llvm_unreachable("This analysis should have been done for class members."); - case MismatchingNewDeleteDetector::AnalyzeLater: - llvm_unreachable("Analysis cannot be postponed any point beyond end of " - "translation unit."); - case MismatchingNewDeleteDetector::MemberInitMismatches: - DiagnoseMismatchedNewDelete(*this, DeleteLoc, Detector); - break; - case MismatchingNewDeleteDetector::NoMismatch: - break; - } -} - /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: /// @code ::delete ptr; @endcode /// or @@ -2709,6 +2454,12 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } + // 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 + // (5.2.11) of the pointer expression before it is used as the operand + // of the delete-expression. ] + if (Pointee->isArrayType() && !ArrayForm) { Diag(StartLoc, diag::warn_delete_array_type) << Type << Ex.get()->getSourceRange() @@ -2783,7 +2534,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, DeleteName); MarkFunctionReferenced(StartLoc, OperatorDelete); - + // Check access and ambiguity of operator delete and destructor. if (PointeeRD) { if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { @@ -2793,11 +2544,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - CXXDeleteExpr *Result = new (Context) CXXDeleteExpr( + return new (Context) CXXDeleteExpr( Context.VoidTy, UseGlobal, ArrayForm, ArrayFormAsWritten, UsualArrayDeleteWantsSize, OperatorDelete, Ex.get(), StartLoc); - AnalyzeDeleteExprMismatch(Result); - return Result; } /// \brief Check the use of the given variable as a C++ condition in an if, |