Ok, I see, I wrongly used to think of MallockChecker as about more
general checker then it really is. If to consider
CK_MismatchedDeallocatorChecker an exception, then all other checks
appear to be similar for a family and there are always two types of
checkers responsible for a family: a leaks checker and a checker
responsible for everything else. An additional bool parameter to
getCheckIfTracked() is sufficient in this case.
Reverted an enhancement at r229593, additional cleanup at r231548
Attach is the patch that adds an additional parameter to
getCheckIfTracked(), please review!
Anton,
I am not convinced. Please, revert the patch until we agree on what is
the right thing to do here.
More comments below.
On Mar 6, 2015, at 7:03 AM, Anton Yartsev <[email protected]
<mailto:[email protected]>> wrote:
On 06.03.2015 8:55, Anna Zaks wrote:
On Mar 5, 2015, at 5:37 PM, Anton Yartsev <[email protected]
<mailto:[email protected]>> wrote:
On 05.03.2015 21:39, Anna Zaks wrote:
On Feb 17, 2015, at 4:39 PM, Anton Yartsev
<[email protected] <mailto:[email protected]>> wrote:
Author: ayartsev
Date: Tue Feb 17 18:39:06 2015
New Revision: 229593
URL: http://llvm.org/viewvc/llvm-project?rev=229593&view=rev
Log:
[analyzer] Refactoring: clarified the way the proper check kind
is chosen.
Anton, this doesn’t look like a simple refactoring. Also, the new
API looks more confusing and difficult to use.
autoCheckKind = getCheckIfTracked(C, DeallocExpr);
vs
autoCheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
CK_MallocPessimistic,
CK_NewDeleteChecker),
C, DeallocExpr);
Instead of checking if any of our checkers handle a specific
family and returning the one that does, we now have to pass in the
list of checkers we are interested in. Can you explain why this is
needed?
I think this is a step in the wrong direction. My understanding is
that some of the methods only work for specific checkers
(regardless of the family being processed). Therefore, they
returned early in case they were called on checkers, where they
are useless. Looks like you are trying to fold that check into the
API family check, which is unrelated. Though, I might be missing
something..
Hi Anna!)
Here is my very high level description on how this works:
When reporting a bug, we call getCheckIfTracked(..) to find out
which check should be used to report it. (We might ocasionaly use
the method in some other context as well.) In most cases, we expect
only one of the checkers to track the symbol.
The old getCheckIfTracked() has two drawbacks: first, it does not
considered CK_MismatchedDeallocatorChecker and
CK_NewDeleteLeaksChecker checkers.
I don’t think it should work with CK_MismatchedDeallocatorChecker as
it covers the case of mixed families. How is this API useful in that
case? In your implementation, you always return it back.
The checker is returned back if the family of the given symbol fits
the checker, otherwise no checker is returned.
I am talking about CK_MismatchedDeallocatorChecker here. This method
does not provide us with useful information when processing mismatched
deallocators. Don't try to overgeneralize and alter the API to fit in
this check. It does not fit by design.
+ if (CK == CK_MismatchedDeallocatorChecker)
+ return CK;
We can discuss the specifics of CK_NewDeleteLeaksChecker in more
detail, but my understanding is that the reason why it does not work
is that we want to be able to turn the DeleteLeaks off separately
because it could lead to false positives. Hopefully, that is a
transitional limitation, so we should not design the malloc checker
around that.
As you correctly described 'we call getCheckIfTracked(..) to find out
which check should be used to report the bug'. Old implementation
just returned CK_MallockChecker for AF_Malloc family and
CK_NewDeleteChecker for AF_CXXNew/AF_CXXNewArray families which is
correct only in the case, when CK_MallockChecker and
CK_NewDeleteChecker are 'on' and all other are 'off'.
I agree, most reports belong to CK_MallockChecker and
CK_NewDeleteChecker checkers, but why not to make
getCheckIfTracked(..) return the proper check in all cases?
What is the "proper" check? I believe this method should return a
single matched check and not depend on the order of checks in the
input array, which is confusing and error prone.
For that we need to decide what to do in cases where there is no
1-to-1 correspondence between families and checkers. There are 2 cases:
- CK_MismatchedDeallocatorChecker // It is not useful to have the
method cover this. I think mismatched deallocator checking should be
special cased. (We don't have to call this method every time a bug is
reported.)
- Leaks // We may want to have leaks be reported by separate checks.
For that, we can pass a boolean to the getCheckIfTracked to specify if
we want leak check or a regular check. It would return MallocChecker
for malloc family since the leaks check is not separate there.
Consider the use of the new API, for example, in ReportFreeAlloca().
However much new checks/checkers/families we add the new API will
remain usable.
Concerning the CK_NewDeleteLeaksChecker checker, currently
CK_NewDeleteLeaksChecker is considered a part of CK_NewDelete
checker. Technically it is implemented as follows: if
CK_NewDeleteLeaksChecker is 'on' then CK_NewDelete is being
automatically turned 'on'. If this link is broken some day returning
CK_NewDelete by an old API will be incorrect.
On the other hand, we should design this to be easily extendable to
handle more families, and this patch hampers that. You’d need to
grow the list of checkers you send to each call to this function for
every new family. Ex: KeychainAPI checker should be folded into this.
You always send the list of checks responsible for the particular
given error and getCheckIfTracked(..) returns (if any) one that is
responsible for the family of the given slmbol/region. If your report
is just for KeychainAPI checker then you send only this checker and
you'll get it back if the family of the given symbol is tracked by
the checker, otherwise no checker is returned. All other calls will
remain unmodified.
Most calls will need to be modified when this is extended to handle
more API families.
In this patch, you call the method 7 times. In 5 out of 7 calls you
pass the same list of 3 regular checkers: CK_MallocOptimistic,
CK_MallocPessimistic, CK_NewDeleteChecker. In two cases, you special
case: once for leaks and once for reporting double delete. Every time
a new family is added, we would need to add it's check to all of the 5
call sites.
The second is that there is, in fact, unable to customize the set
of checkers getCheckIfTracked() chooses from. For each family there
are several checkers responsible for it. Without providing the set
of checkers of interest getCheckIfTracked() is ugly in use.
Consider changes in MallocChecker::reportLeak() below - the removed
block of code (marked start and end of the code with "---------"
for you). This piece was just added for situations (hard to guess
looking at the code), when, for example, CK_MallocPessimistic and
CK_NewDelete are 'on' and CK_NewDeleteLeaksChecker is 'off' and in
this case getCheckIfTracked() returns CK_NewDelete checker as the
checker, responsible for the AF_CXXNew/AF_CXXNewArray families. The
code looks confusing in consideration of the fact that we rejected
all the checkers responsible for AF_CXXNew/AF_CXXNewArray families,
except CK_NewDeleteLeaksChecker, by writing 'if (... &&
!ChecksEnabled[CK_NewDeleteLeaksChecker]) return;' at the beginning
of the method. In the current implementation getCheckIfTracked()
returns only the checkers it was restricted for.
I think it’s better to have one ugly spot that handles a corner case
such as DeleteLeaks. (If we want all leak checks to be separate, we
can design a solution for that as well. Maybe a boolean argument is
passed in whenever we are processing a leak?)
The second bonus of the current implementation is that it gets us
rid of the check for specific checkers at the beginning.
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=229593&r1=229592&r2=229593&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
(original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Tue
Feb 17 18:39:06 2015
@@ -184,6 +184,7 @@ public:
DefaultBool ChecksEnabled[CK_NumCheckKinds];
CheckName CheckNames[CK_NumCheckKinds];
+ typedef llvm::SmallVector<CheckKind, CK_NumCheckKinds> 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<CheckKind> getCheckIfTracked(AllocationFamily Family)
const;
- Optional<CheckKind> getCheckIfTracked(CheckerContext &C,
+ /// Looks through incoming CheckKind(s) and returns the kind
of the checker
+ /// responsible for this family/call/symbol.
Is it possible for more than one checker to be responsible for the
same family?
Yes, it is possible, e.g. NewDelete, NewDeleteLeaks and
MismatchedDeallocator are responsible for AF_CXXNew/AF_CXXNewArray
families.
NewDeleteLeaks and MismatchedDeallocator are the only non-conformant
checks, correct?
My understanding is that the family just tells, which API was used to
allocate the memory (Unix, c++, etc), while the checkers are
separated from each other not only by the family they process, but
also by functionality.
The idea is to generalize this as much as possible, so that you could
add more families and share the functionality.
The family don't necessarily have to be handled by the particular
sole checker. Currently we have:
AF_Malloc, AF_Alloca, AF_IfNameIndex: CK_MallocChecker,
CK_MismatchedDeallocatorChecker
AF_CXXNew, AF_CXXNewArray: CK_NewDeleteChecker,
CK_NewDeleteLeaksChecker, CK_MismatchedDeallocatorChecker
This is the view we should have:
Family | Regular Checker | Leaks checker
AF_Malloc, AF_Alloca, AF_IfNameIndex: CK_MallocChecker,
CK_MallocChecker
AF_CXXNew, AF_CXXNewArray: CK_NewDeleteChecker,
CK_NewDeleteLeaksChecker
New family CK_NewFamily , CK_NewFamilyLeaks
CK_MismatchedDeallocatorChecker does not belong to a family. It's
point is to find family mismatches.
This returns the first checker that handles the family from the
given list.
Yes, that is how getCheckIfTracked() was designed before, but the
order of the checkers was hardcoded:
if (ChecksEnabled[CK_MallocOptimistic]) {
return CK_MallocOptimistic;
} else if (ChecksEnabled[CK_MallocPessimistic]) {
return CK_MallocPessimistic;
}
Now it is possible to customize the order in which the checkers are
checked and returned.
+ Optional<CheckKind> getCheckIfTracked(CheckKind CK,
+ AllocationFamily Family)
const;
This always returns either the input checker or an empty one.
Looks like it should just return a bool...
I left this to be consistent with other overloads, and also the
name of the method implies that the checker is returned. Do you
think the return value should be changed to bool? And, if yes, do
you think the method should be renamed?
+ Optional<CheckKind> getCheckIfTracked(CKVecTy CKVec,
Hard to tell what this argument is from documentation/name.
I'll address this!
+ AllocationFamily Family)
const;
+ Optional<CheckKind> getCheckIfTracked(CKVecTy CKVec,
CheckerContext &C,
const Stmt
*AllocDeallocStmt) const;
- Optional<CheckKind> getCheckIfTracked(CheckerContext &C,
SymbolRef Sym) const;
+ Optional<CheckKind> 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::FreeMemAu
}
Optional<MallocChecker::CheckKind>
-MallocChecker::getCheckIfTracked(AllocationFamily Family) const {
+MallocChecker::getCheckIfTracked(MallocChecker::CheckKind CK,
+ AllocationFamily Family) const {
+
+ if (CK == CK_NumCheckKinds || !ChecksEnabled[CK])
+ return Optional<MallocChecker::CheckKind>();
+
+ // 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<MallocChecker::CheckKind>();
}
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<MallocChecker::CheckKind>();
}
@@ -1335,18 +1351,45 @@ MallocChecker::getCheckIfTracked(Allocat
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::CheckKind>
-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<MallocChecker::CheckKind>();
}
Optional<MallocChecker::CheckKind>
-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::CheckKind>
+MallocChecker::getCheckIfTracked(CKVecTy CKVec, CheckerContext &C,
+ SymbolRef Sym) const {
const RefState *RS = C.getState()->get<RegionState>(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(Checke
SourceRange Range,
const Expr *DeallocExpr) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
- !ChecksEnabled[CK_NewDeleteChecker])
- return;
-
- Optional<MallocChecker::CheckKind> 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(Che
SourceRange Range, const
Expr *DeallocExpr,
const Expr *AllocExpr) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
- !ChecksEnabled[CK_NewDeleteChecker])
- return;
- Optional<MallocChecker::CheckKind> 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(Che
void MallocChecker::ReportUseAfterFree(CheckerContext &C,
SourceRange Range,
SymbolRef Sym) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
- !ChecksEnabled[CK_NewDeleteChecker])
- return;
-
- Optional<MallocChecker::CheckKind> 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(Che
bool Released, SymbolRef Sym,
SymbolRef PrevSym) const {
- if (!ChecksEnabled[CK_MallocOptimistic] &&
- !ChecksEnabled[CK_MallocPessimistic] &&
- !ChecksEnabled[CK_NewDeleteChecker])
- return;
-
- Optional<MallocChecker::CheckKind> 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(Che
void MallocChecker::ReportDoubleDelete(CheckerContext &C,
SymbolRef Sym) const {
- if (!ChecksEnabled[CK_NewDeleteChecker])
- return;
-
- Optional<MallocChecker::CheckKind> CheckKind =
getCheckIfTracked(C, Sym);
+ auto CheckKind =
getCheckIfTracked(MakeVecFromCK(CK_NewDeleteChecker),
+ C, Sym);
Not sure why we cannot reuse ReportDoubleFree here...
I'll meditate on this.
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 E
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<RegionState>(Sym);
- assert(RS && "cannot leak an untracked symbol");
- AllocationFamily Family = RS->getAllocationFamily();
- Optional<MallocChecker::CheckKind> CheckKind =
getCheckIfTracked(Family);
+ auto CheckKind =
getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
+
CK_MallocPessimistic,
+
CK_NewDeleteLeaksChecker),
This should ask getCheckIfTracked() return a "leak" check. This would
also make it easy to allow malloc leaks to be turned on/off separately.
+ 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_ostre
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I
!= E; ++I) {
const RefState *RefS = State->get<RegionState>(I.getKey());
AllocationFamily Family = RefS->getAllocationFamily();
- Optional<MallocChecker::CheckKind> CheckKind =
getCheckIfTracked(Family);
-
+ auto CheckKind =
getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
+
CK_MallocPessimistic,
+
CK_NewDeleteChecker),
+ Family);
This is a generic printing routine, which is used for debugging.
Why is this restricted to the specific checkers?
This particular branch handles leak detecting checkers which are
CK_MallocOptimistic, CK_MallocPessimistic, and CK_NewDeleteChecker.
This is wrong. We've disabled printing for several checks.
I.getKey()->dumpToStream(Out);
Out << " : ";
I.getData().dump(Out);
_______________________________________________
cfe-commits mailing list
[email protected] <mailto:[email protected]>
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
--
Anton
--
Anton
--
Anton
Index: MallocChecker.cpp
===================================================================
--- MallocChecker.cpp (revision 231548)
+++ MallocChecker.cpp (working copy)
@@ -334,10 +334,13 @@
/// 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<CheckKind> getCheckIfTracked(AllocationFamily Family) const;
+ Optional<CheckKind> getCheckIfTracked(AllocationFamily Family,
+ Optional<bool> IsALeakCheck) const;
Optional<CheckKind> getCheckIfTracked(CheckerContext &C,
- const Stmt *AllocDeallocStmt) const;
- Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const;
+ const Stmt *AllocDeallocStmt,
+ Optional<bool> IsALeakCheck) const;
+ Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
+ Optional<bool> IsALeakCheck) const;
///@}
static bool SummarizeValue(raw_ostream &os, SVal V);
static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
@@ -358,6 +361,9 @@
void ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const;
+ void ReportUseZeroAllocated(CheckerContext &C, SourceRange Range,
+ SymbolRef Sym) const;
+
/// Find the location of the allocation for Sym on the path leading to the
/// exploded node N.
LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
@@ -1342,7 +1348,8 @@
}
Optional<MallocChecker::CheckKind>
-MallocChecker::getCheckIfTracked(AllocationFamily Family) const {
+MallocChecker::getCheckIfTracked(AllocationFamily Family,
+ Optional<bool> IsALeakCheck) const {
switch (Family) {
case AF_Malloc:
case AF_Alloca:
@@ -1354,9 +1361,14 @@
}
case AF_CXXNew:
case AF_CXXNewArray: {
- if (ChecksEnabled[CK_NewDeleteChecker]) {
- return CK_NewDeleteChecker;
+ if (!IsALeakCheck.hasValue() || !(*IsALeakCheck)) {
+ if (ChecksEnabled[CK_NewDeleteChecker])
+ return CK_NewDeleteChecker;
}
+ if (!IsALeakCheck.hasValue() || *IsALeakCheck) {
+ if (ChecksEnabled[CK_NewDeleteLeaksChecker])
+ return CK_NewDeleteLeaksChecker;
+ }
return Optional<MallocChecker::CheckKind>();
}
case AF_None: {
@@ -1368,16 +1380,18 @@
Optional<MallocChecker::CheckKind>
MallocChecker::getCheckIfTracked(CheckerContext &C,
- const Stmt *AllocDeallocStmt) const {
- return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt));
+ const Stmt *AllocDeallocStmt,
+ Optional<bool> IsALeakCheck) const {
+ return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
+ IsALeakCheck);
}
Optional<MallocChecker::CheckKind>
-MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym) const {
-
+MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
+ Optional<bool> IsALeakCheck) const {
const RefState *RS = C.getState()->get<RegionState>(Sym);
assert(RS);
- return getCheckIfTracked(RS->getAllocationFamily());
+ return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
}
bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
@@ -1476,7 +1490,7 @@
return;
Optional<MallocChecker::CheckKind> CheckKind =
- getCheckIfTracked(C, DeallocExpr);
+ getCheckIfTracked(C, DeallocExpr, false);
if (!CheckKind.hasValue())
return;
@@ -1603,7 +1617,7 @@
return;
Optional<MallocChecker::CheckKind> CheckKind =
- getCheckIfTracked(C, AllocExpr);
+ getCheckIfTracked(C, AllocExpr, false);
if (!CheckKind.hasValue())
return;
@@ -1657,7 +1671,9 @@
!ChecksEnabled[CK_NewDeleteChecker])
return;
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(C, Sym, false);
+
if (!CheckKind.hasValue())
return;
@@ -1684,7 +1700,9 @@
!ChecksEnabled[CK_NewDeleteChecker])
return;
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(C, Sym, false);
+
if (!CheckKind.hasValue())
return;
@@ -1712,7 +1730,9 @@
if (!ChecksEnabled[CK_NewDeleteChecker])
return;
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(C, Sym, false);
+
if (!CheckKind.hasValue())
return;
@@ -1906,17 +1926,14 @@
const RefState *RS = C.getState()->get<RegionState>(Sym);
assert(RS && "cannot leak an untracked symbol");
AllocationFamily Family = RS->getAllocationFamily();
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
- if (!CheckKind.hasValue())
+
+ if (Family == AF_Alloca)
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;
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(Family, true);
- if (RS->getAllocationFamily() == AF_Alloca)
+ if (!CheckKind.hasValue())
return;
assert(N);
@@ -2528,7 +2545,8 @@
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
const RefState *RefS = State->get<RegionState>(I.getKey());
AllocationFamily Family = RefS->getAllocationFamily();
- Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
+ Optional<MallocChecker::CheckKind>
+ CheckKind = getCheckIfTracked(Family, Optional<bool>());
I.getKey()->dumpToStream(Out);
Out << " : ";
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits