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; }
56 bool VisitCallExpr(
const CallExpr *CE) {
62 LocalVisitor visitor(
this);
66 void visitCallExpr(
const CallExpr *CE)
const {
67 if (shouldSkipCall(CE))
73 unsigned ArgIdx = isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
75 if (
auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE)) {
76 if (
auto *MD = MemberCallExpr->getMethodDecl()) {
78 if (name ==
"ref" || name ==
"deref")
81 auto *E = MemberCallExpr->getImplicitObjectArgument();
82 QualType ArgType = MemberCallExpr->getObjectType();
83 std::optional<bool> IsUncounted =
85 if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E))
89 for (
auto P = F->param_begin();
94 P < F->param_end() && ArgIdx < CE->getNumArgs(); ++
P, ++ArgIdx) {
99 const auto *ArgType = (*P)->getType().getTypePtrOrNull();
105 if (!IsUncounted || !(*IsUncounted))
108 const auto *Arg = CE->
getArg(ArgIdx);
110 if (
auto *defaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
111 Arg = defaultArg->getExpr();
113 if (isPtrOriginSafe(Arg))
121 bool isPtrOriginSafe(
const Expr *Arg)
const {
122 std::pair<const clang::Expr *, bool> ArgOrigin =
127 if (ArgOrigin.second)
130 if (isa<CXXNullPtrLiteralExpr>(ArgOrigin.first)) {
134 if (isa<IntegerLiteral>(ArgOrigin.first)) {
143 bool shouldSkipCall(
const CallExpr *CE)
const {
154 if (
auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
156 if (MemberOp->getOperator() ==
158 auto *callee = MemberOp->getDirectCallee();
159 if (
auto *calleeDecl = dyn_cast<CXXMethodDecl>(callee)) {
166 if (MemberOp->isAssignmentOp())
173 if (isMethodOnWTFContainerType(Callee))
176 auto overloadedOperatorType =
Callee->getOverloadedOperator();
177 if (overloadedOperatorType == OO_EqualEqual ||
178 overloadedOperatorType == OO_ExclaimEqual ||
179 overloadedOperatorType == OO_LessEqual ||
180 overloadedOperatorType == OO_GreaterEqual ||
181 overloadedOperatorType == OO_Spaceship ||
182 overloadedOperatorType == OO_AmpAmp ||
183 overloadedOperatorType == OO_PipePipe)
190 if (name ==
"adoptRef" || name ==
"getPtr" || name ==
"WeakPtr" ||
191 name ==
"dynamicDowncast" || name ==
"downcast" ||
192 name ==
"checkedDowncast" || name ==
"uncheckedDowncast" ||
193 name ==
"bitwise_cast" || name ==
"is" || name ==
"equal" ||
194 name ==
"hash" || name ==
"isType" ||
196 name ==
"equalIgnoringASCIICase" ||
197 name ==
"equalIgnoringASCIICaseCommon" ||
198 name ==
"equalIgnoringNullity" || name ==
"toString")
205 if (!isa<CXXMethodDecl>(
Decl))
207 auto *ClassDecl =
Decl->getParent();
208 if (!ClassDecl || !isa<CXXRecordDecl>(ClassDecl))
211 auto *NsDecl = ClassDecl->getParent();
212 if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
217 StringRef ClsName = ClsNameStr;
220 return NamespaceName ==
"WTF" &&
221 (MethodName ==
"find" || MethodName ==
"findIf" ||
222 MethodName ==
"reverseFind" || MethodName ==
"reverseFindIf" ||
223 MethodName ==
"get" || MethodName ==
"inlineGet" ||
224 MethodName ==
"contains" || MethodName ==
"containsIf") &&
225 (ClsName.ends_with(
"Vector") || ClsName.ends_with(
"Set") ||
226 ClsName.ends_with(
"Map"));
233 llvm::raw_svector_ostream Os(Buf);
236 Os <<
"Call argument";
237 if (!paramName.empty()) {
238 Os <<
" for parameter ";
241 Os <<
" is uncounted and unsafe.";
248 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
253 void reportBugOnThis(
const Expr *CallArg)
const {
259 auto Report = std::make_unique<BasicBugReport>(
260 Bug,
"Call argument for 'this' parameter is uncounted and unsafe.",
272bool 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.
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.
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)
std::pair< const Expr *, bool > tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj)
This function de-facto defines a set of transformations that we consider safe (in heuristical sense).
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)
std::string safeGetName(const T *ASTNode)