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 LeakInfo; -class MallocChecker : public Checker, - check::EndFunction, - check::PreCall, - check::PostStmt, - check::PostStmt, - check::NewAllocator, - check::PreStmt, - check::PostStmt, - check::PostObjCMessage, - check::Location, - eval::Assume> -{ +class MallocChecker + : public Checker, + check::EndFunction, check::PreCall, + check::PostStmt, check::PostStmt, + check::PostStmt, check::NewAllocator, + check::PreStmt, check::PostStmt, + 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(Stmt) || isa(Stmt))) || + (Stmt && (isa(Stmt) || isa(Stmt) || + isa(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(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(CE->getArg(0))) { + ProgramStateRef State = C.getState(); + Optional RetVal = C.getSVal(NE); + + SymbolRef Sym = RetVal->getAsLocSymbol(); + assert(Sym); + + if (const RefState *RS = State->get(Sym)) + if (RS->isReleased()) + return; + + // Set the symbol's state to Released. + State = State->set( + 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. //