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"
17#include "clang/Lex/Lexer.h"
22#include "llvm/Support/SaveAndRestore.h"
23#include <optional>
24
25using namespace clang;
26using namespace ento;
27
28namespace {
29
30class RawPtrRefCallArgsChecker
31 : public Checker<check::ASTDecl<TranslationUnitDecl>> {
32 BugType Bug;
33
34 TrivialFunctionAnalysis TFA;
35 EnsureFunctionAnalysis EFA;
36
37protected:
38 mutable BugReporter *BR;
39 mutable std::optional<RetainTypeChecker> RTC;
40
41public:
42 RawPtrRefCallArgsChecker(const char *description)
43 : Bug(this, description, "WebKit coding guidelines") {}
44
45 virtual std::optional<bool> isUnsafeType(QualType) const = 0;
46 virtual std::optional<bool> isUnsafePtr(QualType) const = 0;
47 virtual bool isSafePtr(const CXXRecordDecl *Record) const = 0;
48 virtual bool isSafePtrType(const QualType type) const = 0;
49 virtual bool isSafeExpr(const Expr *) const { return false; }
50 virtual bool isSafeDecl(const Decl *) const { return false; }
51 virtual const char *typeName() const = 0;
52
53 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
54 BugReporter &BRArg) const {
55 BR = &BRArg;
56
57 // The calls to checkAST* from AnalysisConsumer don't
58 // visit template instantiations or lambda classes. We
59 // want to visit those, so we make our own RecursiveASTVisitor.
60 struct LocalVisitor : DynamicRecursiveASTVisitor {
61 const RawPtrRefCallArgsChecker *Checker;
62 Decl *DeclWithIssue{nullptr};
63
64 explicit LocalVisitor(const RawPtrRefCallArgsChecker *Checker)
65 : Checker(Checker) {
66 assert(Checker);
67 ShouldVisitTemplateInstantiations = true;
68 ShouldVisitImplicitCode = false;
69 }
70
71 bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override {
73 return true;
74 return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl);
75 }
76
77 bool TraverseDecl(Decl *D) override {
78 llvm::SaveAndRestore SavedDecl(DeclWithIssue);
79 if (D && (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)))
80 DeclWithIssue = D;
82 }
83
84 bool VisitCallExpr(CallExpr *CE) override {
85 Checker->visitCallExpr(CE, DeclWithIssue);
86 return true;
87 }
88
89 bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
90 Checker->visitConstructExpr(CE, DeclWithIssue);
91 return true;
92 }
93
94 bool VisitTypedefDecl(TypedefDecl *TD) override {
95 if (Checker->RTC)
96 Checker->RTC->visitTypedef(TD);
97 return true;
98 }
99
100 bool VisitObjCMessageExpr(ObjCMessageExpr *ObjCMsgExpr) override {
101 Checker->visitObjCMessageExpr(ObjCMsgExpr, DeclWithIssue);
102 return true;
103 }
104 };
105
106 LocalVisitor visitor(this);
107 if (RTC)
108 RTC->visitTranslationUnitDecl(TUD);
109 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
110 }
111
112 template <typename CallOrConstrcut>
113 void visitCallOrConstructExpr(const CallOrConstrcut *CE,
114 const FunctionDecl *F, const Decl *D) const {
115 if (F) {
116 // Skip the first argument for overloaded member operators (e. g. lambda
117 // or std::function call operator).
118 unsigned ArgIdx =
119 isa<CXXOperatorCallExpr>(CE) && isa_and_nonnull<CXXMethodDecl>(F);
120
121 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE))
122 checkThisArg(F, MemberCallExpr, D);
123
124 if (ArgIdx) {
125 auto *Arg = CE->getArg(0);
126 QualType ArgType = Arg->getType().getCanonicalType();
127 std::optional<bool> IsUnsafe = isUnsafeType(ArgType);
128 if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(Arg))
129 reportBugOnThis(F, Arg, D);
130 }
131
132 for (auto P = F->param_begin();
133 P < F->param_end() && ArgIdx < CE->getNumArgs(); ++P, ++ArgIdx) {
134 // TODO: attributes.
135 // if ((*P)->hasAttr<SafeRefCntblRawPtrAttr>())
136 // continue;
137 checkArg(F, CE->getArg(ArgIdx), (*P)->getType(), *P, D);
138 }
139 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
140 auto *Arg = CE->getArg(ArgIdx);
141 checkArg(F, Arg, Arg->getType(), nullptr, D);
142 }
143 }
144 }
145
146 void visitCallExpr(const CallExpr *CE, const Decl *D) const {
147 auto *Callee = CE->getDirectCallee();
148 if (shouldSkipCall(CE, Callee))
149 return;
150
151 if (Callee)
152 visitCallOrConstructExpr(CE, Callee, D);
153 else if (auto *Decl = CE->getCalleeDecl()) {
154 if (auto *FnType = Decl->getFunctionType()) {
155 if (auto *ProtoType = dyn_cast<FunctionProtoType>(FnType)) {
156 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE))
157 checkThisArg(nullptr, MemberCallExpr, D);
158 unsigned ArgIdx = 0;
159 for (auto PT = ProtoType->param_type_begin();
160 PT < ProtoType->param_type_end() && ArgIdx < CE->getNumArgs();
161 ++PT, ++ArgIdx)
162 checkArg(nullptr, CE->getArg(ArgIdx), *PT, nullptr, D);
163 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
164 auto *Arg = CE->getArg(ArgIdx);
165 checkArg(nullptr, Arg, Arg->getType(), nullptr, D);
166 }
167 }
168 }
169 }
170 }
171
172 void visitConstructExpr(const CXXConstructExpr *CE, const Decl *D) const {
173 auto *Constructor = CE->getConstructor();
174 if (shouldSkipCall(CE, Constructor))
175 return;
176 if (Constructor)
177 visitCallOrConstructExpr(CE, Constructor, D);
178 }
179
180 void visitObjCMessageExpr(const ObjCMessageExpr *E, const Decl *D) const {
181 if (BR->getSourceManager().isInSystemHeader(E->getExprLoc()))
182 return;
183
184 if (auto *Receiver = E->getInstanceReceiver()) {
185 std::optional<bool> IsUnsafe = isUnsafePtr(E->getReceiverType());
186 if (IsUnsafe && *IsUnsafe && !isPtrOriginSafe(Receiver)) {
187 if (isAllocInit(E))
188 return;
189 auto SelectorName = E->getSelector().getNameForSlot(0);
190 if (SelectorName == "isEqual" || SelectorName == "isEqualToString")
191 return;
192 reportBugOnReceiver(E->getMethodDecl(), Receiver, D);
193 }
194 }
195
196 auto *MethodDecl = E->getMethodDecl();
197 if (!MethodDecl)
198 return;
199
200 auto ArgCount = E->getNumArgs();
201 for (unsigned i = 0; i < ArgCount; ++i) {
202 auto *Arg = E->getArg(i);
203 bool hasParam = i < MethodDecl->param_size();
204 auto *Param = hasParam ? MethodDecl->getParamDecl(i) : nullptr;
205 auto ArgType = Arg->getType();
206 std::optional<bool> IsUnsafe = isUnsafePtr(ArgType);
207 if (!IsUnsafe || !(*IsUnsafe))
208 continue;
209 if (isPtrOriginSafe(Arg))
210 continue;
211 reportBug(MethodDecl, Arg, Param, D);
212 }
213 }
214
215 void checkThisArg(const NamedDecl *Callee,
216 const CXXMemberCallExpr *MemberCallExpr,
217 const Decl *DeclWithIssue) const {
218 if (auto *MD = MemberCallExpr->getMethodDecl()) {
219 auto name = safeGetName(MD);
220 if (name == "ref" || name == "deref")
221 return;
222 if (name == "incrementCheckedPtrCount" ||
223 name == "decrementCheckedPtrCount")
224 return;
225 }
226 auto *ThisExpr = MemberCallExpr->getImplicitObjectArgument();
227 QualType ArgType = MemberCallExpr->getObjectType().getCanonicalType();
228 std::optional<bool> IsUnsafe = isUnsafeType(ArgType);
229 if (!IsUnsafe || !*IsUnsafe)
230 return;
231
232 if (isPtrOriginSafe(ThisExpr))
233 return;
234
235 reportBugOnThis(Callee, ThisExpr, DeclWithIssue);
236 }
237
238 void checkArg(const NamedDecl *Callee, const Expr *Arg, QualType ParamType,
239 const ParmVarDecl *Param, const Decl *DeclWithIssue) const {
240 std::optional<bool> IsUncounted = isUnsafePtr(ParamType);
241 if (!IsUncounted || !(*IsUncounted))
242 return;
243
244 if (auto *DefaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
245 Arg = DefaultArg->getExpr();
246
247 if (isPtrOriginSafe(Arg))
248 return;
249
250 reportBug(Callee, Arg, Param, DeclWithIssue);
251 }
252
253 bool isPtrOriginSafe(const Expr *Arg) const {
254 return tryToFindPtrOrigin(
255 Arg, /*StopAtFirstRefCountedObj=*/true,
256 [&](const clang::CXXRecordDecl *Record) { return isSafePtr(Record); },
257 [&](const clang::QualType T) { return isSafePtrType(T); },
258 [&](const clang::Decl *D) { return isSafeDecl(D); },
259 [&](const clang::Expr *ArgOrigin, bool IsSafe) {
260 if (IsSafe)
261 return true;
262 if (isNullPtr(ArgOrigin))
263 return true;
264 if (isa<IntegerLiteral>(ArgOrigin)) {
265 // FIXME: Check the value.
266 // foo(123)
267 return true;
268 }
269 if (isa<CXXBoolLiteralExpr>(ArgOrigin))
270 return true;
271 if (isa<ObjCStringLiteral>(ArgOrigin))
272 return true;
273 if (isASafeCallArg(ArgOrigin))
274 return true;
275 if (EFA.isACallToEnsureFn(ArgOrigin)) {
276 auto *MCE = dyn_cast<CXXMemberCallExpr>(ArgOrigin);
277 assert(MCE);
278 if (isPtrOriginSafe(MCE->getImplicitObjectArgument()))
279 return true;
280 }
281 if (isSafeExpr(ArgOrigin))
282 return true;
283 return false;
284 });
285 }
286
287 template <typename CallOrConstruct>
288 bool shouldSkipCall(const CallOrConstruct *CE,
289 const FunctionDecl *Callee) const {
290 if (BR->getSourceManager().isInSystemHeader(CE->getExprLoc()))
291 return true;
292
293 if (Callee && TFA.isTrivial(Callee))
294 return true;
295
296 if (isTrivialBuiltinFunction(Callee))
297 return true;
298
299 if (CE->getNumArgs() == 0)
300 return false;
301
302 // If an assignment is problematic we should warn about the sole existence
303 // of object on LHS.
304 if (auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
305 // Note: assignemnt to built-in type isn't derived from CallExpr.
306 if (MemberOp->getOperator() ==
307 OO_Equal) { // Ignore assignment to Ref/RefPtr.
308 auto *callee = MemberOp->getDirectCallee();
309 if (auto *calleeDecl = dyn_cast<CXXMethodDecl>(callee)) {
310 if (const CXXRecordDecl *classDecl = calleeDecl->getParent()) {
311 if (isSafePtr(classDecl))
312 return true;
313 }
314 }
315 }
316 if (MemberOp->isAssignmentOp())
317 return false;
318 }
319
320 if (!Callee)
321 return false;
322
323 if (isMethodOnWTFContainerType(Callee))
324 return true;
325
326 auto overloadedOperatorType = Callee->getOverloadedOperator();
327 if (overloadedOperatorType == OO_EqualEqual ||
328 overloadedOperatorType == OO_ExclaimEqual ||
329 overloadedOperatorType == OO_LessEqual ||
330 overloadedOperatorType == OO_GreaterEqual ||
331 overloadedOperatorType == OO_Spaceship ||
332 overloadedOperatorType == OO_AmpAmp ||
333 overloadedOperatorType == OO_PipePipe)
334 return true;
335
336 if (isCtorOfSafePtr(Callee) || isPtrConversion(Callee))
337 return true;
338
339 auto name = safeGetName(Callee);
340 if (name == "adoptRef" || name == "getPtr" || name == "WeakPtr" ||
341 name == "is" || name == "equal" || name == "hash" || name == "isType" ||
342 // FIXME: Most/all of these should be implemented via attributes.
343 name == "CFEqual" || name == "equalIgnoringASCIICase" ||
344 name == "equalIgnoringASCIICaseCommon" ||
345 name == "equalIgnoringNullity" || name == "toString")
346 return true;
347
348 return false;
349 }
350
351 bool isMethodOnWTFContainerType(const FunctionDecl *Decl) const {
352 if (!isa<CXXMethodDecl>(Decl))
353 return false;
354 auto *ClassDecl = Decl->getParent();
355 if (!ClassDecl || !isa<CXXRecordDecl>(ClassDecl))
356 return false;
357
358 auto *NsDecl = ClassDecl->getParent();
359 if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
360 return false;
361
362 auto MethodName = safeGetName(Decl);
363 auto ClsNameStr = safeGetName(ClassDecl);
364 StringRef ClsName = ClsNameStr; // FIXME: Make safeGetName return StringRef.
365 auto NamespaceName = safeGetName(NsDecl);
366 // FIXME: These should be implemented via attributes.
367 return NamespaceName == "WTF" &&
368 (MethodName == "find" || MethodName == "findIf" ||
369 MethodName == "reverseFind" || MethodName == "reverseFindIf" ||
370 MethodName == "findIgnoringASCIICase" || MethodName == "get" ||
371 MethodName == "inlineGet" || MethodName == "contains" ||
372 MethodName == "containsIf" ||
373 MethodName == "containsIgnoringASCIICase" ||
374 MethodName == "startsWith" || MethodName == "endsWith" ||
375 MethodName == "startsWithIgnoringASCIICase" ||
376 MethodName == "endsWithIgnoringASCIICase" ||
377 MethodName == "substring") &&
378 (ClsName.ends_with("Vector") || ClsName.ends_with("Set") ||
379 ClsName.ends_with("Map") || ClsName == "StringImpl" ||
380 ClsName.ends_with("String"));
381 }
382
383 void reportBug(const NamedDecl *Callee, const Expr *CallArg,
384 const ParmVarDecl *Param, const Decl *DeclWithIssue) const {
385 assert(CallArg);
386
387 SmallString<100> Buf;
388 llvm::raw_svector_ostream Os(Buf);
389
390 const std::string paramName = safeGetName(Param);
391 Os << "Function argument";
392 printArgument(Os, CallArg, DeclWithIssue);
393 if (!paramName.empty() || Callee)
394 Os << " (";
395 if (!paramName.empty()) {
396 Os << "parameter ";
397 printQuotedQualifiedName(Os, Param);
398 }
399 if (Callee) {
400 if (!paramName.empty())
401 Os << " ";
402 Os << "to ";
403 printQuotedQualifiedName(Os, Callee);
404 }
405 if (!paramName.empty() || Callee)
406 Os << ")";
407 Os << " is a ";
408 auto *ArgType = CallArg->getType().getTypePtr();
409
410 if (printPointer(Os, ArgType) == PrintDeclKind::Pointer) {
411 assert(RTC);
412 if (auto *Decl = RTC->getCanonicalDecl(CallArg->getType())) {
413 printQuotedQualifiedName(Os, Decl);
414 } else {
415 auto Typedef = ArgType->getAs<TypedefType>();
416 assert(Typedef);
417 printQuotedQualifiedName(Os, Typedef->getDecl());
418 }
419 } else {
420 Os << " ";
421 printTypeName(Os, CallArg->getType());
422 }
423
424 bool usesDefaultArgValue = isa<CXXDefaultArgExpr>(CallArg) && Param;
425 const SourceLocation SrcLocToReport =
426 usesDefaultArgValue ? Param->getDefaultArg()->getExprLoc()
427 : CallArg->getSourceRange().getBegin();
428
429 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
430 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
431 Report->addRange(CallArg->getSourceRange());
432 Report->setDeclWithIssue(DeclWithIssue);
433 BR->emitReport(std::move(Report));
434 }
435
436 void reportBugOnThis(const NamedDecl *Callee, const Expr *CallArg,
437 const Decl *DeclWithIssue) const {
438 assert(CallArg);
439
440 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
441
442 SmallString<100> Buf;
443 llvm::raw_svector_ostream Os(Buf);
444 Os << "Function argument";
445 printArgument(Os, CallArg, DeclWithIssue);
446 Os << " (parameter 'this'";
447 if (Callee) {
448 Os << " to ";
449 printQuotedQualifiedName(Os, Callee);
450 }
451 Os << ") is a raw pointer to " << typeName() << " ";
452 printTypeName(Os, CallArg->getType());
453
454 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
455 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
456 Report->addRange(CallArg->getSourceRange());
457 Report->setDeclWithIssue(DeclWithIssue);
458 BR->emitReport(std::move(Report));
459 }
460
461 void reportBugOnReceiver(const NamedDecl *Callee, const Expr *CallArg,
462 const Decl *DeclWithIssue) const {
463 assert(CallArg);
464
465 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
466
467 SmallString<100> Buf;
468 llvm::raw_svector_ostream Os(Buf);
469 Os << "Receiver";
470 printArgument(Os, CallArg, DeclWithIssue);
471 if (Callee) {
472 Os << " (to ";
473 printQuotedQualifiedName(Os, Callee);
474 Os << ")";
475 }
476 Os << " is a raw pointer to " << typeName() << " ";
477 printTypeName(Os, CallArg->getType());
478
479 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
480 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
481 Report->addRange(CallArg->getSourceRange());
482 Report->setDeclWithIssue(DeclWithIssue);
483 BR->emitReport(std::move(Report));
484 }
485
486 void printArgument(llvm::raw_svector_ostream &Os, const Expr *Arg,
487 const Decl *D) const {
488 SmallString<100> Buf;
489 llvm::raw_svector_ostream ArgOs(Buf);
490 Arg->printPretty(ArgOs, /*Helper=*/nullptr,
492 StringRef ArgCode = ArgOs.str();
493 if (ArgCode.contains('\n'))
494 return;
495 ArgCode = ArgCode.take_front(50);
496 if (ArgCode.size() == 50)
497 Os << " '" << ArgCode << "...'";
498 else
499 Os << " '" << ArgCode << "'";
500 }
501
502 enum class PrintDeclKind { Pointee, Pointer };
503 virtual PrintDeclKind printPointer(llvm::raw_svector_ostream &Os,
504 const Type *T) const {
507 Os << "raw " << (IsPtr ? "pointer" : "reference") << " to " << typeName();
508 return PrintDeclKind::Pointee;
509 }
510};
511
512class UncountedCallArgsChecker final : public RawPtrRefCallArgsChecker {
513public:
514 UncountedCallArgsChecker()
515 : RawPtrRefCallArgsChecker("Uncounted call argument for a raw "
516 "pointer/reference parameter") {}
517
518 std::optional<bool> isUnsafeType(QualType QT) const final {
519 return isUncounted(QT);
520 }
521
522 std::optional<bool> isUnsafePtr(QualType QT) const final {
523 return isUncountedPtr(QT.getCanonicalType());
524 }
525
526 bool isSafePtr(const CXXRecordDecl *Record) const final {
528 }
529
530 bool isSafePtrType(const QualType type) const final {
532 }
533
534 const char *typeName() const final { return "RefPtr-capable type"; }
535};
536
537class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
538public:
539 UncheckedCallArgsChecker()
540 : RawPtrRefCallArgsChecker("Unchecked call argument for a raw "
541 "pointer/reference parameter") {}
542
543 std::optional<bool> isUnsafeType(QualType QT) const final {
544 return isUnchecked(QT);
545 }
546
547 std::optional<bool> isUnsafePtr(QualType QT) const final {
548 return isUncheckedPtr(QT.getCanonicalType());
549 }
550
551 bool isSafePtr(const CXXRecordDecl *Record) const final {
553 }
554
555 bool isSafePtrType(const QualType type) const final {
557 }
558
559 bool isSafeExpr(const Expr *E) const final {
561 }
562
563 const char *typeName() const final { return "CheckedPtr-capable type"; }
564};
565
566class UnretainedCallArgsChecker final : public RawPtrRefCallArgsChecker {
567public:
568 UnretainedCallArgsChecker()
569 : RawPtrRefCallArgsChecker("Unretained call argument for a raw "
570 "pointer/reference parameter") {
571 RTC = RetainTypeChecker();
572 }
573
574 std::optional<bool> isUnsafeType(QualType QT) const final {
575 return RTC->isUnretained(QT);
576 }
577
578 std::optional<bool> isUnsafePtr(QualType QT) const final {
579 return RTC->isUnretained(QT);
580 }
581
582 bool isSafePtr(const CXXRecordDecl *Record) const final {
584 }
585
586 bool isSafePtrType(const QualType type) const final {
588 }
589
590 bool isSafeDecl(const Decl *D) const final {
591 // Treat NS/CF globals in system header as immortal.
593 }
594
595 PrintDeclKind printPointer(llvm::raw_svector_ostream &Os,
596 const Type *T) const final {
597 if (isa<TypedefType>(T)) {
598 Os << typeName() << " ";
599 return PrintDeclKind::Pointer;
600 }
601 return RawPtrRefCallArgsChecker::printPointer(Os, T);
602 }
603
604 const char *typeName() const final { return "RetainPtr-capable type"; }
605};
606
607} // namespace
608
609void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
610 Mgr.registerChecker<UncountedCallArgsChecker>();
611}
612
613bool ento::shouldRegisterUncountedCallArgsChecker(const CheckerManager &) {
614 return true;
615}
616
617void ento::registerUncheckedCallArgsChecker(CheckerManager &Mgr) {
618 Mgr.registerChecker<UncheckedCallArgsChecker>();
619}
620
621bool ento::shouldRegisterUncheckedCallArgsChecker(const CheckerManager &) {
622 return true;
623}
624
625void ento::registerUnretainedCallArgsChecker(CheckerManager &Mgr) {
626 Mgr.registerChecker<UnretainedCallArgsChecker>();
627}
628
629bool ento::shouldRegisterUnretainedCallArgsChecker(const CheckerManager &) {
630 return true;
631}
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.
static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP, llvm::raw_ostream &OS, bool IncludeType)
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:861
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:3153
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3132
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3140
Decl * getCalleeDecl()
Definition Expr.h:3126
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
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:283
QualType getType() const
Definition Expr.h:144
param_iterator param_begin()
Definition Decl.h:2826
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
Selector getSelector() const
Definition ExprObjC.cpp:301
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:2987
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
QualType getCanonicalType() const
Definition TypeBase.h:8499
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SourceLocation getBegin() const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) 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 T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:690
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:565
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
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:321
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:247
bool isSmartPtrClass(const std::string &Name)
bool isRefCounted(const CXXRecordDecl *R)
@ Type
The name was classified as a type.
Definition Sema.h:564
bool isRetainPtrOrOSPtr(const std::string &Name)
void printTypeName(llvm::raw_ostream &Os, const QualType QT)
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:98
bool isNullPtr(const clang::Expr *E)
Definition ASTUtils.cpp:287
bool isCheckedPtr(const std::string &Name)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
bool isAllocInit(const Expr *E, const Expr **InnerExpr)
Definition ASTUtils.cpp:341
std::optional< bool > isUncounted(const QualType T)
std::optional< bool > isUncheckedPtr(const QualType T)