clang 24.0.0git
RawPtrRefLocalVarsChecker.cpp
Go to the documentation of this file.
1//=======- UncountedLocalVarsChecker.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"
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclCXX.h"
24#include <optional>
25
26using namespace clang;
27using namespace ento;
28
29namespace {
30
31// FIXME: should be defined by anotations in the future
32bool isRefcountedStringsHack(const VarDecl *V) {
33 assert(V);
34 auto safeClass = [](const std::string &className) {
35 return className == "String" || className == "AtomString" ||
36 className == "UniquedString" || className == "Identifier";
37 };
38 QualType QT = V->getType();
39 auto *T = QT.getTypePtr();
40 if (auto *CXXRD = T->getAsCXXRecordDecl()) {
41 if (safeClass(safeGetName(CXXRD)))
42 return true;
43 }
44 if (T->isPointerType() || T->isReferenceType()) {
45 if (auto *CXXRD = T->getPointeeCXXRecordDecl()) {
46 if (safeClass(safeGetName(CXXRD)))
47 return true;
48 }
49 }
50 return false;
51}
52
53struct GuardianVisitor : DynamicRecursiveASTVisitor {
54 const VarDecl *Guardian{nullptr};
55 bool GuardianIsRawPtrOrRef{false};
56
57 explicit GuardianVisitor(const VarDecl *Guardian,
58 bool GuardianIsRawPtrOrRef = false)
59 : Guardian(Guardian), GuardianIsRawPtrOrRef(GuardianIsRawPtrOrRef) {
60 assert(Guardian);
61 }
62
63 bool VisitBinaryOperator(BinaryOperator *BO) override {
64 if (BO->isAssignmentOp()) {
65 if (auto *VarRef = dyn_cast<DeclRefExpr>(BO->getLHS())) {
66 if (VarRef->getDecl() == Guardian)
67 return false;
68 }
69 }
70 return true;
71 }
72
73 bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
74 auto *Ctor = CE->getConstructor();
75 if (!Ctor)
76 return false;
77 unsigned ArgIndex = 0;
78 for (auto *Arg : CE->arguments()) {
79 ParmVarDecl *Parm = nullptr;
80 if (ArgIndex < Ctor->getNumParams())
81 Parm = Ctor->getParamDecl(ArgIndex);
82 if (mutatesGuardian(Arg, Parm))
83 return false;
84 ArgIndex++;
85 }
86 return true;
87 }
88
89 bool VisitCallExpr(CallExpr *CE) override {
90 auto *Callee = CE->getDirectCallee();
91 if (!Callee)
92 return false;
93 if (isPtrConversion(Callee))
94 return true;
95 if (auto *Method = dyn_cast<CXXMethodDecl>(Callee)) {
96 if (isGetterOfSafePtr(Method).value_or(false))
97 return true;
98 }
99 unsigned ArgIndex = 0;
100 unsigned ArgOffset = isa<CXXOperatorCallExpr>(CE);
101 for (auto *Arg : CE->arguments()) {
102 ParmVarDecl *Parm = nullptr;
103 if (ArgIndex >= ArgOffset) {
104 unsigned ParmIndex = ArgIndex - ArgOffset;
105 if (ParmIndex < Callee->getNumParams())
106 Parm = Callee->getParamDecl(ParmIndex);
107 }
108 if (mutatesGuardian(Arg, Parm))
109 return false;
110 ArgIndex++;
111 }
112 return true;
113 }
114
115 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *MCE) override {
116 if (GuardianIsRawPtrOrRef)
117 return true;
118 auto *Method = MCE->getMethodDecl();
119 auto ObjType = MCE->getObjectType();
120 if (ObjType.isConstQualified())
121 return true;
122 auto *ThisArg = MCE->getImplicitObjectArgument()->IgnoreParenCasts();
123 if (auto *VarRef = dyn_cast<DeclRefExpr>(ThisArg)) {
124 if (!isa<CXXConversionDecl>(Method) && VarRef->getDecl() == Guardian)
125 return false;
126 }
127 return true;
128 }
129
130private:
131 bool mutatesGuardian(const Expr *Arg, const ParmVarDecl *ParmDecl) {
132 Arg = Arg->IgnoreParenCasts();
133 auto ArgType = ParmDecl ? ParmDecl->getType() : Arg->getType();
134 bool IsAddressOf = false;
135 if (auto *UO = dyn_cast<UnaryOperator>(Arg);
136 UO && UO->getOpcode() == UO_AddrOf) {
137 Arg = UO->getSubExpr()->IgnoreParenCasts();
138 IsAddressOf = true;
139 }
140 auto *VarRef = dyn_cast<DeclRefExpr>(Arg);
141 if (!VarRef || VarRef->getDecl() != Guardian)
142 return false;
143 if (GuardianIsRawPtrOrRef && !Guardian->getType()->isPointerType())
144 return false;
145 if (IsAddressOf) {
146 if (!ArgType->isPointerType())
147 return false;
148 return !ArgType->getPointeeType().isConstQualified();
149 }
150 if (GuardianIsRawPtrOrRef) {
151 if (!ArgType->isReferenceType())
152 return false;
153 return !ArgType.getNonReferenceType().isConstQualified();
154 }
155 return !ArgType.isConstQualified();
156 }
157};
158
159bool isGuardedScopeEmbeddedInGuardianScope(const VarDecl *Guarded,
160 const VarDecl *MaybeGuardian) {
161 assert(Guarded);
162 assert(MaybeGuardian);
163
164 if (!MaybeGuardian->isLocalVarDecl())
165 return false;
166
167 const CompoundStmt *guardiansClosestCompStmtAncestor = nullptr;
168
169 ASTContext &ctx = MaybeGuardian->getASTContext();
170
171 for (DynTypedNodeList guardianAncestors = ctx.getParents(*MaybeGuardian);
172 !guardianAncestors.empty();
173 guardianAncestors = ctx.getParents(
174 *guardianAncestors
175 .begin()) // FIXME - should we handle all of the parents?
176 ) {
177 for (auto &guardianAncestor : guardianAncestors) {
178 if (auto *CStmtParentAncestor = guardianAncestor.get<CompoundStmt>()) {
179 guardiansClosestCompStmtAncestor = CStmtParentAncestor;
180 break;
181 }
182 }
183 if (guardiansClosestCompStmtAncestor)
184 break;
185 }
186
187 if (!guardiansClosestCompStmtAncestor)
188 return false;
189
190 // We need to skip the first CompoundStmt to avoid situation when guardian is
191 // defined in the same scope as guarded variable.
192 const CompoundStmt *FirstCompondStmt = nullptr;
193 for (DynTypedNodeList guardedVarAncestors = ctx.getParents(*Guarded);
194 !guardedVarAncestors.empty();
195 guardedVarAncestors = ctx.getParents(
196 *guardedVarAncestors
197 .begin()) // FIXME - should we handle all of the parents?
198 ) {
199 for (auto &guardedVarAncestor : guardedVarAncestors) {
200 if (auto *CStmtAncestor = guardedVarAncestor.get<CompoundStmt>()) {
201 if (!FirstCompondStmt) {
202 FirstCompondStmt = CStmtAncestor;
203 continue;
204 }
205 if (CStmtAncestor == guardiansClosestCompStmtAncestor) {
206 GuardianVisitor guardianVisitor(MaybeGuardian);
207 auto *GuardedScope = const_cast<CompoundStmt *>(FirstCompondStmt);
208 return guardianVisitor.TraverseCompoundStmt(GuardedScope);
209 }
210 }
211 }
212 }
213
214 return false;
215}
216
217static const VarDecl *findAssignedVar(const Expr *DestExpr) {
218 while (DestExpr) {
219 DestExpr = DestExpr->IgnoreParenCasts();
220 if (auto *DRE = dyn_cast<DeclRefExpr>(DestExpr))
221 return dyn_cast_or_null<VarDecl>(DRE->getDecl());
222 if (auto *UO = dyn_cast<UnaryOperator>(DestExpr);
223 UO && UO->getOpcode() == UO_Deref) {
224 DestExpr = UO->getSubExpr();
225 continue;
226 }
227 if (auto *ASE = dyn_cast<ArraySubscriptExpr>(DestExpr)) {
228 DestExpr = ASE->getBase();
229 continue;
230 }
231 return nullptr;
232 }
233 return nullptr;
234}
235
236class RawPtrRefLocalVarsChecker
237 : public Checker<check::ASTDecl<TranslationUnitDecl>> {
238 BugType Bug;
239 EnsureFunctionAnalysis EFA;
240
241protected:
242 mutable BugReporter *BR;
243 const std::unique_ptr<PtrRefSafetyModel> Model;
244
245public:
246 RawPtrRefLocalVarsChecker(const char *description,
247 std::unique_ptr<PtrRefSafetyModel> Model)
248 : Bug(this, description, "WebKit coding guidelines"),
249 Model(std::move(Model)) {}
250
251 std::optional<bool> isUnsafePtr(QualType T) const {
252 return isUnsafePtrForStorage(*Model, T);
253 }
254
255 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
256 BugReporter &BRArg) const {
257 BR = &BRArg;
258
259 // The calls to checkAST* from AnalysisConsumer don't
260 // visit template instantiations or lambda classes. We
261 // want to visit those, so we make our own RecursiveASTVisitor.
262 struct LocalVisitor : DynamicRecursiveASTVisitor {
263 const RawPtrRefLocalVarsChecker *Checker;
264 Decl *DeclWithIssue{nullptr};
265
266 TrivialFunctionAnalysis TFA;
267
268 explicit LocalVisitor(const RawPtrRefLocalVarsChecker *Checker)
269 : Checker(Checker) {
270 assert(Checker);
271 ShouldVisitTemplateInstantiations = true;
272 ShouldVisitImplicitCode = false;
273 }
274
275 bool TraverseDecl(Decl *D) override {
276 // A template pattern is checked through its instantiations, which are
277 // traversed from the TemplateDecl itself. In the pattern the callee of
278 // a call may still be an unresolved overload set and the type of an
279 // expression may still be dependent, neither of which can be reasoned
280 // about, so don't enter it at all.
281 if (D && !isa<TemplateDecl>(D) && D->isTemplated())
282 return true;
283 llvm::SaveAndRestore SavedDecl(DeclWithIssue);
284 if (D && (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)))
285 DeclWithIssue = D;
287 }
288
289 bool TraverseLambdaExpr(LambdaExpr *L) override {
291 if (!FTD)
292 return DynamicRecursiveASTVisitor::TraverseLambdaExpr(L);
293 // The body of a generic lambda is the pattern of its call operator,
294 // but it is reached from the LambdaExpr as a statement, so TraverseDecl
295 // never gets to skip it. Traverse the capture initializers, which are
296 // evaluated in the enclosing scope, and then the call operator itself,
297 // of which the pattern is skipped like any other and the instantiations
298 // are traversed. Going through TraverseDecl also makes an instantiation
299 // the decl with the issue, so that a guardian is looked up in it rather
300 // than in the pattern. The initializers are traversed as expressions
301 // because the variable of an init capture is declared in the pattern.
302 for (unsigned I = 0, N = L->capture_size(); I != N; ++I) {
303 if (!(L->capture_begin() + I)->isExplicit())
304 continue;
305 if (auto *Init = L->capture_init_begin()[I];
306 Init && !TraverseStmt(Init))
307 return false;
308 }
309 return TraverseDecl(FTD);
310 }
311
312 bool VisitTypedefDecl(TypedefDecl *TD) override {
313 if (auto *RTC = Checker->Model->retainTypeChecker())
314 RTC->visitTypedef(TD);
315 return true;
316 }
317
318 bool VisitVarDecl(VarDecl *V) override {
319 auto *Init = V->getInit();
320 if (V->isLocalVarDecl())
321 Checker->visitVarDecl(V, V->getType(), Init, DeclWithIssue);
322 return true;
323 }
324
325 bool VisitBinaryOperator(BinaryOperator *BO) override {
326 if (BO->isAssignmentOp()) {
327 if (Checker->Model->recognizesIndirectStores()) {
328 if (auto *V = findAssignedVar(BO->getLHS()))
329 Checker->visitVarDecl(V, BO->getLHS()->getType(), BO->getRHS(),
330 DeclWithIssue);
331 } else if (auto *VarRef = dyn_cast<DeclRefExpr>(BO->getLHS())) {
332 if (auto *V = dyn_cast<VarDecl>(VarRef->getDecl()))
333 Checker->visitVarDecl(V, V->getType(), BO->getRHS(),
334 DeclWithIssue);
335 }
336 }
337 return true;
338 }
339
340 bool TraverseIfStmt(IfStmt *IS) override {
341 if (IS->getConditionVariable()) {
342 // This code does not check the condition variable in the "else"
343 // statement since getConditionVariable returns nullptr when there
344 // is a condition defined after ";" as in "if (auto foo = ~; !foo)".
345 // If this semantics change, we should check it in "else" as well.
346 if (auto *Then = IS->getThen(); !Then || TFA.isTrivial(Then)) {
347 if (auto *Else = IS->getElse(); Else && !TFA.isTrivial(Else))
348 return TraverseStmt(Else);
349 return true;
350 }
351 }
352 if (!TFA.isTrivial(IS))
353 return DynamicRecursiveASTVisitor::TraverseIfStmt(IS);
354 return true;
355 }
356
357 bool TraverseForStmt(ForStmt *FS) override {
358 if (!TFA.isTrivial(FS))
359 return DynamicRecursiveASTVisitor::TraverseForStmt(FS);
360 return true;
361 }
362
363 bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) override {
364 if (!TFA.isTrivial(FRS))
365 return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(FRS);
366 return true;
367 }
368
369 bool TraverseWhileStmt(WhileStmt *WS) override {
370 if (!TFA.isTrivial(WS))
371 return DynamicRecursiveASTVisitor::TraverseWhileStmt(WS);
372 return true;
373 }
374
375 bool TraverseCompoundStmt(CompoundStmt *CS) override {
376 if (!TFA.isTrivial(CS))
377 return DynamicRecursiveASTVisitor::TraverseCompoundStmt(CS);
378 return true;
379 }
380
381 bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override {
382 if (isSmartPtrClass(safeGetName(Decl)))
383 return true;
384 return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl);
385 }
386 };
387
388 LocalVisitor visitor(this);
389 if (auto *RTC = Model->retainTypeChecker())
390 RTC->visitTranslationUnitDecl(TUD);
391 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
392 }
393
394 void visitVarDecl(const VarDecl *V, QualType SinkType, const Expr *Value,
395 const Decl *DeclWithIssue) const {
396 if (shouldSkipVarDecl(V))
397 return;
398
399 if (auto *DD = dyn_cast<DecompositionDecl>(V)) {
400 const auto *InitList =
401 Value ? dyn_cast<InitListExpr>(Value->IgnoreParenCasts()) : nullptr;
402 if (InitList && InitList->getNumInits() != DD->bindings().size())
403 InitList = nullptr;
404
405 unsigned BindingIndex = 0;
406 for (auto *BD : DD->bindings()) {
407 const unsigned Index = BindingIndex++;
408 auto *Binding = BD->getBinding();
409 if (!Binding)
410 continue;
411 std::optional<bool> IsUncountedPtr = isUnsafePtr(Binding->getType());
412 if (!IsUncountedPtr || !*IsUncountedPtr)
413 continue;
414
415 const Expr *Origin = nullptr;
416 if (Model->checksForInteriorDestruction()) {
417 const Expr *Source = InitList ? InitList->getInit(Index) : Value;
418 if (isPtrOriginSafe(V, Source, DeclWithIssue, Origin))
419 continue;
420 }
421 reportBug(V, V->getType(), nullptr, BD, DeclWithIssue, Origin);
422 }
423 }
424
425 std::optional<bool> IsUncountedPtr = isUnsafePtr(SinkType);
426 if (IsUncountedPtr && *IsUncountedPtr) {
427 const Expr *Origin = nullptr;
428 if (Value) {
429 if (isPtrOriginSafe(V, Value, DeclWithIssue, Origin))
430 return;
431 } else if (Model->checksForInteriorDestruction())
432 return;
433 reportBug(V, SinkType, Value, nullptr, DeclWithIssue, Origin);
434 }
435 }
436
437 bool isPtrOriginSafe(const VarDecl *V, const Expr *Value,
438 const Decl *DeclWithIssue, const Expr *&Origin) const {
439 return tryToFindPtrOrigin(
440 Value, /*StopAtFirstRefCountedObj=*/false,
441 Model->checksForInteriorDestruction(),
442 [&](const clang::CXXRecordDecl *Record) {
443 return Model->isSafePtr(Record);
444 },
445 [&](const clang::QualType Type) { return Model->isSafePtrType(Type); },
446 [&](const clang::Decl *D) {
447 return Model->isSafeDecl(D, BR->getSourceManager());
448 },
449 [&](const clang::Expr *InitArgOrigin, bool IsSafe,
450 bool OriginDependsOnFullExpressionTemporary,
451 bool PtrIsLifetimeBoundToOrigin) {
452 if (!InitArgOrigin)
453 return true;
454
455 if (IsSafe) {
456 if (!OriginDependsOnFullExpressionTemporary)
457 return true;
458 if (!Origin)
459 Origin = InitArgOrigin;
460 return false;
461 }
462
463 if (isa<CXXThisExpr>(InitArgOrigin))
464 return true;
465
466 if (isNullPtr(InitArgOrigin))
467 return true;
468
469 if (isa<IntegerLiteral>(InitArgOrigin))
470 return true;
471
472 if (isConstOwnerPtrMemberExpr(InitArgOrigin))
473 return true;
474
475 if (EFA.isACallToEnsureFn(InitArgOrigin))
476 return true;
477
478 if (Model->isSafeExpr(InitArgOrigin, PtrIsLifetimeBoundToOrigin))
479 return true;
480
481 if (!Model->checksForInteriorDestruction() &&
482 hasGuardian(V, InitArgOrigin, DeclWithIssue))
483 return true;
484
485 if (!Origin)
486 Origin = InitArgOrigin;
487 return false;
488 });
489 }
490
491 bool hasGuardian(const VarDecl *V, const Expr *InitArgOrigin,
492 const Decl *DeclWithIssue) const {
493 auto *Ref = dyn_cast<DeclRefExpr>(InitArgOrigin);
494 if (!Ref)
495 return false;
496
497 auto *MaybeGuardian = dyn_cast_or_null<VarDecl>(Ref->getFoundDecl());
498 if (!MaybeGuardian)
499 return false;
500
501 QualType GuardianType = MaybeGuardian->getType();
502 if (!GuardianType.isNull()) {
503 if (auto *Record = GuardianType->getAsCXXRecordDecl()) {
504 if (MaybeGuardian->isLocalVarDecl() &&
505 (Model->isSafePtr(Record) ||
506 isRefcountedStringsHack(MaybeGuardian)) &&
507 isGuardedScopeEmbeddedInGuardianScope(V, MaybeGuardian))
508 return true;
509 }
510 }
511
512 if (isa<ParmVarDecl>(MaybeGuardian)) {
513 bool IsRawPtrOrRef = isUnsafePtr(GuardianType).value_or(false);
514 GuardianVisitor Visitor{MaybeGuardian, IsRawPtrOrRef};
515 if (auto *FD = dyn_cast<FunctionDecl>(DeclWithIssue))
516 return Visitor.TraverseStmt(FD->getBody());
517 if (auto *MD = dyn_cast<ObjCMethodDecl>(DeclWithIssue))
518 return Visitor.TraverseStmt(MD->getBody());
519 }
520
521 return false;
522 }
523
524 bool shouldSkipVarDecl(const VarDecl *V) const {
525 assert(V);
527 return true;
528 if (V->isInitCapture())
529 return true;
530 return BR->getSourceManager().isInSystemHeader(V->getLocation());
531 }
532
533 void reportBug(const VarDecl *V, QualType SinkType, const Expr *Value,
534 const Decl *BindingDecl, const Decl *DeclWithIssue,
535 const Expr *Origin) const {
536 assert(V);
538 llvm::raw_svector_ostream Os(Buf);
539
540 if (isa<ParmVarDecl>(V)) {
541 Os << "Parameter ";
543 Os << " is a ";
544 Model->describeHazard(Os, Origin, SinkType);
545
546 SourceLocation ExprLoc = (Value) ? Value->getExprLoc() : V->getLocation();
547 PathDiagnosticLocation BSLoc(ExprLoc, BR->getSourceManager());
548 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
549 if (Value)
550 Report->addRange(Value->getSourceRange());
551 Report->setDeclWithIssue(DeclWithIssue);
552 BR->emitReport(std::move(Report));
553 } else {
554 if (V->hasLocalStorage())
555 Os << "Local variable ";
556 else if (V->isStaticLocal())
557 Os << "Static local variable ";
558 else if (V->hasGlobalStorage())
559 Os << "Global variable ";
560 else
561 Os << "Variable ";
562 if (BindingDecl)
563 Os << "'" << safeGetName(BindingDecl) << "'";
564 else
566 Os << " is a ";
567 Model->describeHazard(Os, Origin, SinkType);
568
569 PathDiagnosticLocation BSLoc(V->getLocation(), BR->getSourceManager());
570 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
571 Report->addRange(V->getSourceRange());
572 Report->setDeclWithIssue(DeclWithIssue);
573 BR->emitReport(std::move(Report));
574 }
575 }
576};
577
578class UncountedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
579public:
580 UncountedLocalVarsChecker()
581 : RawPtrRefLocalVarsChecker("Uncounted raw pointer or reference not "
582 "provably backed by ref-counted variable",
584};
585
586class UncheckedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
587public:
588 UncheckedLocalVarsChecker()
589 : RawPtrRefLocalVarsChecker("Unchecked raw pointer or reference not "
590 "provably backed by checked variable",
592};
593
594class UnretainedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
595public:
596 UnretainedLocalVarsChecker()
597 : RawPtrRefLocalVarsChecker("Unretained raw pointer or reference not "
598 "provably backed by a RetainPtr",
600};
601
602class UnborrowedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
603public:
604 UnborrowedLocalVarsChecker()
605 : RawPtrRefLocalVarsChecker("Loan on a CanBorrow object not guarded by "
606 "a Borrow",
608};
609
610} // namespace
611
612void ento::registerUncountedLocalVarsChecker(CheckerManager &Mgr) {
613 Mgr.registerChecker<UncountedLocalVarsChecker>();
614}
615
616bool ento::shouldRegisterUncountedLocalVarsChecker(const CheckerManager &) {
617 return true;
618}
619
620void ento::registerUncheckedLocalVarsChecker(CheckerManager &Mgr) {
621 Mgr.registerChecker<UncheckedLocalVarsChecker>();
622}
623
624bool ento::shouldRegisterUncheckedLocalVarsChecker(const CheckerManager &) {
625 return true;
626}
627
628void ento::registerUnretainedLocalVarsChecker(CheckerManager &Mgr) {
629 Mgr.registerChecker<UnretainedLocalVarsChecker>();
630}
631
632bool ento::shouldRegisterUnretainedLocalVarsChecker(const CheckerManager &) {
633 return true;
634}
635
636void ento::registerUnborrowedLocalVarsChecker(CheckerManager &Mgr) {
637 Mgr.registerChecker<UnborrowedLocalVarsChecker>();
638}
639
640bool ento::shouldRegisterUnborrowedLocalVarsChecker(const CheckerManager &) {
641 return true;
642}
#define V(N, I)
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
DynTypedNodeList getParents(const NodeT &Node)
Forwards to get node parents from the ParentMapContext.
Expr * getLHS() const
Definition Expr.h:4132
Expr * getRHS() const
Definition Expr.h:4134
static bool isAssignmentOp(Opcode Opc)
Definition Expr.h:4218
A binding in a decomposition declaration.
Definition DeclCXX.h:4215
arg_range arguments()
Definition ExprCXX.h:1677
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1616
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:773
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:754
QualType getObjectType() const
Retrieve the type of the object argument.
Definition ExprCXX.cpp:766
FunctionTemplateDecl * getDependentLambdaCallOperator() const
Retrieve the dependent lambda call operator of the closure type if this is a templated closure type.
Definition DeclCXX.cpp:1739
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3170
arg_range arguments()
Definition Expr.h:3239
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1752
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
bool isTemplated() const
Determine whether this declaration is a templated entity (whether it is.
Definition DeclBase.cpp:308
Container for either a single DynTypedNode or for an ArrayRef to DynTypedNode.
virtual bool TraverseDecl(MaybeConst< Decl > *D)
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3131
QualType getType() const
Definition Expr.h:145
Stmt * getThen()
Definition Stmt.h:2360
Stmt * getElse()
Definition Stmt.h:2369
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
Definition Stmt.cpp:1068
capture_iterator capture_begin() const
Retrieve an iterator pointing to the first lambda capture.
Definition ExprCXX.cpp:1395
unsigned capture_size() const
Determine the number of captures in this lambda.
Definition ExprCXX.h:2054
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument for this lambda expression (which initializes the first ca...
Definition ExprCXX.h:2099
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Definition ExprCXX.cpp:1432
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
Encodes a location in the source.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isTrivial(const Decl *D, const Stmt **OffendingStmt=nullptr) const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1275
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)
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
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
std::unique_ptr< PtrRefSafetyModel > makeBorrowSafetyModel()
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isPtrConversion(const FunctionDecl *F)
std::unique_ptr< PtrRefSafetyModel > makeCheckedPtrSafetyModel()
void printQuotedQualifiedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
std::optional< bool > isUnsafePtrForStorage(const PtrRefSafetyModel &Model, QualType T, bool IgnoreARC=false)
Applies the memory-management exemptions that hold for a variable, member, or lambda capture (but not...
const FunctionProtoType * T
bool isSmartPtrClass(const std::string &Name)
std::optional< bool > isGetterOfSafePtr(const CXXMethodDecl *M)
std::string safeGetName(const T *ASTNode)
Definition ASTUtils.h:109
bool isNullPtr(const clang::Expr *E)
Definition ASTUtils.cpp:521
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
std::unique_ptr< PtrRefSafetyModel > makeRefPtrSafetyModel()
bool tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj, bool FollowLifetimeBound, 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, bool, bool)> callback)
This function de-facto defines a set of transformations that we consider safe (in heuristical sense).
Definition ASTUtils.cpp:464
std::unique_ptr< PtrRefSafetyModel > makeRetainPtrSafetyModel()
bool isConstOwnerPtrMemberExpr(const clang::Expr *E)
Definition ASTUtils.cpp:531