28class UncountedCallArgsChecker
29 :
public Checker<check::ASTDecl<TranslationUnitDecl>> {
31 "Uncounted call argument for a raw pointer/reference parameter",
32 "WebKit coding guidelines"};
47 const UncountedCallArgsChecker *
Checker;
48 explicit LocalVisitor(
const UncountedCallArgsChecker *
Checker)
53 bool shouldVisitTemplateInstantiations()
const {
return true; }
54 bool shouldVisitImplicitCode()
const {
return false; }
63 bool VisitCallExpr(
const CallExpr *CE) {
69 LocalVisitor visitor(
this);
73 void visitCallExpr(
const CallExpr *CE)
const {
74 if (shouldSkipCall(CE))
80 unsigned ArgIdx = isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
82 if (
auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE)) {
83 if (
auto *MD = MemberCallExpr->getMethodDecl()) {
85 if (name ==
"ref" || name ==
"deref")
88 auto *
E = MemberCallExpr->getImplicitObjectArgument();
89 QualType ArgType = MemberCallExpr->getObjectType();
90 std::optional<bool> IsUncounted =
92 if (IsUncounted && *IsUncounted && !isPtrOriginSafe(
E))
96 for (
auto P = F->param_begin();
101 P < F->param_end() && ArgIdx < CE->getNumArgs(); ++
P, ++ArgIdx) {
106 const auto *ArgType = (*P)->getType().getTypePtrOrNull();
112 if (!IsUncounted || !(*IsUncounted))
115 const auto *Arg = CE->
getArg(ArgIdx);
117 if (
auto *defaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
118 Arg = defaultArg->getExpr();
120 if (isPtrOriginSafe(Arg))
128 bool isPtrOriginSafe(
const Expr *Arg)
const {
133 if (isa<CXXNullPtrLiteralExpr>(ArgOrigin)) {
137 if (isa<IntegerLiteral>(ArgOrigin)) {
148 bool shouldSkipCall(
const CallExpr *CE)
const {
162 if (
auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
164 if (MemberOp->getOperator() ==
166 auto *callee = MemberOp->getDirectCallee();
167 if (
auto *calleeDecl = dyn_cast<CXXMethodDecl>(callee)) {
174 if (MemberOp->isAssignmentOp())
181 if (isMethodOnWTFContainerType(Callee))
184 auto overloadedOperatorType =
Callee->getOverloadedOperator();
185 if (overloadedOperatorType == OO_EqualEqual ||
186 overloadedOperatorType == OO_ExclaimEqual ||
187 overloadedOperatorType == OO_LessEqual ||
188 overloadedOperatorType == OO_GreaterEqual ||
189 overloadedOperatorType == OO_Spaceship ||
190 overloadedOperatorType == OO_AmpAmp ||
191 overloadedOperatorType == OO_PipePipe)
198 if (name ==
"adoptRef" || name ==
"getPtr" || name ==
"WeakPtr" ||
199 name ==
"dynamicDowncast" || name ==
"downcast" ||
200 name ==
"checkedDowncast" || name ==
"uncheckedDowncast" ||
201 name ==
"bitwise_cast" || name ==
"is" || name ==
"equal" ||
202 name ==
"hash" || name ==
"isType" ||
204 name ==
"equalIgnoringASCIICase" ||
205 name ==
"equalIgnoringASCIICaseCommon" ||
206 name ==
"equalIgnoringNullity" || name ==
"toString")
213 if (!isa<CXXMethodDecl>(
Decl))
215 auto *ClassDecl =
Decl->getParent();
216 if (!ClassDecl || !isa<CXXRecordDecl>(ClassDecl))
219 auto *NsDecl = ClassDecl->getParent();
220 if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
225 StringRef ClsName = ClsNameStr;
228 return NamespaceName ==
"WTF" &&
229 (MethodName ==
"find" || MethodName ==
"findIf" ||
230 MethodName ==
"reverseFind" || MethodName ==
"reverseFindIf" ||
231 MethodName ==
"findIgnoringASCIICase" || MethodName ==
"get" ||
232 MethodName ==
"inlineGet" || MethodName ==
"contains" ||
233 MethodName ==
"containsIf" ||
234 MethodName ==
"containsIgnoringASCIICase" ||
235 MethodName ==
"startsWith" || MethodName ==
"endsWith" ||
236 MethodName ==
"startsWithIgnoringASCIICase" ||
237 MethodName ==
"endsWithIgnoringASCIICase" ||
238 MethodName ==
"substring") &&
239 (ClsName.ends_with(
"Vector") || ClsName.ends_with(
"Set") ||
240 ClsName.ends_with(
"Map") || ClsName ==
"StringImpl" ||
241 ClsName.ends_with(
"String"));
248 llvm::raw_svector_ostream Os(Buf);
251 Os <<
"Call argument";
252 if (!paramName.empty()) {
253 Os <<
" for parameter ";
256 Os <<
" is uncounted and unsafe.";
263 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
268 void reportBugOnThis(
const Expr *CallArg)
const {
274 auto Report = std::make_unique<BasicBugReport>(
275 Bug,
"Call argument for 'this' parameter is uncounted and unsafe.",
287bool ento::shouldRegisterUncountedCallArgsChecker(
const CheckerManager &) {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Declaration of a class template.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
Represents a parameter to a function.
A (possibly-)qualified type.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Encodes a location in the source.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
The top declaration context.
An inter-procedural analysis facility that detects functions with "trivial" behavior with respect to ...
bool isTrivial(const Decl *D) const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
The JSON file list parser is used to communicate input to InstallAPI.
std::optional< bool > isUncountedPtr(const Type *T)
bool isCtorOfRefCounted(const clang::FunctionDecl *F)
std::optional< bool > isUncounted(const CXXRecordDecl *Class)
void printQuotedQualifiedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
bool isASafeCallArg(const Expr *E)
For E referring to a ref-countable/-counted pointer/reference we return whether it's a safe call argu...
bool isRefCounted(const CXXRecordDecl *R)
bool isRefType(const std::string &Name)
bool tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj, std::function< bool(const clang::Expr *, bool)> callback)
This function de-facto defines a set of transformations that we consider safe (in heuristical sense).
std::string safeGetName(const T *ASTNode)