@@ -103,14 +103,46 @@ using namespace std::placeholders;
103
103
namespace {
104
104
105
105
// Used to check correspondence between allocators and deallocators.
106
- enum AllocationFamily {
106
+ enum AllocationFamilyKind {
107
107
AF_None,
108
108
AF_Malloc,
109
109
AF_CXXNew,
110
110
AF_CXXNewArray,
111
111
AF_IfNameIndex,
112
112
AF_Alloca,
113
- AF_InnerBuffer
113
+ AF_InnerBuffer,
114
+ AF_Custom,
115
+ };
116
+
117
+ class AllocationFamily {
118
+ public:
119
+ AllocationFamily (AllocationFamilyKind kind,
120
+ std::optional<StringRef> name = std::nullopt)
121
+ : _kind(kind), _customName(name) {
122
+ assert (kind != AF_Custom || name != std::nullopt);
123
+ }
124
+
125
+ bool operator ==(const AllocationFamily &Other) const {
126
+ if (Other.kind () == this ->kind ()) {
127
+ return this ->kind () == AF_Custom ? this ->_customName == Other._customName
128
+ : true ;
129
+ } else {
130
+ return false ;
131
+ }
132
+ }
133
+
134
+ bool operator ==(const AllocationFamilyKind &kind) {
135
+ return this ->kind () == kind;
136
+ }
137
+
138
+ bool operator !=(const AllocationFamilyKind &kind) { return !(*this == kind); }
139
+
140
+ std::optional<StringRef> name () const { return _customName; }
141
+ AllocationFamilyKind kind () const { return _kind; }
142
+
143
+ private:
144
+ AllocationFamilyKind _kind;
145
+ std::optional<StringRef> _customName;
114
146
};
115
147
116
148
} // end of anonymous namespace
@@ -194,7 +226,7 @@ class RefState {
194
226
void Profile (llvm::FoldingSetNodeID &ID) const {
195
227
ID.AddInteger (K);
196
228
ID.AddPointer (S);
197
- ID.AddInteger (Family);
229
+ ID.AddInteger (Family. kind () );
198
230
}
199
231
200
232
LLVM_DUMP_METHOD void dump (raw_ostream &OS) const {
@@ -1918,26 +1950,52 @@ static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E) {
1918
1950
1919
1951
static void printExpectedAllocName (raw_ostream &os, AllocationFamily Family) {
1920
1952
1921
- switch (Family) {
1922
- case AF_Malloc: os << " malloc()" ; return ;
1923
- case AF_CXXNew: os << " 'new'" ; return ;
1924
- case AF_CXXNewArray: os << " 'new[]'" ; return ;
1925
- case AF_IfNameIndex: os << " 'if_nameindex()'" ; return ;
1926
- case AF_InnerBuffer: os << " container-specific allocator" ; return ;
1927
- case AF_Alloca:
1928
- case AF_None: llvm_unreachable (" not a deallocation expression" );
1953
+ switch (Family.kind ()) {
1954
+ case AF_Malloc:
1955
+ os << " malloc()" ;
1956
+ return ;
1957
+ case AF_CXXNew:
1958
+ os << " 'new'" ;
1959
+ return ;
1960
+ case AF_CXXNewArray:
1961
+ os << " 'new[]'" ;
1962
+ return ;
1963
+ case AF_IfNameIndex:
1964
+ os << " 'if_nameindex()'" ;
1965
+ return ;
1966
+ case AF_InnerBuffer:
1967
+ os << " container-specific allocator" ;
1968
+ return ;
1969
+ case AF_Alloca:
1970
+ case AF_None:
1971
+ llvm_unreachable (" not a deallocation expression" );
1972
+ case AF_Custom:
1973
+ llvm_unreachable (" not a deallocation expression" );
1929
1974
}
1930
1975
}
1931
1976
1932
1977
static void printExpectedDeallocName (raw_ostream &os, AllocationFamily Family) {
1933
- switch (Family) {
1934
- case AF_Malloc: os << " free()" ; return ;
1935
- case AF_CXXNew: os << " 'delete'" ; return ;
1936
- case AF_CXXNewArray: os << " 'delete[]'" ; return ;
1937
- case AF_IfNameIndex: os << " 'if_freenameindex()'" ; return ;
1938
- case AF_InnerBuffer: os << " container-specific deallocator" ; return ;
1939
- case AF_Alloca:
1940
- case AF_None: llvm_unreachable (" suspicious argument" );
1978
+ switch (Family.kind ()) {
1979
+ case AF_Malloc:
1980
+ os << " free()" ;
1981
+ return ;
1982
+ case AF_CXXNew:
1983
+ os << " 'delete'" ;
1984
+ return ;
1985
+ case AF_CXXNewArray:
1986
+ os << " 'delete[]'" ;
1987
+ return ;
1988
+ case AF_IfNameIndex:
1989
+ os << " 'if_freenameindex()'" ;
1990
+ return ;
1991
+ case AF_InnerBuffer:
1992
+ os << " container-specific deallocator" ;
1993
+ return ;
1994
+ case AF_Alloca:
1995
+ case AF_None:
1996
+ llvm_unreachable (" suspicious argument" );
1997
+ case AF_Custom:
1998
+ llvm_unreachable (" suspicious argument" );
1941
1999
}
1942
2000
}
1943
2001
@@ -2119,7 +2177,7 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
2119
2177
std::optional<MallocChecker::CheckKind>
2120
2178
MallocChecker::getCheckIfTracked (AllocationFamily Family,
2121
2179
bool IsALeakCheck) const {
2122
- switch (Family) {
2180
+ switch (Family. kind () ) {
2123
2181
case AF_Malloc:
2124
2182
case AF_Alloca:
2125
2183
case AF_IfNameIndex: {
@@ -2144,6 +2202,7 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
2144
2202
return CK_InnerPointerChecker;
2145
2203
return std::nullopt;
2146
2204
}
2205
+ case AF_Custom:
2147
2206
case AF_None: {
2148
2207
llvm_unreachable (" no family" );
2149
2208
}
@@ -3483,53 +3542,54 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
3483
3542
Sym, " Returned allocated memory" );
3484
3543
} else if (isReleased (RSCurr, RSPrev, S)) {
3485
3544
const auto Family = RSCurr->getAllocationFamily ();
3486
- switch (Family) {
3487
- case AF_Alloca:
3488
- case AF_Malloc:
3489
- case AF_CXXNew:
3490
- case AF_CXXNewArray:
3491
- case AF_IfNameIndex:
3492
- Msg = " Memory is released" ;
3545
+ switch (Family.kind ()) {
3546
+ case AF_Alloca:
3547
+ case AF_Malloc:
3548
+ case AF_CXXNew:
3549
+ case AF_CXXNewArray:
3550
+ case AF_IfNameIndex:
3551
+ Msg = " Memory is released" ;
3552
+ StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3553
+ Sym, " Returning; memory was released" );
3554
+ break ;
3555
+ case AF_InnerBuffer: {
3556
+ const MemRegion *ObjRegion =
3557
+ allocation_state::getContainerObjRegion (statePrev, Sym);
3558
+ const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
3559
+ QualType ObjTy = TypedRegion->getValueType ();
3560
+ OS << " Inner buffer of '" << ObjTy << " ' " ;
3561
+
3562
+ if (N->getLocation ().getKind () == ProgramPoint::PostImplicitCallKind) {
3563
+ OS << " deallocated by call to destructor" ;
3493
3564
StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3494
- Sym, " Returning; memory was released" );
3495
- break ;
3496
- case AF_InnerBuffer: {
3497
- const MemRegion *ObjRegion =
3498
- allocation_state::getContainerObjRegion (statePrev, Sym);
3499
- const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
3500
- QualType ObjTy = TypedRegion->getValueType ();
3501
- OS << " Inner buffer of '" << ObjTy << " ' " ;
3502
-
3503
- if (N->getLocation ().getKind () == ProgramPoint::PostImplicitCallKind) {
3504
- OS << " deallocated by call to destructor" ;
3505
- StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3506
- Sym, " Returning; inner buffer was deallocated" );
3507
- } else {
3508
- OS << " reallocated by call to '" ;
3509
- const Stmt *S = RSCurr->getStmt ();
3510
- if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
3511
- OS << MemCallE->getMethodDecl ()->getDeclName ();
3512
- } else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
3513
- OS << OpCallE->getDirectCallee ()->getDeclName ();
3514
- } else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
3515
- auto &CEMgr = BRC.getStateManager ().getCallEventManager ();
3516
- CallEventRef<> Call =
3517
- CEMgr.getSimpleCall (CallE, state, CurrentLC, {nullptr , 0 });
3518
- if (const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl ()))
3519
- OS << D->getDeclName ();
3520
- else
3521
- OS << " unknown" ;
3522
- }
3523
- OS << " '" ;
3524
- StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3525
- Sym, " Returning; inner buffer was reallocated" );
3565
+ Sym, " Returning; inner buffer was deallocated" );
3566
+ } else {
3567
+ OS << " reallocated by call to '" ;
3568
+ const Stmt *S = RSCurr->getStmt ();
3569
+ if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
3570
+ OS << MemCallE->getMethodDecl ()->getDeclName ();
3571
+ } else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
3572
+ OS << OpCallE->getDirectCallee ()->getDeclName ();
3573
+ } else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
3574
+ auto &CEMgr = BRC.getStateManager ().getCallEventManager ();
3575
+ CallEventRef<> Call =
3576
+ CEMgr.getSimpleCall (CallE, state, CurrentLC, {nullptr , 0 });
3577
+ if (const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl ()))
3578
+ OS << D->getDeclName ();
3579
+ else
3580
+ OS << " unknown" ;
3526
3581
}
3527
- Msg = OS.str ();
3528
- break ;
3582
+ OS << " '" ;
3583
+ StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3584
+ Sym, " Returning; inner buffer was reallocated" );
3585
+ }
3586
+ Msg = OS.str ();
3587
+ break ;
3529
3588
}
3589
+ case AF_Custom:
3530
3590
case AF_None:
3531
3591
llvm_unreachable (" Unhandled allocation family!" );
3532
- }
3592
+ }
3533
3593
3534
3594
// See if we're releasing memory while inlining a destructor
3535
3595
// (or one of its callees). This turns on various common
0 commit comments