@@ -70,6 +70,15 @@ class UncountedCallArgsChecker
70
70
// or std::function call operator).
71
71
unsigned ArgIdx = isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
72
72
73
+ if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE)) {
74
+ auto *E = MemberCallExpr->getImplicitObjectArgument ();
75
+ auto *ArgType = MemberCallExpr->getObjectType ().getTypePtrOrNull ();
76
+ std::optional<bool > IsUncounted =
77
+ isUncounted (ArgType->getAsCXXRecordDecl ());
78
+ if (IsUncounted && *IsUncounted && !isPtrOriginSafe (E))
79
+ reportBugOnThis (E);
80
+ }
81
+
73
82
for (auto P = F->param_begin ();
74
83
// FIXME: Also check variadic function parameters.
75
84
// FIXME: Also check default function arguments. Probably a different
@@ -91,32 +100,36 @@ class UncountedCallArgsChecker
91
100
92
101
const auto *Arg = CE->getArg (ArgIdx);
93
102
94
- std::pair<const clang::Expr *, bool > ArgOrigin =
95
- tryToFindPtrOrigin (Arg, true );
96
-
97
- // Temporary ref-counted object created as part of the call argument
98
- // would outlive the call.
99
- if (ArgOrigin.second )
100
- continue ;
101
-
102
- if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first )) {
103
- // foo(nullptr)
104
- continue ;
105
- }
106
- if (isa<IntegerLiteral>(ArgOrigin.first )) {
107
- // FIXME: Check the value.
108
- // foo(NULL)
109
- continue ;
110
- }
111
-
112
- if (isASafeCallArg (ArgOrigin.first ))
103
+ if (isPtrOriginSafe (Arg))
113
104
continue ;
114
105
115
106
reportBug (Arg, *P);
116
107
}
117
108
}
118
109
}
119
110
111
+ bool isPtrOriginSafe (const Expr *Arg) const {
112
+ std::pair<const clang::Expr *, bool > ArgOrigin =
113
+ tryToFindPtrOrigin (Arg, true );
114
+
115
+ // Temporary ref-counted object created as part of the call argument
116
+ // would outlive the call.
117
+ if (ArgOrigin.second )
118
+ return true ;
119
+
120
+ if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first )) {
121
+ // foo(nullptr)
122
+ return true ;
123
+ }
124
+ if (isa<IntegerLiteral>(ArgOrigin.first )) {
125
+ // FIXME: Check the value.
126
+ // foo(NULL)
127
+ return true ;
128
+ }
129
+
130
+ return isASafeCallArg (ArgOrigin.first );
131
+ }
132
+
120
133
bool shouldSkipCall (const CallExpr *CE) const {
121
134
if (CE->getNumArgs () == 0 )
122
135
return false ;
@@ -183,6 +196,22 @@ class UncountedCallArgsChecker
183
196
Report->addRange (CallArg->getSourceRange ());
184
197
BR->emitReport (std::move (Report));
185
198
}
199
+
200
+ void reportBugOnThis (const Expr *CallArg) const {
201
+ assert (CallArg);
202
+
203
+ SmallString<100 > Buf;
204
+ llvm::raw_svector_ostream Os (Buf);
205
+
206
+ Os << " Call argument for 'this' parameter is uncounted and unsafe." ;
207
+
208
+ const SourceLocation SrcLocToReport = CallArg->getSourceRange ().getBegin ();
209
+
210
+ PathDiagnosticLocation BSLoc (SrcLocToReport, BR->getSourceManager ());
211
+ auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
212
+ Report->addRange (CallArg->getSourceRange ());
213
+ BR->emitReport (std::move (Report));
214
+ }
186
215
};
187
216
} // namespace
188
217
0 commit comments