diff options
| author | Devin Coughlin <dcoughlin@apple.com> | 2015-10-13 22:20:52 +0000 |
|---|---|---|
| committer | Devin Coughlin <dcoughlin@apple.com> | 2015-10-13 22:20:52 +0000 |
| commit | 4f770dee5435d20c71bdb7627615476d93b6b741 (patch) | |
| tree | dcf343e901d8c3e5c7f6e6982e020a3ed2d08455 /clang/lib | |
| parent | d3a7bfcde543b9a5adb31d042d0aa7a3907ceaa6 (diff) | |
| download | bcm5719-llvm-4f770dee5435d20c71bdb7627615476d93b6b741.tar.gz bcm5719-llvm-4f770dee5435d20c71bdb7627615476d93b6b741.zip | |
[analyzer] Don’t invalidate CXXThis when conservatively evaluating const methods (PR 21606)
Prevent invalidation of `this' when a method is const; fixing PR 21606.
A patch by Sean Eveson!
Differential Revision: http://reviews.llvm.org/D13099
llvm-svn: 250237
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 5b6a8258d7a..a2875697231 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -148,7 +148,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, SmallVector<SVal, 8> ValuesToInvalidate; RegionAndSymbolInvalidationTraits ETraits; - getExtraInvalidatedValues(ValuesToInvalidate); + getExtraInvalidatedValues(ValuesToInvalidate, &ETraits); // Indexes of arguments whose values will be preserved by the call. llvm::SmallSet<unsigned, 4> PreserveArgs; @@ -403,8 +403,28 @@ const FunctionDecl *CXXInstanceCall::getDecl() const { return getSVal(CE->getCallee()).getAsFunctionDecl(); } -void CXXInstanceCall::getExtraInvalidatedValues(ValueList &Values) const { - Values.push_back(getCXXThisVal()); +void CXXInstanceCall::getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const { + SVal ThisVal = getCXXThisVal(); + Values.push_back(ThisVal); + + // Don't invalidate if the method is const and there are no mutable fields + if (const CXXMethodDecl *D = cast_or_null<CXXMethodDecl>(getDecl())) { + if (!D->isConst()) + return; + // Get the record decl for the class of 'This'. D->getParent() may return a + // base class decl, rather than the class of the instance which needs to be + // checked for mutable fields. + const Expr *Ex = getCXXThisExpr()->ignoreParenBaseCasts(); + const CXXRecordDecl *ParentRecord = Ex->getType()->getAsCXXRecordDecl(); + if (!ParentRecord || ParentRecord->hasMutableFields()) + return; + // Preserve CXXThis. + const MemRegion *ThisRegion = ThisVal.getAsRegion(); + assert(ThisRegion && "ThisValue was not a memory region"); + ETraits->setTrait(ThisRegion->getBaseRegion(), + RegionAndSymbolInvalidationTraits::TK_PreserveContents); + } } SVal CXXInstanceCall::getCXXThisVal() const { @@ -550,7 +570,8 @@ ArrayRef<ParmVarDecl*> BlockCall::parameters() const { return D->parameters(); } -void BlockCall::getExtraInvalidatedValues(ValueList &Values) const { +void BlockCall::getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const { // FIXME: This also needs to invalidate captured globals. if (const MemRegion *R = getBlockRegion()) Values.push_back(loc::MemRegionVal(R)); @@ -571,7 +592,8 @@ SVal CXXConstructorCall::getCXXThisVal() const { return UnknownVal(); } -void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values) const { +void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const { if (Data) Values.push_back(loc::MemRegionVal(static_cast<const MemRegion *>(Data))); } @@ -613,7 +635,8 @@ ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const { } void -ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values) const { +ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const { Values.push_back(getReceiverSVal()); } |

