clang 23.0.0git
RawPtrRefCallArgsChecker.cpp
Go to the documentation of this file.
1//=======- RawPtrRefCallArgsChecker.cpp --------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ASTUtils.h"
10#include "DiagOutputUtils.h"
11#include "PtrTypesSemantics.h"
12#include "clang/AST/Decl.h"
13#include "clang/AST/DeclCXX.h"
21#include "llvm/Support/SaveAndRestore.h"
22#include <optional>
23
24using namespace clang;
25using namespace ento;
26
27namespace {
28
29class RawPtrRefCallArgsChecker
30 : public Checker<check::ASTDecl<TranslationUnitDecl>> {
31 BugType Bug;
32
33 TrivialFunctionAnalysis TFA;
34 EnsureFunctionAnalysis EFA;
35
36protected:
37 mutable BugReporter *BR;
38 mutable std::optional<RetainTypeChecker> RTC;
39
40public:
41 RawPtrRefCallArgsChecker(const char *description)
42 : Bug(this, description, "WebKit coding guidelines") {}
43
44 virtual std::optional<bool> isUnsafeType(QualType) const = 0;
45 virtual std::optional<bool> isUnsafePtr(QualType) const = 0;
46 virtual bool isSafePtr(const CXXRecordDecl *Record) const = 0;
47 virtual bool isSafePtrType(const QualType type) const = 0;
48 virtual bool isSafeExpr(const Expr *) const { return false; }
49 virtual bool isSafeDecl(const Decl *) const { return false; }
50 virtual const char *ptrKind() const = 0;
51
52 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
53 BugReporter &BRArg) const {
54 BR = &BRArg;
55
56 // The calls to checkAST* from AnalysisConsumer don't
57 // visit template instantiations or lambda classes. We
58 // want to visit those, so we make our own RecursiveASTVisitor.
59 struct LocalVisitor : DynamicRecursiveASTVisitor {
60 const RawPtrRefCallArgsChecker *Checker;
61 Decl *DeclWithIssue{nullptr};
62
63 explicit LocalVisitor(const RawPtrRefCallArgsChecker *Checker)
64 : Checker(Checker) {
65 assert(Checker);
66 ShouldVisitTemplateInstantiations = true;
67 ShouldVisitImplicitCode = false;
68 }
69
70 bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override {
72 return true;
73 return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl);
74 }
75
76 bool TraverseDecl(Decl *D) override {
77 llvm::SaveAndRestore SavedDecl(DeclWithIssue);
78 if (D && (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)))
79 DeclWithIssue = D;
81 }
82
83 bool VisitCallExpr(CallExpr *CE) override {
84 Checker->visitCallExpr(CE, DeclWithIssue);
85 return true;
86 }
87
88 bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
89 Checker->visitConstructExpr(CE, DeclWithIssue);
90 return true;
91 }
92
93 bool VisitTypedefDecl(TypedefDecl *TD) override {
94 if (Checker->RTC)
95 Checker->RTC->visitTypedef(TD);
96 return true;
97 }
98
99 bool VisitObjCMessageExpr(ObjCMessageExpr *ObjCMsgExpr) override {
100 Checker->visitObjCMessageExpr(ObjCMsgExpr, DeclWithIssue);
101 return true;
102 }
103 };
104
105 LocalVisitor visitor(this);
106 if (RTC)
107 RTC->visitTranslationUnitDecl(TUD);
108 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
109 }
110
111 template <typename CallOrConstrcut>
112 void visitCallOrConstructExpr(const CallOrConstrcut *CE,
113 const FunctionDecl *F, const Decl *D) const {
114 if (F) {
115 // Skip the first argument for overloaded member operators (e. g. lambda
116 // or std::function call operator).
117 unsigned ArgIdx =
118 isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
119
120 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE))
121 checkThisArg(MemberCallExpr, D);
122
123 if (ArgIdx) {
124 auto *Arg = CE->getArg(0);
125 QualType ArgType = Arg->getType().getCanonicalType();
126 std::optional<bool> IsUnsafe = isUnsafeType(ArgType);
127 if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(Arg))
128 reportBugOnThis(Arg, D);
129 }
130
131 for (auto P = F->param_begin();
132 P < F->param_end() && ArgIdx < CE->getNumArgs(); ++P, ++ArgIdx) {
133 // TODO: attributes.
134 // if ((*P)->hasAttr<SafeRefCntblRawPtrAttr>())
135 // continue;
136 checkArg(CE->getArg(ArgIdx), (*P)->getType(), *P, D);
137 }
138 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
139 auto *Arg = CE->getArg(ArgIdx);
140 checkArg(Arg, Arg->getType(), nullptr, D);
141 }
142 }
143 }
144
145 void visitCallExpr(const CallExpr *CE, const Decl *D) const {
146 auto *Callee = CE->getDirectCallee();
147 if (shouldSkipCall(CE, Callee))
148 return;
149
150 if (Callee)
151 visitCallOrConstructExpr(CE, Callee, D);
152 else if (auto *Decl = CE->getCalleeDecl()) {
153 if (auto *FnType = Decl->getFunctionType()) {
154 if (auto *ProtoType = dyn_cast<FunctionProtoType>(FnType)) {
155 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE))
156 checkThisArg(MemberCallExpr, D);
157 unsigned ArgIdx = 0;
158 for (auto PT = ProtoType->param_type_begin();
159 PT < ProtoType->param_type_end() && ArgIdx < CE->getNumArgs();
160 ++PT, ++ArgIdx)
161 checkArg(CE->getArg(ArgIdx), *PT, nullptr, D);
162 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
163 auto *Arg = CE->getArg(ArgIdx);
164 checkArg(Arg, Arg->getType(), nullptr, D);
165 }
166 }
167 }
168 }
169 }
170
171 void visitConstructExpr(const CXXConstructExpr *CE, const Decl *D) const {
172 auto *Constructor = CE->getConstructor();
173 if (shouldSkipCall(CE, Constructor))
174 return;
175 if (Constructor)
176 visitCallOrConstructExpr(CE, Constructor, D);
177 }
178
179 void visitObjCMessageExpr(const ObjCMessageExpr *E, const Decl *D) const {
180 if (BR->getSourceManager().isInSystemHeader(E->getExprLoc()))
181 return;
182
183 if (auto *Receiver = E->getInstanceReceiver()) {
184 std::optional<bool> IsUnsafe = isUnsafePtr(E->getReceiverType());
185 if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(Receiver)) {
186 if (isAllocInit(E))
187 return;
188 reportBugOnReceiver(Receiver, D);
189 }
190 }
191
192 auto *MethodDecl = E->getMethodDecl();
193 if (!MethodDecl)
194 return;
195
196 auto ArgCount = E->getNumArgs();
197 for (unsigned i = 0; i < ArgCount; ++i) {
198 auto *Arg = E->getArg(i);
199 bool hasParam = i < MethodDecl->param_size();
200 auto *Param = hasParam ? MethodDecl->getParamDecl(i) : nullptr;
201 auto ArgType = Arg->getType();
202 std::optional<bool> IsUnsafe = isUnsafePtr(ArgType);
203 if (!IsUnsafe || !(*IsUnsafe))
204 continue;
205 if (isPtrOriginSafe(Arg))
206 continue;
207 reportBug(Arg, Param, D);
208 }
209 }
210
211 void checkThisArg(const CXXMemberCallExpr *MemberCallExpr,
212 const Decl *DeclWithIssue) const {
213 if (auto *MD = MemberCallExpr->getMethodDecl()) {
214 auto name = safeGetName(MD);
215 if (name == "ref" || name == "deref")
216 return;
217 if (name == "incrementCheckedPtrCount" ||
218 name == "decrementCheckedPtrCount")
219 return;
220 }
221 auto *ThisExpr = MemberCallExpr->getImplicitObjectArgument();
222 QualType ArgType = MemberCallExpr->getObjectType().getCanonicalType();
223 std::optional<bool> IsUnsafe = isUnsafeType(ArgType);
224 if (!IsUnsafe || !*IsUnsafe)
225 return;
226
227 if (isPtrOriginSafe(ThisExpr))
228 return;
229
230 reportBugOnThis(MemberCallExpr, DeclWithIssue);
231 }
232
233 void checkArg(const Expr *Arg, QualType ParamType, const ParmVarDecl *Param,
234 const Decl *DeclWithIssue) const {
235 std::optional<bool> IsUncounted = isUnsafePtr(ParamType);
236 if (!IsUncounted || !(*IsUncounted))
237 return;
238
239 if (auto *DefaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
240 Arg = DefaultArg->getExpr();
241
242 if (isPtrOriginSafe(Arg))
243 return;
244
245 reportBug(Arg, Param, DeclWithIssue);
246 }
247
248 bool isPtrOriginSafe(const Expr *Arg) const {
249 return tryToFindPtrOrigin(
250 Arg, /*StopAtFirstRefCountedObj=*/true,
251 [&](const clang::CXXRecordDecl *Record) { return isSafePtr(Record); },
252 [&](const clang::QualType T) { return isSafePtrType(T); },
253 [&](const clang::Decl *D) { return isSafeDecl(D); },
254 [&](const clang::Expr *ArgOrigin, bool IsSafe) {
255 if (IsSafe)
256 return true;
257 if (isNullPtr(ArgOrigin))
258 return true;
259 if (isa<IntegerLiteral>(ArgOrigin)) {
260 // FIXME: Check the value.
261 // foo(123)
262 return true;
263 }
264 if (isa<CXXBoolLiteralExpr>(ArgOrigin))
265 return true;
266 if (isa<ObjCStringLiteral>(ArgOrigin))
267 return true;
268 if (isASafeCallArg(ArgOrigin))
269 return true;
270 if (EFA.isACallToEnsureFn(ArgOrigin))
271 return true;
272 if (isSafeExpr(ArgOrigin))
273 return true;
274 return false;
275 });
276 }
277
278 template <typename CallOrConstruct>
279 bool shouldSkipCall(const CallOrConstruct *CE,
280 const FunctionDecl *Callee) const {
281 if (BR->getSourceManager().isInSystemHeader(CE->getExprLoc()))
282 return true;
283
284 if (Callee && TFA.isTrivial(Callee))
285 return true;
286
287 if (isTrivialBuiltinFunction(Callee))
288 return true;
289
290 if (CE->getNumArgs() == 0)
291 return false;
292
293 // If an assignment is problematic we should warn about the sole existence
294 // of object on LHS.
295 if (auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
296 // Note: assignemnt to built-in type isn't derived from CallExpr.
297 if (MemberOp->getOperator() ==
298 OO_Equal) { // Ignore assignment to Ref/RefPtr.
299 auto *callee = MemberOp->getDirectCallee();
300 if (auto *calleeDecl = dyn_cast<CXXMethodDecl>(callee)) {
301 if (const CXXRecordDecl *classDecl = calleeDecl->getParent()) {
302 if (isSafePtr(classDecl))
303 return true;
304 }
305 }
306 }
307 if (MemberOp->isAssignmentOp())
308 return false;
309 }
310
311 if (!Callee)
312 return false;
313
314 if (isMethodOnWTFContainerType(Callee))
315 return true;
316
317 auto overloadedOperatorType = Callee->getOverloadedOperator();
318 if (overloadedOperatorType == OO_EqualEqual ||
319 overloadedOperatorType == OO_ExclaimEqual ||
320 overloadedOperatorType == OO_LessEqual ||
321 overloadedOperatorType == OO_GreaterEqual ||
322 overloadedOperatorType == OO_Spaceship ||
323 overloadedOperatorType == OO_AmpAmp ||
324 overloadedOperatorType == OO_PipePipe)
325 return true;
326
327 if (isCtorOfSafePtr(Callee) || isPtrConversion(Callee))
328 return true;
329
330 auto name = safeGetName(Callee);
331 if (name == "adoptRef" || name == "getPtr" || name == "WeakPtr" ||
332 name == "is" || name == "equal" || name == "hash" || name == "isType" ||
333 // FIXME: Most/all of these should be implemented via attributes.
334 name == "CFEqual" || name == "equalIgnoringASCIICase" ||
335 name == "equalIgnoringASCIICaseCommon" ||
336 name == "equalIgnoringNullity" || name == "toString")
337 return true;
338
339 return false;
340 }
341
342 bool isMethodOnWTFContainerType(const FunctionDecl *Decl) const {
343 if (!isa<CXXMethodDecl>(Decl))
344 return false;
345 auto *ClassDecl = Decl->getParent();
346 if (!ClassDecl || !isa<CXXRecordDecl>(ClassDecl))
347 return false;
348
349 auto *NsDecl = ClassDecl->getParent();
350 if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
351 return false;
352
353 auto MethodName = safeGetName(Decl);
354 auto ClsNameStr = safeGetName(ClassDecl);
355 StringRef ClsName = ClsNameStr; // FIXME: Make safeGetName return StringRef.
356 auto NamespaceName = safeGetName(NsDecl);
357 // FIXME: These should be implemented via attributes.
358 return NamespaceName == "WTF" &&
359 (MethodName == "find" || MethodName == "findIf" ||
360 MethodName == "reverseFind" || MethodName == "reverseFindIf" ||
361 MethodName == "findIgnoringASCIICase" || MethodName == "get" ||
362 MethodName == "inlineGet" || MethodName == "contains" ||
363 MethodName == "containsIf" ||
364 MethodName == "containsIgnoringASCIICase" ||
365 MethodName == "startsWith" || MethodName == "endsWith" ||
366 MethodName == "startsWithIgnoringASCIICase" ||
367 MethodName == "endsWithIgnoringASCIICase" ||
368 MethodName == "substring") &&
369 (ClsName.ends_with("Vector") || ClsName.ends_with("Set") ||
370 ClsName.ends_with("Map") || ClsName == "StringImpl" ||
371 ClsName.ends_with("String"));
372 }
373
374 void reportBug(const Expr *CallArg, const ParmVarDecl *Param,
375 const Decl *DeclWithIssue) const {
376 assert(CallArg);
377
378 SmallString<100> Buf;
379 llvm::raw_svector_ostream Os(Buf);
380
381 const std::string paramName = safeGetName(Param);
382 Os << "Call argument";
383 if (!paramName.empty()) {
384 Os << " for parameter ";
385 printQuotedQualifiedName(Os, Param);
386 }
387 Os << " is " << ptrKind() << " and unsafe.";
388
389 bool usesDefaultArgValue = isa<CXXDefaultArgExpr>(CallArg) && Param;
390 const SourceLocation SrcLocToReport =
391 usesDefaultArgValue ? Param->getDefaultArg()->getExprLoc()
392 : CallArg->getSourceRange().getBegin();
393
394 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
395 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
396 Report->addRange(CallArg->getSourceRange());
397 Report->setDeclWithIssue(DeclWithIssue);
398 BR->emitReport(std::move(Report));
399 }
400
401 void reportBugOnThis(const Expr *CallArg, const Decl *DeclWithIssue) const {
402 assert(CallArg);
403
404 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
405
406 SmallString<100> Buf;
407 llvm::raw_svector_ostream Os(Buf);
408 Os << "Call argument for 'this' parameter is " << ptrKind();
409 Os << " and unsafe.";
410
411 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
412 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
413 Report->addRange(CallArg->getSourceRange());
414 Report->setDeclWithIssue(DeclWithIssue);
415 BR->emitReport(std::move(Report));
416 }
417
418 void reportBugOnReceiver(const Expr *CallArg,
419 const Decl *DeclWithIssue) const {
420 assert(CallArg);
421
422 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
423
424 SmallString<100> Buf;
425 llvm::raw_svector_ostream Os(Buf);
426 Os << "Receiver is " << ptrKind() << " and unsafe.";
427
428 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
429 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
430 Report->addRange(CallArg->getSourceRange());
431 Report->setDeclWithIssue(DeclWithIssue);
432 BR->emitReport(std::move(Report));
433 }
434};
435
436class UncountedCallArgsChecker final : public RawPtrRefCallArgsChecker {
437public:
438 UncountedCallArgsChecker()
439 : RawPtrRefCallArgsChecker("Uncounted call argument for a raw "
440 "pointer/reference parameter") {}
441
442 std::optional<bool> isUnsafeType(QualType QT) const final {
443 return isUncounted(QT);
444 }
445
446 std::optional<bool> isUnsafePtr(QualType QT) const final {
447 return isUncountedPtr(QT.getCanonicalType());
448 }
449
450 bool isSafePtr(const CXXRecordDecl *Record) const final {
452 }
453
454 bool isSafePtrType(const QualType type) const final {
456 }
457
458 const char *ptrKind() const final { return "uncounted"; }
459};
460
461class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
462public:
463 UncheckedCallArgsChecker()
464 : RawPtrRefCallArgsChecker("Unchecked call argument for a raw "
465 "pointer/reference parameter") {}
466
467 std::optional<bool> isUnsafeType(QualType QT) const final {
468 return isUnchecked(QT);
469 }
470
471 std::optional<bool> isUnsafePtr(QualType QT) const final {
472 return isUncheckedPtr(QT.getCanonicalType());
473 }
474
475 bool isSafePtr(const CXXRecordDecl *Record) const final {
477 }
478
479 bool isSafePtrType(const QualType type) const final {
481 }
482
483 bool isSafeExpr(const Expr *E) const final {
485 }
486
487 const char *ptrKind() const final { return "unchecked"; }
488};
489
490class UnretainedCallArgsChecker final : public RawPtrRefCallArgsChecker {
491public:
492 UnretainedCallArgsChecker()
493 : RawPtrRefCallArgsChecker("Unretained call argument for a raw "
494 "pointer/reference parameter") {
495 RTC = RetainTypeChecker();
496 }
497
498 std::optional<bool> isUnsafeType(QualType QT) const final {
499 return RTC->isUnretained(QT);
500 }
501
502 std::optional<bool> isUnsafePtr(QualType QT) const final {
503 return RTC->isUnretained(QT);
504 }
505
506 bool isSafePtr(const CXXRecordDecl *Record) const final {
508 }
509
510 bool isSafePtrType(const QualType type) const final {
512 }
513
514 bool isSafeExpr(const Expr *E) const final {
517 }
518
519 bool isSafeDecl(const Decl *D) const final {
520 // Treat NS/CF globals in system header as immortal.
522 }
523
524 const char *ptrKind() const final { return "unretained"; }
525};
526
527} // namespace
528
529void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
530 Mgr.registerChecker<UncountedCallArgsChecker>();
531}
532
533bool ento::shouldRegisterUncountedCallArgsChecker(const CheckerManager &) {
534 return true;
535}
536
537void ento::registerUncheckedCallArgsChecker(CheckerManager &Mgr) {
538 Mgr.registerChecker<UncheckedCallArgsChecker>();
539}
540
541bool ento::shouldRegisterUncheckedCallArgsChecker(const CheckerManager &) {
542 return true;
543}
544
545void ento::registerUnretainedCallArgsChecker(CheckerManager &Mgr) {
546 Mgr.registerChecker<UnretainedCallArgsChecker>();
547}
548
549bool ento::shouldRegisterUnretainedCallArgsChecker(const CheckerManager &) {
550 return true;
551}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::MachO::Record Record
Definition MachO.h:31
Defines the clang::SourceLocation class and associated facilities.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1615
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:748
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:729
QualType getObjectType() const
Retrieve the type of the object argument.
Definition ExprCXX.cpp:741
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3150
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3129
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3137
Decl * getCalleeDecl()
Definition Expr.h:3123
SourceLocation getLocation() const
Definition DeclBase.h:447
virtual bool TraverseDecl(MaybeConst< Decl > *D)
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:282
QualType getType() const
Definition Expr.h:144
param_iterator param_begin()
Definition Decl.h:2804
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition ExprObjC.h:1434
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition ExprObjC.h:1299
const ObjCMethodDecl * getMethodDecl() const
Definition ExprObjC.h:1395
QualType getReceiverType() const
Retrieve the receiver type to which this message is being directed.
Definition ExprObjC.cpp:308
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver.
Definition ExprObjC.h:1421
Expr * getDefaultArg()
Definition Decl.cpp:2984
QualType getCanonicalType() const
Definition TypeBase.h:8497
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...
Definition Stmt.cpp:343
const SourceManager & getSourceManager()
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
Definition Checker.h:550
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
bool isCocoaObjectRef(QualType T)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
bool isCtorOfSafePtr(const clang::FunctionDecl *F)
bool isTrivialBuiltinFunction(const FunctionDecl *F)
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E)
Definition ASTUtils.cpp:319
bool isPtrConversion(const FunctionDecl *F)
std::optional< bool > isUnchecked(const QualType T)
bool isRefOrCheckedPtrType(const clang::QualType T)
void printQuotedQualifiedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
bool isRetainPtrOrOSPtrType(const clang::QualType T)
bool tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj, std::function< bool(const clang::CXXRecordDecl *)> isSafePtr, std::function< bool(const clang::QualType)> isSafePtrType, std::function< bool(const clang::Decl *)> isSafeGlobalDecl, std::function< bool(const clang::Expr *, bool)> callback)
This function de-facto defines a set of transformations that we consider safe (in heuristical sense).
Definition ASTUtils.cpp:25
bool isASafeCallArg(const Expr *E)
For E referring to a ref-countable/-counted pointer/reference we return whether it's a safe call argu...
Definition ASTUtils.cpp:245
bool isSmartPtrClass(const std::string &Name)
bool isRefCounted(const CXXRecordDecl *R)
bool isRetainPtrOrOSPtr(const std::string &Name)
std::optional< bool > isUncountedPtr(const QualType T)
bool isSafePtr(clang::CXXRecordDecl *Decl)
Definition ASTUtils.cpp:21
std::string safeGetName(const T *ASTNode)
Definition ASTUtils.h:95
bool isNullPtr(const clang::Expr *E)
Definition ASTUtils.cpp:285
bool isCheckedPtr(const std::string &Name)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
bool isAllocInit(const Expr *E, const Expr **InnerExpr)
Definition ASTUtils.cpp:339
std::optional< bool > isUncounted(const QualType T)
std::optional< bool > isUncheckedPtr(const QualType T)