From: Anton Yartsev Date: Wed, 18 Feb 2015 00:39:06 +0000 (+0000) Subject: [analyzer] Refactoring: clarified the way the proper check kind is chosen. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=52d5a7bf5cc4c6967ad752ebbf181050a8bc45bb;p=clang [analyzer] Refactoring: clarified the way the proper check kind is chosen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@229593 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index d5e70e8c65..a49247bbd2 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -184,6 +184,7 @@ public: DefaultBool ChecksEnabled[CK_NumCheckKinds]; CheckName CheckNames[CK_NumCheckKinds]; + typedef llvm::SmallVector CKVecTy; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; @@ -327,12 +328,16 @@ private: ///@{ /// Tells if a given family/call/symbol is tracked by the current checker. - /// Sets CheckKind to the kind of the checker responsible for this - /// family/call/symbol. - Optional getCheckIfTracked(AllocationFamily Family) const; - Optional getCheckIfTracked(CheckerContext &C, + /// Looks through incoming CheckKind(s) and returns the kind of the checker + /// responsible for this family/call/symbol. + Optional getCheckIfTracked(CheckKind CK, + AllocationFamily Family) const; + Optional getCheckIfTracked(CKVecTy CKVec, + AllocationFamily Family) const; + Optional getCheckIfTracked(CKVecTy CKVec, CheckerContext &C, const Stmt *AllocDeallocStmt) const; - Optional getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const; + Optional getCheckIfTracked(CKVecTy CKVec, CheckerContext &C, + SymbolRef Sym) const; ///@} static bool SummarizeValue(raw_ostream &os, SVal V); static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); @@ -1310,21 +1315,32 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, } Optional -MallocChecker::getCheckIfTracked(AllocationFamily Family) const { +MallocChecker::getCheckIfTracked(MallocChecker::CheckKind CK, + AllocationFamily Family) const { + + if (CK == CK_NumCheckKinds || !ChecksEnabled[CK]) + return Optional(); + + // C/C++ checkers. + if (CK == CK_MismatchedDeallocatorChecker) + return CK; + switch (Family) { case AF_Malloc: case AF_IfNameIndex: { - if (ChecksEnabled[CK_MallocOptimistic]) { - return CK_MallocOptimistic; - } else if (ChecksEnabled[CK_MallocPessimistic]) { - return CK_MallocPessimistic; + // C checkers. + if (CK == CK_MallocOptimistic || + CK == CK_MallocPessimistic) { + return CK; } return Optional(); } case AF_CXXNew: case AF_CXXNewArray: { - if (ChecksEnabled[CK_NewDeleteChecker]) { - return CK_NewDeleteChecker; + // C++ checkers. + if (CK == CK_NewDeleteChecker || + CK == CK_NewDeleteLeaksChecker) { + return CK; } return Optional(); } @@ -1335,18 +1351,45 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family) const { llvm_unreachable("unhandled family"); } +static MallocChecker::CKVecTy MakeVecFromCK(MallocChecker::CheckKind CK1, + MallocChecker::CheckKind CK2 = MallocChecker::CK_NumCheckKinds, + MallocChecker::CheckKind CK3 = MallocChecker::CK_NumCheckKinds, + MallocChecker::CheckKind CK4 = MallocChecker::CK_NumCheckKinds) { + MallocChecker::CKVecTy CKVec; + CKVec.push_back(CK1); + if (CK2 != MallocChecker::CK_NumCheckKinds) { + CKVec.push_back(CK2); + if (CK3 != MallocChecker::CK_NumCheckKinds) { + CKVec.push_back(CK3); + if (CK4 != MallocChecker::CK_NumCheckKinds) + CKVec.push_back(CK4); + } + } + return CKVec; +} + Optional -MallocChecker::getCheckIfTracked(CheckerContext &C, - const Stmt *AllocDeallocStmt) const { - return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt)); +MallocChecker::getCheckIfTracked(CKVecTy CKVec, AllocationFamily Family) const { + for (auto CK: CKVec) { + auto RetCK = getCheckIfTracked(CK, Family); + if (RetCK.hasValue()) + return RetCK; + } + return Optional(); } Optional -MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const { +MallocChecker::getCheckIfTracked(CKVecTy CKVec, CheckerContext &C, + const Stmt *AllocDeallocStmt) const { + return getCheckIfTracked(CKVec, getAllocationFamily(C, AllocDeallocStmt)); +} +Optional +MallocChecker::getCheckIfTracked(CKVecTy CKVec, CheckerContext &C, + SymbolRef Sym) const { const RefState *RS = C.getState()->get(Sym); assert(RS); - return getCheckIfTracked(RS->getAllocationFamily()); + return getCheckIfTracked(CKVec, RS->getAllocationFamily()); } bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { @@ -1440,13 +1483,10 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range, const Expr *DeallocExpr) const { - if (!ChecksEnabled[CK_MallocOptimistic] && - !ChecksEnabled[CK_MallocPessimistic] && - !ChecksEnabled[CK_NewDeleteChecker]) - return; - - Optional CheckKind = - getCheckIfTracked(C, DeallocExpr); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteChecker), + C, DeallocExpr); if (!CheckKind.hasValue()) return; @@ -1546,13 +1586,11 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range, const Expr *DeallocExpr, const Expr *AllocExpr) const { - if (!ChecksEnabled[CK_MallocOptimistic] && - !ChecksEnabled[CK_MallocPessimistic] && - !ChecksEnabled[CK_NewDeleteChecker]) - return; - Optional CheckKind = - getCheckIfTracked(C, AllocExpr); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteChecker), + C, AllocExpr); if (!CheckKind.hasValue()) return; @@ -1602,12 +1640,10 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal, void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range, SymbolRef Sym) const { - if (!ChecksEnabled[CK_MallocOptimistic] && - !ChecksEnabled[CK_MallocPessimistic] && - !ChecksEnabled[CK_NewDeleteChecker]) - return; - - Optional CheckKind = getCheckIfTracked(C, Sym); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteChecker), + C, Sym); if (!CheckKind.hasValue()) return; @@ -1630,12 +1666,10 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released, SymbolRef Sym, SymbolRef PrevSym) const { - if (!ChecksEnabled[CK_MallocOptimistic] && - !ChecksEnabled[CK_MallocPessimistic] && - !ChecksEnabled[CK_NewDeleteChecker]) - return; - - Optional CheckKind = getCheckIfTracked(C, Sym); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteChecker), + C, Sym); if (!CheckKind.hasValue()) return; @@ -1660,13 +1694,10 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range, void MallocChecker::ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const { - if (!ChecksEnabled[CK_NewDeleteChecker]) - return; - - Optional CheckKind = getCheckIfTracked(C, Sym); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_NewDeleteChecker), + C, Sym); if (!CheckKind.hasValue()) return; - assert(*CheckKind == CK_NewDeleteChecker && "invalid check kind"); if (ExplodedNode *N = C.generateSink()) { if (!BT_DoubleDelete) @@ -1851,24 +1882,13 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const { - if (!ChecksEnabled[CK_MallocOptimistic] && - !ChecksEnabled[CK_MallocPessimistic] && - !ChecksEnabled[CK_NewDeleteLeaksChecker]) - return; - - const RefState *RS = C.getState()->get(Sym); - assert(RS && "cannot leak an untracked symbol"); - AllocationFamily Family = RS->getAllocationFamily(); - Optional CheckKind = getCheckIfTracked(Family); + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteLeaksChecker), + C, Sym); if (!CheckKind.hasValue()) return; - // Special case for new and new[]; these are controlled by a separate checker - // flag so that they can be selectively disabled. - if (Family == AF_CXXNew || Family == AF_CXXNewArray) - if (!ChecksEnabled[CK_NewDeleteLeaksChecker]) - return; - assert(N); if (!BT_Leak[*CheckKind]) { BT_Leak[*CheckKind].reset( @@ -2479,8 +2499,10 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State, for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { const RefState *RefS = State->get(I.getKey()); AllocationFamily Family = RefS->getAllocationFamily(); - Optional CheckKind = getCheckIfTracked(Family); - + auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic, + CK_MallocPessimistic, + CK_NewDeleteChecker), + Family); I.getKey()->dumpToStream(Out); Out << " : "; I.getData().dump(Out);