clang 24.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"
13#include "clang/AST/Decl.h"
14#include "clang/AST/DeclCXX.h"
19#include "clang/Lex/Lexer.h"
24#include "llvm/Support/SaveAndRestore.h"
25#include <optional>
26
27using namespace clang;
28using namespace ento;
29
30namespace {
31
32class RawPtrRefCallArgsChecker
33 : public Checker<check::ASTDecl<TranslationUnitDecl>> {
34 BugType Bug;
35
36 TrivialFunctionAnalysis TFA;
37 EnsureFunctionAnalysis EFA;
38
39protected:
40 mutable BugReporter *BR;
41 const std::unique_ptr<PtrRefSafetyModel> Model;
42
43public:
44 RawPtrRefCallArgsChecker(const char *description,
45 std::unique_ptr<PtrRefSafetyModel> Model)
46 : Bug(this, description, "WebKit coding guidelines"),
47 Model(std::move(Model)) {}
48
49 void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
50 BugReporter &BRArg) const {
51 BR = &BRArg;
52
53 // The calls to checkAST* from AnalysisConsumer don't
54 // visit template instantiations or lambda classes. We
55 // want to visit those, so we make our own RecursiveASTVisitor.
56 struct LocalVisitor : DynamicRecursiveASTVisitor {
57 const RawPtrRefCallArgsChecker *Checker;
58 Decl *DeclWithIssue{nullptr};
59
60 explicit LocalVisitor(const RawPtrRefCallArgsChecker *Checker)
61 : Checker(Checker) {
62 assert(Checker);
63 ShouldVisitTemplateInstantiations = true;
64 ShouldVisitImplicitCode = false;
65 }
66
67 bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override {
69 return true;
70 return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl);
71 }
72
73 bool TraverseDecl(Decl *D) override {
74 // A template pattern is checked through its instantiations, which are
75 // traversed from the TemplateDecl itself. In the pattern the callee of
76 // a call may still be an unresolved overload set and the type of an
77 // expression may still be dependent, neither of which can be reasoned
78 // about, so don't enter it at all.
79 if (D && !isa<TemplateDecl>(D) && D->isTemplated())
80 return true;
81 llvm::SaveAndRestore SavedDecl(DeclWithIssue);
82 if (D && (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)))
83 DeclWithIssue = D;
85 }
86
87 bool TraverseLambdaExpr(LambdaExpr *L) override {
89 if (!FTD)
90 return DynamicRecursiveASTVisitor::TraverseLambdaExpr(L);
91 // The body of a generic lambda is the pattern of its call operator,
92 // but it is reached from the LambdaExpr as a statement, so TraverseDecl
93 // never gets to skip it. Traverse the capture initializers, which are
94 // evaluated in the enclosing scope, and then the call operator itself,
95 // of which the pattern is skipped like any other and the instantiations
96 // are traversed. The initializers are traversed as expressions because
97 // the variable of an init capture is declared in the pattern.
98 for (unsigned I = 0, N = L->capture_size(); I != N; ++I) {
99 if (!(L->capture_begin() + I)->isExplicit())
100 continue;
101 if (auto *Init = L->capture_init_begin()[I];
102 Init && !TraverseStmt(Init))
103 return false;
104 }
105 return TraverseDecl(FTD);
106 }
107
108 bool VisitCallExpr(CallExpr *CE) override {
109 Checker->visitCallExpr(CE, DeclWithIssue);
110 return true;
111 }
112
113 bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
114 Checker->visitConstructExpr(CE, DeclWithIssue);
115 return true;
116 }
117
118 bool VisitTypedefDecl(TypedefDecl *TD) override {
119 if (auto *RTC = Checker->Model->retainTypeChecker())
120 RTC->visitTypedef(TD);
121 return true;
122 }
123
124 bool VisitObjCMessageExpr(ObjCMessageExpr *ObjCMsgExpr) override {
125 Checker->visitObjCMessageExpr(ObjCMsgExpr, DeclWithIssue);
126 return true;
127 }
128 };
129
130 LocalVisitor visitor(this);
131 if (auto *RTC = Model->retainTypeChecker())
132 RTC->visitTranslationUnitDecl(TUD);
133 visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
134 }
135
136 template <typename CallOrConstruct>
137 void visitCallOrConstructExpr(const CallOrConstruct *CE,
138 const FunctionDecl *F, const Decl *D) const {
139 if (F) {
140 unsigned ArgIdx = 0;
141 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE)) {
142 checkThisArg(F, MemberCallExpr, D);
143 } else if (isa<CXXOperatorCallExpr>(CE) && isa<CXXMethodDecl>(F)) {
144 // An overloaded member operator (e.g. lambda or std::function call
145 // operator) receives the receiver object as argument 0; start the
146 // parameter loop at 1 so we don't match it against the operator's
147 // first declared parameter.
148 auto *Receiver = CE->getArg(0);
149 checkThisArg(F, Receiver, Receiver->getType(), D);
150 ArgIdx = 1;
151 }
152
153 for (auto P = F->param_begin();
154 P < F->param_end() && ArgIdx < CE->getNumArgs(); ++P, ++ArgIdx) {
155 // TODO: attributes.
156 // if ((*P)->hasAttr<SafeRefCntblRawPtrAttr>())
157 // continue;
158 checkArg(F, CE->getArg(ArgIdx), (*P)->getType(), *P, D);
159 }
160 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
161 auto *Arg = CE->getArg(ArgIdx);
162 checkArg(F, Arg, Arg->getType(), nullptr, D);
163 }
164 }
165 }
166
167 void visitCallExpr(const CallExpr *CE, const Decl *D) const {
168 auto *Callee = CE->getDirectCallee();
169 if (shouldSkipCall(CE, Callee))
170 return;
171
172 if (Callee)
173 visitCallOrConstructExpr(CE, Callee, D);
174 else if (auto *Decl = CE->getCalleeDecl()) {
175 if (auto *FnType = Decl->getFunctionType()) {
176 if (auto *ProtoType = dyn_cast<FunctionProtoType>(FnType)) {
177 if (auto *MemberCallExpr = dyn_cast<CXXMemberCallExpr>(CE))
178 checkThisArg(nullptr, MemberCallExpr, D);
179 unsigned ArgIdx = 0;
180 for (auto PT = ProtoType->param_type_begin();
181 PT < ProtoType->param_type_end() && ArgIdx < CE->getNumArgs();
182 ++PT, ++ArgIdx)
183 checkArg(nullptr, CE->getArg(ArgIdx), *PT, nullptr, D);
184 for (; ArgIdx < CE->getNumArgs(); ++ArgIdx) {
185 auto *Arg = CE->getArg(ArgIdx);
186 checkArg(nullptr, Arg, Arg->getType(), nullptr, D);
187 }
188 }
189 }
190 }
191 }
192
193 void visitConstructExpr(const CXXConstructExpr *CE, const Decl *D) const {
194 auto *Constructor = CE->getConstructor();
195 if (shouldSkipCall(CE, Constructor))
196 return;
197 if (Constructor)
198 visitCallOrConstructExpr(CE, Constructor, D);
199 }
200
201 void visitObjCMessageExpr(const ObjCMessageExpr *E, const Decl *D) const {
202 if (BR->getSourceManager().isInSystemHeader(E->getExprLoc()))
203 return;
204
205 if (auto *Receiver = E->getInstanceReceiver()) {
206 std::optional<bool> IsUnsafe = Model->isUnsafePtr(E->getReceiverType());
207 const Expr *Origin = nullptr;
208 if (IsUnsafe && *IsUnsafe &&
209 !isPtrOriginSafe(Receiver, &Origin, E->getReceiverType())) {
210 if (isAllocInit(E))
211 return;
212 reportBugOnReceiver(E->getMethodDecl(), Receiver, D, Origin);
213 }
214 }
215
216 auto *MethodDecl = E->getMethodDecl();
217 if (!MethodDecl)
218 return;
219
220 auto ArgCount = E->getNumArgs();
221 for (unsigned i = 0; i < ArgCount; ++i) {
222 auto *Arg = E->getArg(i);
223 bool hasParam = i < MethodDecl->param_size();
224 auto *Param = hasParam ? MethodDecl->getParamDecl(i) : nullptr;
225 auto ArgType = Arg->getType();
226 std::optional<bool> IsUnsafe = Model->isUnsafePtr(ArgType);
227 if (!IsUnsafe || !(*IsUnsafe))
228 continue;
229 const Expr *Origin = nullptr;
230 if (isPtrOriginSafe(Arg, &Origin, ArgType))
231 continue;
232 reportBug(MethodDecl, Arg, Param, D, Origin);
233 }
234 }
235
236 static bool isRefCountingOperation(const CXXMethodDecl *MD) {
237 if (!MD)
238 return false;
239 auto name = safeGetName(MD);
240 return name == "ref" || name == "deref" ||
241 name == "incrementCheckedPtrCount" ||
242 name == "decrementCheckedPtrCount";
243 }
244
245 void checkThisArg(const NamedDecl *Callee,
246 const CXXMemberCallExpr *MemberCallExpr,
247 const Decl *DeclWithIssue) const {
248 if (isRefCountingOperation(MemberCallExpr->getMethodDecl()))
249 return;
250 checkThisArg(Callee, MemberCallExpr->getImplicitObjectArgument(),
251 MemberCallExpr->getObjectType(), DeclWithIssue);
252 }
253
254 void checkThisArg(const NamedDecl *Callee, const Expr *Receiver,
255 QualType ReceiverType, const Decl *DeclWithIssue) const {
256 // There is no ParmVarDecl for the implicit object parameter, so
257 // synthesize its type ('T&' per [over.match.funcs]) for the model to
258 // classify.
259 QualType ParamType = BR->getContext().getLValueReferenceType(
260 ReceiverType.getCanonicalType());
261 std::optional<bool> IsUnsafe = Model->isUnsafePtr(ParamType);
262 if (!IsUnsafe || !*IsUnsafe)
263 return;
264
265 const Expr *Origin = nullptr;
266 if (isPtrOriginSafe(Receiver, &Origin, ParamType))
267 return;
268
269 reportBugOnThis(Callee, Receiver, DeclWithIssue, Origin);
270 }
271
272 void checkArg(const NamedDecl *Callee, const Expr *Arg, QualType ParamType,
273 const ParmVarDecl *Param, const Decl *DeclWithIssue) const {
274 std::optional<bool> IsUncounted = Model->isUnsafePtr(ParamType);
275 if (!IsUncounted || !(*IsUncounted))
276 return;
277
278 if (auto *DefaultArg = dyn_cast<CXXDefaultArgExpr>(Arg))
279 Arg = DefaultArg->getExpr();
280
281 const Expr *Origin = nullptr;
282 if (isPtrOriginSafe(Arg, &Origin, ParamType))
283 return;
284
285 reportBug(Callee, Arg, Param, DeclWithIssue, Origin);
286 }
287
288 bool isPtrOriginSafe(const Expr *Arg, const Expr **Origin = nullptr,
289 QualType SinkType = QualType()) const {
290 return tryToFindPtrOrigin(
291 Arg, /*StopAtFirstRefCountedObj=*/true,
292 Model->checksForInteriorDestruction(),
293 [&](const clang::CXXRecordDecl *Record) {
294 return Model->isSafePtr(Record);
295 },
296 [&](const clang::QualType T) { return Model->isSafePtrType(T); },
297 [&](const clang::Decl *D) {
298 return Model->isSafeDecl(D, BR->getSourceManager());
299 },
300 // A temporary on the path to an argument's origin is safe: the full
301 // expression does not end until the call returns.
302 [&](const clang::Expr *ArgOrigin, bool IsSafe,
303 bool /*OriginDependsOnFullExpressionTemporary*/,
304 bool PtrIsLifetimeBoundToOrigin) {
305 if (IsSafe)
306 return true;
307 if (isNullPtr(ArgOrigin))
308 return true;
309 if (isa<IntegerLiteral>(ArgOrigin)) {
310 // FIXME: Check the value.
311 // foo(123)
312 return true;
313 }
314 if (isa<CXXBoolLiteralExpr>(ArgOrigin))
315 return true;
316 if (isa<ObjCStringLiteral>(ArgOrigin))
317 return true;
318 if (!Model->checksForInteriorDestruction() &&
319 originOutlivesCall(ArgOrigin))
320 return true;
321 if (EFA.isACallToEnsureFn(ArgOrigin)) {
322 auto *MCE = dyn_cast<CXXMemberCallExpr>(ArgOrigin);
323 assert(MCE);
324 if (isPtrOriginSafe(MCE->getImplicitObjectArgument()))
325 return true;
326 }
327 if (Model->isSafeExpr(ArgOrigin, PtrIsLifetimeBoundToOrigin, SinkType,
328 /*SinkMayEscape=*/false))
329 return true;
330 if (Origin && !*Origin)
331 *Origin = ArgOrigin;
332 return false;
333 });
334 }
335
336 template <typename CallOrConstruct>
337 bool shouldSkipCall(const CallOrConstruct *CE,
338 const FunctionDecl *Callee) const {
339 if (BR->getSourceManager().isInSystemHeader(CE->getExprLoc()))
340 return true;
341
342 if (Callee && TFA.isTrivial(Callee))
343 return true;
344
345 if (isTrivialBuiltinFunction(Callee))
346 return true;
347
348 if (CE->getNumArgs() == 0)
349 return false;
350
351 // If an assignment is problematic we should warn about the sole existence
352 // of object on LHS.
353 if (auto *MemberOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
354 // Note: assignemnt to built-in type isn't derived from CallExpr.
355 if (MemberOp->getOperator() ==
356 OO_Equal) { // Ignore assignment to Ref/RefPtr.
357 auto *callee = MemberOp->getDirectCallee();
358 if (auto *calleeDecl = dyn_cast<CXXMethodDecl>(callee)) {
359 if (const CXXRecordDecl *classDecl = calleeDecl->getParent()) {
360 if (Model->isSafePtr(classDecl))
361 return true;
362 }
363 }
364 }
365 if (MemberOp->isAssignmentOp())
366 return false;
367 }
368
369 if (!Callee)
370 return false;
371
372 if (isMethodOnWTFContainerType(Callee))
373 return true;
374
375 auto overloadedOperatorType = Callee->getOverloadedOperator();
376 if (overloadedOperatorType == OO_EqualEqual ||
377 overloadedOperatorType == OO_ExclaimEqual ||
378 overloadedOperatorType == OO_LessEqual ||
379 overloadedOperatorType == OO_GreaterEqual ||
380 overloadedOperatorType == OO_Spaceship ||
381 overloadedOperatorType == OO_AmpAmp ||
382 overloadedOperatorType == OO_PipePipe)
383 return true;
384
385 if (isCtorOfSafePtr(Callee) || isPtrConversion(Callee))
386 return true;
387
388 auto name = safeGetName(Callee);
389 if (name == "adoptRef" || name == "getPtr" || name == "WeakPtr" ||
390 name == "is" || name == "equal" || name == "hash" || name == "isType" ||
391 // FIXME: Most/all of these should be implemented via attributes.
392 name == "CFEqual" || name == "equalIgnoringASCIICase" ||
393 name == "equalIgnoringASCIICaseCommon" ||
394 name == "equalIgnoringNullity" || name == "toString")
395 return true;
396
397 return false;
398 }
399
400 bool isMethodOnWTFContainerType(const FunctionDecl *Decl) const {
402 return false;
403 auto *ClassDecl = Decl->getParent();
404 if (!ClassDecl || !isa<CXXRecordDecl>(ClassDecl))
405 return false;
406
407 auto *NsDecl = ClassDecl->getParent();
408 if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
409 return false;
410
411 auto MethodName = safeGetName(Decl);
412 auto ClsNameStr = safeGetName(ClassDecl);
413 StringRef ClsName = ClsNameStr; // FIXME: Make safeGetName return StringRef.
414 auto NamespaceName = safeGetName(NsDecl);
415 // FIXME: These should be implemented via attributes.
416 return NamespaceName == "WTF" &&
417 (MethodName == "find" || MethodName == "findIf" ||
418 MethodName == "reverseFind" || MethodName == "reverseFindIf" ||
419 MethodName == "findIgnoringASCIICase" || MethodName == "get" ||
420 MethodName == "inlineGet" || MethodName == "contains" ||
421 MethodName == "containsIf" ||
422 MethodName == "containsIgnoringASCIICase" ||
423 MethodName == "startsWith" || MethodName == "endsWith" ||
424 MethodName == "startsWithIgnoringASCIICase" ||
425 MethodName == "endsWithIgnoringASCIICase" ||
426 MethodName == "substring") &&
427 (ClsName.ends_with("Vector") || ClsName.ends_with("Set") ||
428 ClsName.ends_with("Map") || ClsName == "StringImpl" ||
429 ClsName.ends_with("String"));
430 }
431
432 void reportBug(const NamedDecl *Callee, const Expr *CallArg,
433 const ParmVarDecl *Param, const Decl *DeclWithIssue,
434 const Expr *Origin) const {
435 assert(CallArg);
436
438 llvm::raw_svector_ostream Os(Buf);
439
440 const std::string paramName = safeGetName(Param);
441 Os << "Function argument";
442 printArgument(Os, CallArg);
443 if (!paramName.empty() || Callee)
444 Os << " (";
445 if (!paramName.empty()) {
446 Os << "parameter ";
447 printQuotedQualifiedName(Os, Param);
448 }
449 if (Callee) {
450 if (!paramName.empty())
451 Os << " ";
452 Os << "to ";
453 printQuotedQualifiedName(Os, Callee);
454 }
455 if (!paramName.empty() || Callee)
456 Os << ")";
457 Os << " is a ";
458 Model->describeHazard(Os, Origin, CallArg->getType());
459
460 bool usesDefaultArgValue = isa<CXXDefaultArgExpr>(CallArg) && Param;
461 const SourceLocation SrcLocToReport =
462 usesDefaultArgValue ? Param->getDefaultArg()->getExprLoc()
463 : CallArg->getSourceRange().getBegin();
464
465 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
466 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
467 Report->addRange(CallArg->getSourceRange());
468 Report->setDeclWithIssue(DeclWithIssue);
469 BR->emitReport(std::move(Report));
470 }
471
472 void reportBugOnThis(const NamedDecl *Callee, const Expr *CallArg,
473 const Decl *DeclWithIssue, const Expr *Origin) const {
474 assert(CallArg);
475
476 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
477
479 llvm::raw_svector_ostream Os(Buf);
480 Os << "Function argument";
481 printArgument(Os, CallArg);
482 Os << " (parameter 'this'";
483 if (Callee) {
484 Os << " to ";
485 printQuotedQualifiedName(Os, Callee);
486 }
487 Os << ") is a ";
488 printHazardOrPointerTo(Os, CallArg, Origin);
489
490 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
491 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
492 Report->addRange(CallArg->getSourceRange());
493 Report->setDeclWithIssue(DeclWithIssue);
494 BR->emitReport(std::move(Report));
495 }
496
497 void reportBugOnReceiver(const NamedDecl *Callee, const Expr *CallArg,
498 const Decl *DeclWithIssue,
499 const Expr *Origin) const {
500 assert(CallArg);
501
502 const SourceLocation SrcLocToReport = CallArg->getSourceRange().getBegin();
503
505 llvm::raw_svector_ostream Os(Buf);
506 Os << "Receiver";
507 printArgument(Os, CallArg);
508 if (Callee) {
509 Os << " (to ";
510 printQuotedQualifiedName(Os, Callee);
511 Os << ")";
512 }
513 Os << " is a ";
514 printHazardOrPointerTo(Os, CallArg, Origin);
515
516 PathDiagnosticLocation BSLoc(SrcLocToReport, BR->getSourceManager());
517 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
518 Report->addRange(CallArg->getSourceRange());
519 Report->setDeclWithIssue(DeclWithIssue);
520 BR->emitReport(std::move(Report));
521 }
522
523 void printHazardOrPointerTo(llvm::raw_svector_ostream &Os,
524 const Expr *CallArg, const Expr *Origin) const {
525 if (Model->checksForInteriorDestruction()) {
526 Model->describeHazard(Os, Origin, CallArg->getType());
527 return;
528 }
529 // 'this' is a pointer even when the call is spelled with '.', so don't
530 // infer pointer vs reference from the argument type.
531 Os << "raw pointer to " << Model->typeName() << " ";
532 printTypeName(Os, CallArg->getType());
533 }
534
535 void printArgument(llvm::raw_svector_ostream &Os, const Expr *Arg) const {
537 llvm::raw_svector_ostream ArgOs(Buf);
538 Arg->printPretty(ArgOs, /*Helper=*/nullptr,
540 StringRef ArgCode = ArgOs.str();
541 if (ArgCode.contains('\n'))
542 return;
543 ArgCode = ArgCode.take_front(50);
544 if (ArgCode.size() == 50)
545 Os << " '" << ArgCode << "...'";
546 else
547 Os << " '" << ArgCode << "'";
548 }
549};
550
551class UncountedCallArgsChecker final : public RawPtrRefCallArgsChecker {
552public:
553 UncountedCallArgsChecker()
554 : RawPtrRefCallArgsChecker("Uncounted call argument for a raw "
555 "pointer/reference parameter",
557};
558
559class UncheckedCallArgsChecker final : public RawPtrRefCallArgsChecker {
560public:
561 UncheckedCallArgsChecker()
562 : RawPtrRefCallArgsChecker("Unchecked call argument for a raw "
563 "pointer/reference parameter",
565};
566
567class UnretainedCallArgsChecker final : public RawPtrRefCallArgsChecker {
568public:
569 UnretainedCallArgsChecker()
570 : RawPtrRefCallArgsChecker("Unretained call argument for a raw "
571 "pointer/reference parameter",
573};
574
575class UnborrowedCallArgsChecker final : public RawPtrRefCallArgsChecker {
576public:
577 UnborrowedCallArgsChecker()
578 : RawPtrRefCallArgsChecker("Unborrowed call argument for a raw "
579 "pointer/reference parameter",
581};
582
583} // namespace
584
585void ento::registerUncountedCallArgsChecker(CheckerManager &Mgr) {
586 Mgr.registerChecker<UncountedCallArgsChecker>();
587}
588
589bool ento::shouldRegisterUncountedCallArgsChecker(const CheckerManager &) {
590 return true;
591}
592
593void ento::registerUncheckedCallArgsChecker(CheckerManager &Mgr) {
594 Mgr.registerChecker<UncheckedCallArgsChecker>();
595}
596
597bool ento::shouldRegisterUncheckedCallArgsChecker(const CheckerManager &) {
598 return true;
599}
600
601void ento::registerUnretainedCallArgsChecker(CheckerManager &Mgr) {
602 Mgr.registerChecker<UnretainedCallArgsChecker>();
603}
604
605bool ento::shouldRegisterUnretainedCallArgsChecker(const CheckerManager &) {
606 return true;
607}
608
609void ento::registerUnborrowedCallArgsChecker(CheckerManager &Mgr) {
610 Mgr.registerChecker<UnborrowedCallArgsChecker>();
611}
612
613bool ento::shouldRegisterUnborrowedCallArgsChecker(const CheckerManager &) {
614 return true;
615}
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.
Defines the SourceManager interface.
static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP, llvm::raw_ostream &OS, bool IncludeType)
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:905
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
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
FunctionTemplateDecl * getDependentLambdaCallOperator() const
Retrieve the dependent lambda call operator of the closure type if this is a templated closure type.
Definition DeclCXX.cpp:1739
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3216
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3195
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3203
Decl * getCalleeDecl()
Definition Expr.h:3189
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2108
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isTemplated() const
Determine whether this declaration is a templated entity (whether it is.
Definition DeclBase.cpp:308
virtual bool TraverseDecl(MaybeConst< Decl > *D)
This represents one expression.
Definition Expr.h:114
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:146
Represents a function declaration or definition.
Definition Decl.h:2082
param_iterator param_begin()
Definition Decl.h:2959
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
This represents a decl that may have a name.
Definition Decl.h:276
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition ExprObjC.h:1435
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition ExprObjC.h:1300
const ObjCMethodDecl * getMethodDecl() const
Definition ExprObjC.h:1396
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:1422
Represents a parameter to a function.
Definition Decl.h:1832
QualType getCanonicalType() const
Definition TypeBase.h:8630
Encodes a location in the source.
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
bool isTrivial(const Decl *D) const
const SourceManager & getSourceManager()
ASTContext & getContext()
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.
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
Top level wrappers for InstallAPI frontend operations.
bool isCtorOfSafePtr(const clang::FunctionDecl *F)
bool isTrivialBuiltinFunction(const FunctionDecl *F)
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)
const FunctionProtoType * T
bool isSmartPtrClass(const std::string &Name)
bool originOutlivesCall(const Expr *E)
For E referring to a ref-countable/-counted pointer/reference we return whether the pointee outlives ...
Definition ASTUtils.cpp:495
void printTypeName(llvm::raw_ostream &Os, const QualType QT)
std::string safeGetName(const T *ASTNode)
Definition ASTUtils.h:109
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:478
bool isAllocInit(const Expr *E, const Expr **InnerExpr)
Definition ASTUtils.cpp:589
std::unique_ptr< PtrRefSafetyModel > makeRetainPtrSafetyModel()