@@ -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
@@ -94,32 +103,36 @@ class UncountedCallArgsChecker
94
103
if (auto *defaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
95
104
Arg = defaultArg->getExpr ();
96
105
97
- std::pair<const clang::Expr *, bool > ArgOrigin =
98
- tryToFindPtrOrigin (Arg, true );
99
-
100
- // Temporary ref-counted object created as part of the call argument
101
- // would outlive the call.
102
- if (ArgOrigin.second )
103
- continue ;
104
-
105
- if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first )) {
106
- // foo(nullptr)
107
- continue ;
108
- }
109
- if (isa<IntegerLiteral>(ArgOrigin.first )) {
110
- // FIXME: Check the value.
111
- // foo(NULL)
112
- continue ;
113
- }
114
-
115
- if (isASafeCallArg (ArgOrigin.first ))
106
+ if (isPtrOriginSafe (Arg))
116
107
continue ;
117
108
118
109
reportBug (Arg, *P);
119
110
}
120
111
}
121
112
}
122
113
114
+ bool isPtrOriginSafe (const Expr *Arg) const {
115
+ std::pair<const clang::Expr *, bool > ArgOrigin =
116
+ tryToFindPtrOrigin (Arg, true );
117
+
118
+ // Temporary ref-counted object created as part of the call argument
119
+ // would outlive the call.
120
+ if (ArgOrigin.second )
121
+ return true ;
122
+
123
+ if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first )) {
124
+ // foo(nullptr)
125
+ return true ;
126
+ }
127
+ if (isa<IntegerLiteral>(ArgOrigin.first )) {
128
+ // FIXME: Check the value.
129
+ // foo(NULL)
130
+ return true ;
131
+ }
132
+
133
+ return isASafeCallArg (ArgOrigin.first );
134
+ }
135
+
123
136
bool shouldSkipCall (const CallExpr *CE) const {
124
137
if (CE->getNumArgs () == 0 )
125
138
return false ;
@@ -196,6 +209,22 @@ class UncountedCallArgsChecker
196
209
Report->addRange (CallArg->getSourceRange ());
197
210
BR->emitReport (std::move (Report));
198
211
}
212
+
213
+ void reportBugOnThis (const Expr *CallArg) const {
214
+ assert (CallArg);
215
+
216
+ SmallString<100 > Buf;
217
+ llvm::raw_svector_ostream Os (Buf);
218
+
219
+ Os << " Call argument for 'this' parameter is uncounted and unsafe." ;
220
+
221
+ const SourceLocation SrcLocToReport = CallArg->getSourceRange ().getBegin ();
222
+
223
+ PathDiagnosticLocation BSLoc (SrcLocToReport, BR->getSourceManager ());
224
+ auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
225
+ Report->addRange (CallArg->getSourceRange ());
226
+ BR->emitReport (std::move (Report));
227
+ }
199
228
};
200
229
} // namespace
201
230
0 commit comments