Charusso created this revision. Charusso added reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus. Charusso added a project: clang. Herald added subscribers: cfe-commits, dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet.
- Repository: rC Clang https://reviews.llvm.org/D63093 Files: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -156,21 +156,14 @@ typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo; -class MallocChecker : public Checker<check::DeadSymbols, - check::PointerEscape, - check::ConstPointerEscape, - check::PreStmt<ReturnStmt>, - check::EndFunction, - check::PreCall, - check::PostStmt<CallExpr>, - check::PostStmt<CXXNewExpr>, - check::NewAllocator, - check::PreStmt<CXXDeleteExpr>, - check::PostStmt<BlockExpr>, - check::PostObjCMessage, - check::Location, - eval::Assume> -{ +class MallocChecker + : public Checker<check::DeadSymbols, check::PointerEscape, + check::ConstPointerEscape, check::PreStmt<ReturnStmt>, + check::EndFunction, check::PreCall, + check::PostStmt<CallExpr>, check::PostStmt<CXXNewExpr>, + check::PostStmt<CXXBindTemporaryExpr>, check::NewAllocator, + check::PreStmt<CXXDeleteExpr>, check::PostStmt<BlockExpr>, + check::PostObjCMessage, check::Location, eval::Assume> { public: MallocChecker() : II_alloca(nullptr), II_win_alloca(nullptr), II_malloc(nullptr), @@ -211,6 +204,7 @@ void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; + void checkPostStmt(const CXXBindTemporaryExpr *BTE, CheckerContext &C) const; void checkNewAllocator(const CXXNewExpr *NE, SVal Target, CheckerContext &C) const; void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const; @@ -489,7 +483,8 @@ bool IsReleased = (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()); assert(!IsReleased || - (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt))) || + (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt) || + isa<CXXBindTemporaryExpr>(Stmt))) || (!Stmt && S->getAllocationFamily() == AF_InnerBuffer)); return IsReleased; } @@ -1103,6 +1098,34 @@ processNewAllocation(NE, C, Target); } +void MallocChecker::checkPostStmt(const CXXBindTemporaryExpr *BTE, + CheckerContext &C) const { + if (const auto *CE = dyn_cast<CXXConstructExpr>(BTE->getSubExpr())) { + if (CE->getNumArgs() == 0) + return; + + // If we catch a 'CXXNewExpr' set it is released as it is temporary. + if (const auto *NE = dyn_cast<CXXNewExpr>(CE->getArg(0))) { + ProgramStateRef State = C.getState(); + Optional<SVal> RetVal = C.getSVal(NE); + + SymbolRef Sym = RetVal->getAsLocSymbol(); + assert(Sym); + + if (const RefState *RS = State->get<RegionState>(Sym)) + if (RS->isReleased()) + return; + + // Set the symbol's state to Released. + State = State->set<RegionState>( + Sym, RefState::getReleased(NE->isArray() ? AF_CXXNewArray : AF_CXXNew, + NE)); + + C.addTransition(State); + } + } +} + // Sets the extent value of the MemRegion allocated by // new expression NE to its size in Bytes. //
Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -156,21 +156,14 @@ typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo; -class MallocChecker : public Checker<check::DeadSymbols, - check::PointerEscape, - check::ConstPointerEscape, - check::PreStmt<ReturnStmt>, - check::EndFunction, - check::PreCall, - check::PostStmt<CallExpr>, - check::PostStmt<CXXNewExpr>, - check::NewAllocator, - check::PreStmt<CXXDeleteExpr>, - check::PostStmt<BlockExpr>, - check::PostObjCMessage, - check::Location, - eval::Assume> -{ +class MallocChecker + : public Checker<check::DeadSymbols, check::PointerEscape, + check::ConstPointerEscape, check::PreStmt<ReturnStmt>, + check::EndFunction, check::PreCall, + check::PostStmt<CallExpr>, check::PostStmt<CXXNewExpr>, + check::PostStmt<CXXBindTemporaryExpr>, check::NewAllocator, + check::PreStmt<CXXDeleteExpr>, check::PostStmt<BlockExpr>, + check::PostObjCMessage, check::Location, eval::Assume> { public: MallocChecker() : II_alloca(nullptr), II_win_alloca(nullptr), II_malloc(nullptr), @@ -211,6 +204,7 @@ void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; + void checkPostStmt(const CXXBindTemporaryExpr *BTE, CheckerContext &C) const; void checkNewAllocator(const CXXNewExpr *NE, SVal Target, CheckerContext &C) const; void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const; @@ -489,7 +483,8 @@ bool IsReleased = (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()); assert(!IsReleased || - (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt))) || + (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt) || + isa<CXXBindTemporaryExpr>(Stmt))) || (!Stmt && S->getAllocationFamily() == AF_InnerBuffer)); return IsReleased; } @@ -1103,6 +1098,34 @@ processNewAllocation(NE, C, Target); } +void MallocChecker::checkPostStmt(const CXXBindTemporaryExpr *BTE, + CheckerContext &C) const { + if (const auto *CE = dyn_cast<CXXConstructExpr>(BTE->getSubExpr())) { + if (CE->getNumArgs() == 0) + return; + + // If we catch a 'CXXNewExpr' set it is released as it is temporary. + if (const auto *NE = dyn_cast<CXXNewExpr>(CE->getArg(0))) { + ProgramStateRef State = C.getState(); + Optional<SVal> RetVal = C.getSVal(NE); + + SymbolRef Sym = RetVal->getAsLocSymbol(); + assert(Sym); + + if (const RefState *RS = State->get<RegionState>(Sym)) + if (RS->isReleased()) + return; + + // Set the symbol's state to Released. + State = State->set<RegionState>( + Sym, RefState::getReleased(NE->isArray() ? AF_CXXNewArray : AF_CXXNew, + NE)); + + C.addTransition(State); + } + } +} + // Sets the extent value of the MemRegion allocated by // new expression NE to its size in Bytes. //
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits