clang 23.0.0git
PtrTypesSemantics.cpp
Go to the documentation of this file.
1//=======- PtrTypesSemantics.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 "PtrTypesSemantics.h"
10#include "ASTUtils.h"
11#include "clang/AST/Attr.h"
13#include "clang/AST/Decl.h"
14#include "clang/AST/DeclCXX.h"
15#include "clang/AST/ExprCXX.h"
18#include <optional>
19
20using namespace clang;
21
22namespace {
23
24bool hasPublicMethodInBaseClass(const CXXRecordDecl *R, StringRef NameToMatch) {
25 assert(R);
26 assert(R->hasDefinition());
27
28 for (const CXXMethodDecl *MD : R->methods()) {
29 const auto MethodName = safeGetName(MD);
30 if (MethodName == NameToMatch && MD->getAccess() == AS_public)
31 return true;
32 }
33 return false;
34}
35
36} // namespace
37
38namespace clang {
39
40std::optional<const clang::CXXRecordDecl *>
41hasPublicMethodInBase(const CXXBaseSpecifier *Base, StringRef NameToMatch) {
42 assert(Base);
43
44 const Type *T = Base->getType().getTypePtrOrNull();
45 if (!T)
46 return std::nullopt;
47
48 const CXXRecordDecl *R = T->getAsCXXRecordDecl();
49 if (!R) {
50 auto CT = Base->getType().getCanonicalType();
51 if (auto *TST = dyn_cast<TemplateSpecializationType>(CT)) {
52 auto TmplName = TST->getTemplateName();
53 if (!TmplName.isNull()) {
54 if (auto *TD = TmplName.getAsTemplateDecl())
55 R = dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
56 }
57 }
58 if (!R)
59 return std::nullopt;
60 }
61 if (!R->hasDefinition())
62 return std::nullopt;
63
64 return hasPublicMethodInBaseClass(R, NameToMatch) ? R : nullptr;
65}
66
67std::optional<bool> isSmartPtrCompatible(const CXXRecordDecl *R,
68 StringRef IncMethodName,
69 StringRef DecMethodName) {
70 assert(R);
71
72 R = R->getDefinition();
73 if (!R)
74 return std::nullopt;
75
76 bool hasRef = hasPublicMethodInBaseClass(R, IncMethodName);
77 bool hasDeref = hasPublicMethodInBaseClass(R, DecMethodName);
78 if (hasRef && hasDeref)
79 return true;
80
81 CXXBasePaths Paths;
82 Paths.setOrigin(const_cast<CXXRecordDecl *>(R));
83
84 bool AnyInconclusiveBase = false;
85 const auto hasPublicRefInBase = [&](const CXXBaseSpecifier *Base,
86 CXXBasePath &) {
87 auto hasRefInBase = clang::hasPublicMethodInBase(Base, IncMethodName);
88 if (!hasRefInBase) {
89 AnyInconclusiveBase = true;
90 return false;
91 }
92 return (*hasRefInBase) != nullptr;
93 };
94
95 hasRef = hasRef || R->lookupInBases(hasPublicRefInBase, Paths,
96 /*LookupInDependent =*/true);
97 if (AnyInconclusiveBase)
98 return std::nullopt;
99
100 Paths.clear();
101 const auto hasPublicDerefInBase = [&](const CXXBaseSpecifier *Base,
102 CXXBasePath &) {
103 auto hasDerefInBase = clang::hasPublicMethodInBase(Base, DecMethodName);
104 if (!hasDerefInBase) {
105 AnyInconclusiveBase = true;
106 return false;
107 }
108 return (*hasDerefInBase) != nullptr;
109 };
110 hasDeref = hasDeref || R->lookupInBases(hasPublicDerefInBase, Paths,
111 /*LookupInDependent =*/true);
112 if (AnyInconclusiveBase)
113 return std::nullopt;
114
115 return hasRef && hasDeref;
116}
117
118std::optional<bool> isRefCountable(const clang::CXXRecordDecl *R) {
119 return isSmartPtrCompatible(R, "ref", "deref");
120}
121
122std::optional<bool> isCheckedPtrCapable(const clang::CXXRecordDecl *R) {
123 return isSmartPtrCompatible(R, "incrementCheckedPtrCount",
124 "decrementCheckedPtrCount");
125}
126
127bool isRefType(const std::string &Name) {
128 return Name == "Ref" || Name == "RefAllowingPartiallyDestroyed" ||
129 Name == "RefPtr" || Name == "RefPtrAllowingPartiallyDestroyed";
130}
131
132bool isRetainPtrOrOSPtr(const std::string &Name) {
133 return Name == "RetainPtr" || Name == "RetainPtrArc" ||
134 Name == "OSObjectPtr" || Name == "OSObjectPtrArc";
135}
136
137bool isCheckedPtr(const std::string &Name) {
138 return Name == "CheckedPtr" || Name == "CheckedRef";
139}
140
141bool isOwnerPtr(const std::string &Name) {
142 return isRefType(Name) || isCheckedPtr(Name) || Name == "unique_ptr" ||
143 Name == "UniqueRef" || Name == "LazyUniqueRef";
144}
145
146bool isSmartPtrClass(const std::string &Name) {
147 return isRefType(Name) || isCheckedPtr(Name) || isRetainPtrOrOSPtr(Name) ||
148 Name == "WeakPtr" || Name == "WeakPtrFactory" ||
149 Name == "WeakPtrFactoryWithBitField" || Name == "WeakPtrImplBase" ||
150 Name == "WeakPtrImplBaseSingleThread" || Name == "ThreadSafeWeakPtr" ||
151 Name == "ThreadSafeWeakOrStrongPtr" ||
152 Name == "ThreadSafeWeakPtrControlBlock" ||
153 Name == "ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr";
154}
155
157 assert(F);
158 const std::string &FunctionName = safeGetName(F);
159
160 return isRefType(FunctionName) || FunctionName == "adoptRef" ||
161 FunctionName == "UniqueRef" || FunctionName == "makeUniqueRef" ||
162 FunctionName == "makeUniqueRefWithoutFastMallocCheck"
163
164 || FunctionName == "String" || FunctionName == "AtomString" ||
165 FunctionName == "UniqueString"
166 // FIXME: Implement as attribute.
167 || FunctionName == "Identifier";
168}
169
171 assert(F);
172 return isCheckedPtr(safeGetName(F));
173}
174
176 const std::string &FunctionName = safeGetName(F);
177 return FunctionName == "RetainPtr" || FunctionName == "adoptNS" ||
178 FunctionName == "adoptCF" || FunctionName == "retainPtr" ||
179 FunctionName == "RetainPtrArc" || FunctionName == "adoptNSArc" ||
180 FunctionName == "adoptOSObject" || FunctionName == "adoptOSObjectArc";
181}
182
187
189 auto FnName = safeGetName(F);
190 auto *Namespace = F->getParent();
191 if (!Namespace)
192 return false;
193 auto *TUDeck = Namespace->getParent();
194 if (!isa_and_nonnull<TranslationUnitDecl>(TUDeck))
195 return false;
196 auto NsName = safeGetName(Namespace);
197 return (NsName == "WTF" || NsName == "std") && FnName == "move";
198}
199
200template <typename Predicate>
201static bool isPtrOfType(const clang::QualType T, Predicate Pred) {
202 QualType type = T;
203 while (!type.isNull()) {
204 if (auto *SpecialT = type->getAs<TemplateSpecializationType>()) {
205 auto *Decl = SpecialT->getTemplateName().getAsTemplateDecl();
206 return Decl && Pred(Decl->getNameAsString());
207 } else if (auto *DTS = type->getAs<DeducedTemplateSpecializationType>()) {
208 auto *Decl = DTS->getTemplateName().getAsTemplateDecl();
209 return Decl && Pred(Decl->getNameAsString());
210 } else
211 break;
212 }
213 return false;
214}
215
217 return isPtrOfType(
218 T, [](auto Name) { return isRefType(Name) || isCheckedPtr(Name); });
219}
220
222 return isPtrOfType(T, [](auto Name) { return isRetainPtrOrOSPtr(Name); });
223}
224
226 return isPtrOfType(T, [](auto Name) { return isOwnerPtr(Name); });
227}
228
229std::optional<bool> isUncounted(const QualType T) {
230 if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
231 if (auto *Decl = Subst->getAssociatedDecl()) {
233 return false;
234 }
235 }
236 return isUncounted(T->getAsCXXRecordDecl());
237}
238
239std::optional<bool> isUnchecked(const QualType T) {
240 if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
241 if (auto *Decl = Subst->getAssociatedDecl()) {
243 return false;
244 }
245 }
246 return isUnchecked(T->getAsCXXRecordDecl());
247}
248
250 const TranslationUnitDecl *TUD) {
251 IsARCEnabled = TUD->getLangOpts().ObjCAutoRefCount;
252 DefaultSynthProperties = TUD->getLangOpts().ObjCDefaultSynthProperties;
253}
254
256 auto QT = TD->getUnderlyingType();
257 if (!QT->isPointerType())
258 return;
259
260 auto PointeeQT = QT->getPointeeType();
261 const RecordType *RT = PointeeQT->getAsCanonical<RecordType>();
262 if (!RT) {
263 if (TD->hasAttr<ObjCBridgeAttr>() || TD->hasAttr<ObjCBridgeMutableAttr>()) {
264 RecordlessTypes.insert(TD->getASTContext()
266 /*Qualifier=*/std::nullopt, TD)
267 .getTypePtr());
268 }
269 return;
270 }
271
272 for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
273 if (Redecl->getAttr<ObjCBridgeAttr>() ||
274 Redecl->getAttr<ObjCBridgeMutableAttr>()) {
275 CFPointees.insert(RT);
276 return;
277 }
278 }
279}
280
281bool RetainTypeChecker::isUnretained(const QualType QT, bool ignoreARC) {
282 if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC))
283 return true;
284 if (auto *RT = dyn_cast_or_null<RecordType>(
286 return CFPointees.contains(RT);
287 return RecordlessTypes.contains(QT.getTypePtr());
288}
289
290std::optional<bool> isUncounted(const CXXRecordDecl* Class)
291{
292 // Keep isRefCounted first as it's cheaper.
293 if (!Class || isRefCounted(Class))
294 return false;
295
296 std::optional<bool> IsRefCountable = isRefCountable(Class);
297 if (!IsRefCountable)
298 return std::nullopt;
299
300 return (*IsRefCountable);
301}
302
303std::optional<bool> isUnchecked(const CXXRecordDecl *Class) {
304 if (!Class || isCheckedPtr(Class))
305 return false; // Cheaper than below
307}
308
309std::optional<bool> isUncountedPtr(const QualType T) {
310 if (T->isPointerType() || T->isReferenceType()) {
311 if (auto *CXXRD = T->getPointeeCXXRecordDecl())
312 return isUncounted(CXXRD);
313 }
314 return false;
315}
316
317std::optional<bool> isUncheckedPtr(const QualType T) {
318 if (T->isPointerType() || T->isReferenceType()) {
319 if (auto *CXXRD = T->getPointeeCXXRecordDecl())
320 return isUnchecked(CXXRD);
321 }
322 return false;
323}
324
325std::optional<bool> isGetterOfSafePtr(const CXXMethodDecl *M) {
326 assert(M);
327
328 if (isa<CXXMethodDecl>(M)) {
329 const CXXRecordDecl *calleeMethodsClass = M->getParent();
330 auto className = safeGetName(calleeMethodsClass);
331 auto method = safeGetName(M);
332
333 if (isCheckedPtr(className) && (method == "get" || method == "ptr"))
334 return true;
335
336 if ((isRefType(className) && (method == "get" || method == "ptr")) ||
337 ((className == "String" || className == "AtomString" ||
338 className == "AtomStringImpl" || className == "UniqueString" ||
339 className == "UniqueStringImpl" || className == "Identifier") &&
340 method == "impl"))
341 return true;
342
343 if (isRetainPtrOrOSPtr(className) && method == "get")
344 return true;
345
346 // Ref<T> -> T conversion
347 // FIXME: Currently allowing any Ref<T> -> whatever cast.
348 if (isRefType(className)) {
349 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
350 auto QT = maybeRefToRawOperator->getConversionType();
351 auto *T = QT.getTypePtrOrNull();
352 return T && (T->isPointerType() || T->isReferenceType());
353 }
354 }
355
356 if (isCheckedPtr(className)) {
357 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
358 auto QT = maybeRefToRawOperator->getConversionType();
359 auto *T = QT.getTypePtrOrNull();
360 return T && (T->isPointerType() || T->isReferenceType());
361 }
362 }
363
364 if (isRetainPtrOrOSPtr(className)) {
365 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
366 auto QT = maybeRefToRawOperator->getConversionType();
367 auto *T = QT.getTypePtrOrNull();
368 return T && (T->isPointerType() || T->isReferenceType() ||
369 T->isObjCObjectPointerType());
370 }
371 }
372 }
373 return false;
374}
375
377 assert(R);
378 if (auto *TmplR = R->getTemplateInstantiationPattern()) {
379 // FIXME: String/AtomString/UniqueString
380 const auto &ClassName = safeGetName(TmplR);
381 return isRefType(ClassName);
382 }
383 return false;
384}
385
387 assert(R);
388 if (auto *TmplR = R->getTemplateInstantiationPattern()) {
389 const auto &ClassName = safeGetName(TmplR);
390 return isCheckedPtr(ClassName);
391 }
392 return false;
393}
394
396 assert(R);
397 if (auto *TmplR = R->getTemplateInstantiationPattern())
398 return isRetainPtrOrOSPtr(safeGetName(TmplR));
399 return false;
400}
401
402bool isSmartPtr(const CXXRecordDecl *R) {
403 assert(R);
404 if (auto *TmplR = R->getTemplateInstantiationPattern())
405 return isSmartPtrClass(safeGetName(TmplR));
406 return false;
407}
408
414
416 auto RetType = FD->getReturnType();
417 auto *Attr = dyn_cast_or_null<AttributedType>(RetType.getTypePtrOrNull());
418 if (!Attr)
420 auto *AnnotateType = dyn_cast_or_null<AnnotateTypeAttr>(Attr->getAttr());
421 if (!AnnotateType)
423 auto Annotation = AnnotateType->getAnnotation();
424 if (Annotation == "webkit.pointerconversion")
426 if (Annotation == "webkit.nodelete")
429}
430
432 assert(F);
433 if (isCtorOfRefCounted(F))
434 return true;
435
436 // FIXME: check # of params == 1
437 const auto FunctionName = safeGetName(F);
438 if (FunctionName == "getPtr" || FunctionName == "WeakPtr" ||
439 FunctionName == "dynamicDowncast" || FunctionName == "downcast" ||
440 FunctionName == "checkedDowncast" || FunctionName == "bit_cast" ||
441 FunctionName == "uncheckedDowncast" || FunctionName == "bitwise_cast" ||
442 FunctionName == "bridge_cast" || FunctionName == "bridge_id_cast" ||
443 FunctionName == "dynamic_cf_cast" || FunctionName == "checked_cf_cast" ||
444 FunctionName == "dynamic_objc_cast" ||
445 FunctionName == "checked_objc_cast")
446 return true;
447
449 return true;
450
451 return false;
452}
453
457
459 if (!F || !F->getDeclName().isIdentifier())
460 return false;
461 auto Name = F->getName();
462 return Name.starts_with("__builtin") || Name == "__libcpp_verbose_abort" ||
463 Name.starts_with("os_log") || Name.starts_with("_os_log");
464}
465
466bool isSingleton(const NamedDecl *F) {
467 assert(F);
468 // FIXME: check # of params == 1
469 if (auto *MethodDecl = dyn_cast<CXXMethodDecl>(F)) {
470 if (!MethodDecl->isStatic())
471 return false;
472 }
473 const auto &NameStr = safeGetName(F);
474 StringRef Name = NameStr; // FIXME: Make safeGetName return StringRef.
475 return Name == "singleton" || Name.ends_with("Singleton");
476}
477
478// We only care about statements so let's use the simple
479// (non-recursive) visitor.
481 : public ConstStmtVisitor<TrivialFunctionAnalysisVisitor, bool> {
482
483 // Returns false if at least one child is non-trivial.
484 bool VisitChildren(const Stmt *S) {
485 for (const Stmt *Child : S->children()) {
486 if (Child && !Visit(Child))
487 return false;
488 }
489
490 return true;
491 }
492
493 template <typename StmtOrDecl, typename CheckFunction>
494 bool WithCachedResult(const StmtOrDecl *S, CheckFunction Function) {
495 auto CacheIt = Cache.find(S);
496 if (CacheIt != Cache.end())
497 return CacheIt->second;
498
499 // Treat a recursive statement to be trivial until proven otherwise.
500 auto [RecursiveIt, IsNew] = RecursiveFn.insert(std::make_pair(S, true));
501 if (!IsNew)
502 return RecursiveIt->second;
503
504 bool Result = Function();
505
506 if (!Result) {
507 for (auto &It : RecursiveFn)
508 It.second = false;
509 }
510 RecursiveIt = RecursiveFn.find(S);
511 assert(RecursiveIt != RecursiveFn.end());
512 Result = RecursiveIt->second;
513 RecursiveFn.erase(RecursiveIt);
514 Cache[S] = Result;
515
516 return Result;
517 }
518
519public:
520 using CacheTy = TrivialFunctionAnalysis::CacheTy;
521
522 TrivialFunctionAnalysisVisitor(CacheTy &Cache) : Cache(Cache) {}
523
524 bool IsFunctionTrivial(const Decl *D) {
525 if (auto *FnDecl = dyn_cast<FunctionDecl>(D)) {
526 if (isNoDeleteFunction(FnDecl))
527 return true;
528 if (FnDecl->isVirtualAsWritten())
529 return false;
530 }
531 return WithCachedResult(D, [&]() {
532 if (auto *CtorDecl = dyn_cast<CXXConstructorDecl>(D)) {
533 for (auto *CtorInit : CtorDecl->inits()) {
534 if (!Visit(CtorInit->getInit()))
535 return false;
536 }
537 }
538 const Stmt *Body = D->getBody();
539 if (!Body)
540 return false;
541 return Visit(Body);
542 });
543 }
544
545 bool IsStatementTrivial(const Stmt *S) {
546 auto CacheIt = Cache.find(S);
547 if (CacheIt != Cache.end())
548 return CacheIt->second;
549 bool Result = Visit(S);
550 Cache[S] = Result;
551 return Result;
552 }
553
554 bool VisitStmt(const Stmt *S) {
555 // All statements are non-trivial unless overriden later.
556 // Don't even recurse into children by default.
557 return false;
558 }
559
561 // Ignore attributes.
562 return Visit(AS->getSubStmt());
563 }
564
566 // A compound statement is allowed as long each individual sub-statement
567 // is trivial.
568 return WithCachedResult(CS, [&]() { return VisitChildren(CS); });
569 }
570
572 return WithCachedResult(CBS, [&]() { return VisitChildren(CBS); });
573 }
574
575 bool VisitReturnStmt(const ReturnStmt *RS) {
576 // A return statement is allowed as long as the return value is trivial.
577 if (auto *RV = RS->getRetValue())
578 return Visit(RV);
579 return true;
580 }
581
582 bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
583 bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
584 bool VisitIfStmt(const IfStmt *IS) {
585 return WithCachedResult(IS, [&]() { return VisitChildren(IS); });
586 }
587 bool VisitForStmt(const ForStmt *FS) {
588 return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
589 }
591 return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
592 }
593 bool VisitWhileStmt(const WhileStmt *WS) {
594 return WithCachedResult(WS, [&]() { return VisitChildren(WS); });
595 }
596 bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
597 bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
598 bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
599
600 // break, continue, goto, and label statements are always trivial.
601 bool VisitBreakStmt(const BreakStmt *) { return true; }
602 bool VisitContinueStmt(const ContinueStmt *) { return true; }
603 bool VisitGotoStmt(const GotoStmt *) { return true; }
604 bool VisitLabelStmt(const LabelStmt *) { return true; }
605
607 // Unary operators are trivial if its operand is trivial except co_await.
608 return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr());
609 }
610
612 // Binary operators are trivial if their operands are trivial.
613 return Visit(BO->getLHS()) && Visit(BO->getRHS());
614 }
615
617 // Compound assignment operator such as |= is trivial if its
618 // subexpresssions are trivial.
619 return VisitChildren(CAO);
620 }
621
623 return VisitChildren(ASE);
624 }
625
627 // Ternary operators are trivial if their conditions & values are trivial.
628 return VisitChildren(CO);
629 }
630
631 bool VisitAtomicExpr(const AtomicExpr *E) { return VisitChildren(E); }
632
634 // Any static_assert is considered trivial.
635 return true;
636 }
637
638 bool VisitCallExpr(const CallExpr *CE) {
639 if (!checkArguments(CE))
640 return false;
641
642 auto *Callee = CE->getDirectCallee();
643 if (!Callee)
644 return false;
645
646 if (isPtrConversion(Callee))
647 return true;
648
649 const auto &Name = safeGetName(Callee);
650
651 if (Callee->isInStdNamespace() &&
652 (Name == "addressof" || Name == "forward" || Name == "move"))
653 return true;
654
655 if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
656 Name == "WTFReportBacktrace" ||
657 Name == "WTFCrashWithSecurityImplication" || Name == "WTFCrash" ||
658 Name == "WTFReportAssertionFailure" || Name == "isMainThread" ||
659 Name == "isMainThreadOrGCThread" || Name == "isMainRunLoop" ||
660 Name == "isWebThread" || Name == "isUIThread" ||
661 Name == "mayBeGCThread" || Name == "compilerFenceForCrash" ||
663 return true;
664
665 return IsFunctionTrivial(Callee);
666 }
667
668 bool VisitGCCAsmStmt(const GCCAsmStmt *AS) {
669 return AS->getAsmString() == "brk #0xc471";
670 }
671
672 bool
674 // Non-type template paramter is compile time constant and trivial.
675 return true;
676 }
677
679 return VisitChildren(E);
680 }
681
683 // A predefined identifier such as "func" is considered trivial.
684 return true;
685 }
686
688 // offsetof(T, D) is considered trivial.
689 return true;
690 }
691
693 if (!checkArguments(MCE))
694 return false;
695
696 bool TrivialThis = Visit(MCE->getImplicitObjectArgument());
697 if (!TrivialThis)
698 return false;
699
700 auto *Callee = MCE->getMethodDecl();
701 if (!Callee)
702 return false;
703
704 auto Name = safeGetName(Callee);
705 if (Name == "ref" || Name == "incrementCheckedPtrCount")
706 return true;
707
708 std::optional<bool> IsGetterOfRefCounted = isGetterOfSafePtr(Callee);
709 if (IsGetterOfRefCounted && *IsGetterOfRefCounted)
710 return true;
711
712 // Recursively descend into the callee to confirm that it's trivial as well.
713 return IsFunctionTrivial(Callee);
714 }
715
717 if (!checkArguments(OCE))
718 return false;
719 auto *Callee = OCE->getCalleeDecl();
720 if (!Callee)
721 return false;
722 // Recursively descend into the callee to confirm that it's trivial as well.
723 return IsFunctionTrivial(Callee);
724 }
725
727 if (auto *Expr = E->getExpr()) {
728 if (!Visit(Expr))
729 return false;
730 }
731 return true;
732 }
733
734 bool checkArguments(const CallExpr *CE) {
735 for (const Expr *Arg : CE->arguments()) {
736 if (Arg && !Visit(Arg))
737 return false;
738 }
739 return true;
740 }
741
743 for (const Expr *Arg : CE->arguments()) {
744 if (Arg && !Visit(Arg))
745 return false;
746 }
747
748 // Recursively descend into the callee to confirm that it's trivial.
749 return IsFunctionTrivial(CE->getConstructor());
750 }
751
755
756 bool VisitCXXNewExpr(const CXXNewExpr *NE) { return VisitChildren(NE); }
757
759 return Visit(ICE->getSubExpr());
760 }
761
763 return Visit(ECE->getSubExpr());
764 }
765
767 return Visit(VMT->getSubExpr());
768 }
769
771 if (auto *Temp = BTE->getTemporary()) {
772 if (!TrivialFunctionAnalysis::isTrivialImpl(Temp->getDestructor(), Cache))
773 return false;
774 }
775 return Visit(BTE->getSubExpr());
776 }
777
779 return Visit(AILE->getCommonExpr()) && Visit(AILE->getSubExpr());
780 }
781
783 return true; // The current array index in VisitArrayInitLoopExpr is always
784 // trivial.
785 }
786
788 return Visit(OVE->getSourceExpr());
789 }
790
792 return Visit(EWC->getSubExpr());
793 }
794
795 bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
796
798 for (const Expr *Child : ILE->inits()) {
799 if (Child && !Visit(Child))
800 return false;
801 }
802 return true;
803 }
804
805 bool VisitMemberExpr(const MemberExpr *ME) {
806 // Field access is allowed but the base pointer may itself be non-trivial.
807 return Visit(ME->getBase());
808 }
809
810 bool VisitCXXThisExpr(const CXXThisExpr *CTE) {
811 // The expression 'this' is always trivial, be it explicit or implicit.
812 return true;
813 }
814
816 // nullptr is trivial.
817 return true;
818 }
819
820 bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
821 // The use of a variable is trivial.
822 return true;
823 }
824
825 // Constant literal expressions are always trivial
826 bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
827 bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
828 bool VisitFixedPointLiteral(const FixedPointLiteral *E) { return true; }
829 bool VisitCharacterLiteral(const CharacterLiteral *E) { return true; }
830 bool VisitStringLiteral(const StringLiteral *E) { return true; }
831 bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return true; }
832
834 // Constant expressions are trivial.
835 return true;
836 }
837
839 // An implicit value initialization is trvial.
840 return true;
841 }
842
843private:
844 CacheTy &Cache;
845 CacheTy RecursiveFn;
846};
847
848bool TrivialFunctionAnalysis::isTrivialImpl(
849 const Decl *D, TrivialFunctionAnalysis::CacheTy &Cache) {
851 return V.IsFunctionTrivial(D);
852}
853
854bool TrivialFunctionAnalysis::isTrivialImpl(
855 const Stmt *S, TrivialFunctionAnalysis::CacheTy &Cache) {
857 return V.IsStatementTrivial(S);
858}
859
860} // namespace clang
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
TypePropertyCache< Private > Cache
Definition Type.cpp:4786
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
Represents the index of the current element of an array being initialized by an ArrayInitLoopExpr.
Definition Expr.h:6021
Represents a loop initializing the elements of an array.
Definition Expr.h:5968
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:5983
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:5988
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2721
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6880
Attr - This represents one attribute.
Definition Attr.h:46
Represents an attribute applied to a statement.
Definition Stmt.h:2195
Stmt * getSubStmt()
Definition Stmt.h:2231
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4038
Expr * getLHS() const
Definition Expr.h:4088
Expr * getRHS() const
Definition Expr.h:4090
BreakStmt - This represents a break.
Definition Stmt.h:3127
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
void setOrigin(const CXXRecordDecl *Rec)
void clear()
Clear the base-paths results.
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents binding an expression to a temporary.
Definition ExprCXX.h:1493
CXXTemporary * getTemporary()
Definition ExprCXX.h:1511
const Expr * getSubExpr() const
Definition ExprCXX.h:1515
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition ExprCXX.h:723
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
arg_range arguments()
Definition ExprCXX.h:1672
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1270
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1751
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
Definition ExprCXX.h:1788
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:741
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:722
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2355
The null pointer literal (C++11 [lex.nullptr])
Definition ExprCXX.h:768
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:84
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
method_range methods() const
Definition DeclCXX.h:650
CXXRecordDecl * getDefinition() const
Definition DeclCXX.h:548
const CXXRecordDecl * getTemplateInstantiationPattern() const
Retrieve the record declaration from which this record could be instantiated.
Definition DeclCXX.cpp:2075
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
bool hasDefinition() const
Definition DeclCXX.h:561
Represents the this expression in C++.
Definition ExprCXX.h:1154
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3126
arg_range arguments()
Definition Expr.h:3195
Decl * getCalleeDecl()
Definition Expr.h:3120
CaseStmt - Represent a case statement.
Definition Stmt.h:1912
Expr * getSubExpr()
Definition Expr.h:3726
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4300
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1732
ConditionalOperator - The ?
Definition Expr.h:4391
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition Expr.h:1082
ContinueStmt - This represents a continue.
Definition Stmt.h:3111
Represents the body of a coroutine.
Definition StmtCXX.h:320
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1623
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:546
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition DeclBase.h:1087
bool hasAttr() const
Definition DeclBase.h:577
const LangOptions & getLangOpts() const LLVM_READONLY
Helper to get the language options from the ASTContext.
Definition DeclBase.cpp:552
bool isIdentifier() const
Predicate functions for querying what type of name this is.
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2824
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3928
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
Definition ExprCXX.h:3661
This represents one expression.
Definition Expr.h:112
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2880
const Expr * getSubExpr() const
Definition Expr.h:1062
Represents a function declaration or definition.
Definition Decl.h:2000
QualType getReturnType() const
Definition Decl.h:2845
This represents a GCC inline-assembly statement extension.
Definition Stmt.h:3438
std::string getAsmString() const
Definition Stmt.cpp:569
GotoStmt - This represents a direct goto.
Definition Stmt.h:2961
IfStmt - This represents an if/then/else.
Definition Stmt.h:2251
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3853
Represents an implicitly-generated value initialization of an object of a given type.
Definition Expr.h:6057
Describes an C or C++ initializer list.
Definition Expr.h:5299
ArrayRef< Expr * > inits()
Definition Expr.h:5349
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2138
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4920
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4937
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3364
Expr * getBase() const
Definition Expr.h:3441
This represents a decl that may have a name.
Definition Decl.h:274
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2527
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
ParenExpr - This represents a parenthesized expression, e.g.
Definition Expr.h:2182
const Expr * getSubExpr() const
Definition Expr.h:2199
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2005
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8292
QualType getCanonicalType() const
Definition TypeBase.h:8344
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8296
bool isUnretained(const QualType, bool ignoreARC=false)
void visitTranslationUnitDecl(const TranslationUnitDecl *)
void visitTypedef(const TypedefDecl *)
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3152
Expr * getRetValue()
Definition Stmt.h:3179
Represents a C++11 static_assert declaration.
Definition DeclCXX.h:4132
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:299
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1799
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition ExprCXX.h:4664
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2501
The top declaration context.
Definition Decl.h:105
bool VisitMemberExpr(const MemberExpr *ME)
bool VisitStringLiteral(const StringLiteral *E)
bool VisitStaticAssertDecl(const StaticAssertDecl *SAD)
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE)
bool VisitCXXThisExpr(const CXXThisExpr *CTE)
bool VisitUnaryOperator(const UnaryOperator *UO)
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *AILE)
bool VisitPredefinedExpr(const PredefinedExpr *E)
bool VisitContinueStmt(const ContinueStmt *)
bool VisitSwitchStmt(const SwitchStmt *SS)
bool VisitGCCAsmStmt(const GCCAsmStmt *AS)
bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO)
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
bool VisitFixedPointLiteral(const FixedPointLiteral *E)
bool VisitDeclRefExpr(const DeclRefExpr *DRE)
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E)
bool VisitFloatingLiteral(const FloatingLiteral *E)
TrivialFunctionAnalysis::CacheTy CacheTy
bool VisitConditionalOperator(const ConditionalOperator *CO)
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
bool VisitCompoundStmt(const CompoundStmt *CS)
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *IVIE)
bool VisitConstantExpr(const ConstantExpr *CE)
bool VisitImplicitCastExpr(const ImplicitCastExpr *ICE)
bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
bool VisitOpaqueValueExpr(const OpaqueValueExpr *OVE)
bool VisitExprWithCleanups(const ExprWithCleanups *EWC)
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE)
bool VisitCXXNewExpr(const CXXNewExpr *NE)
bool VisitBinaryOperator(const BinaryOperator *BO)
bool VisitCoroutineBodyStmt(const CoroutineBodyStmt *CBS)
bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)
bool VisitCXXForRangeStmt(const CXXForRangeStmt *FS)
bool VisitCharacterLiteral(const CharacterLiteral *E)
bool VisitInitListExpr(const InitListExpr *ILE)
bool VisitAttributedStmt(const AttributedStmt *AS)
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E)
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
bool VisitExplicitCastExpr(const ExplicitCastExpr *ECE)
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *AIIE)
bool VisitDefaultStmt(const DefaultStmt *DS)
bool VisitOffsetOfExpr(const OffsetOfExpr *OE)
bool VisitCXXConstructExpr(const CXXConstructExpr *CE)
bool VisitReturnStmt(const ReturnStmt *RS)
The base class of the type hierarchy.
Definition TypeBase.h:1833
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2922
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Definition Decl.h:3667
QualType getUnderlyingType() const
Definition Decl.h:3617
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2625
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
Expr * getSubExpr() const
Definition Expr.h:2285
Opcode getOpcode() const
Definition Expr.h:2280
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2689
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
bool isCocoaObjectRef(QualType T)
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 isPtrConversion(const FunctionDecl *F)
std::optional< bool > isCheckedPtrCapable(const clang::CXXRecordDecl *R)
std::optional< bool > isUnchecked(const QualType T)
bool isCtorOfRefCounted(const clang::FunctionDecl *F)
bool isRefOrCheckedPtrType(const clang::QualType T)
@ AS_public
Definition Specifiers.h:124
bool isRetainPtrOrOSPtrType(const clang::QualType T)
bool isCtorOfRetainPtrOrOSPtr(const clang::FunctionDecl *F)
@ Result
The result type of a method or function.
Definition TypeBase.h:905
bool isOwnerPtr(const std::string &Name)
const FunctionProtoType * T
std::optional< bool > isRefCountable(const clang::CXXRecordDecl *R)
std::optional< const clang::CXXRecordDecl * > hasPublicMethodInBase(const CXXBaseSpecifier *Base, StringRef NameToMatch)
static WebKitAnnotation typeAnnotationForReturnType(const FunctionDecl *FD)
bool isSmartPtrClass(const std::string &Name)
bool isRefCounted(const CXXRecordDecl *R)
static bool isPtrOfType(const clang::QualType T, Predicate Pred)
std::optional< bool > isSmartPtrCompatible(const CXXRecordDecl *R, StringRef IncMethodName, StringRef DecMethodName)
bool isNoDeleteFunction(const FunctionDecl *F)
bool isOwnerPtrType(const clang::QualType T)
bool isSmartPtr(const CXXRecordDecl *R)
std::optional< bool > isGetterOfSafePtr(const CXXMethodDecl *M)
bool isRetainPtrOrOSPtr(const std::string &Name)
bool isRefType(const std::string &Name)
std::optional< bool > isUncountedPtr(const QualType T)
std::string safeGetName(const T *ASTNode)
Definition ASTUtils.h:95
bool isCtorOfCheckedPtr(const clang::FunctionDecl *F)
bool isSingleton(const NamedDecl *F)
bool isCheckedPtr(const std::string &Name)
bool isStdOrWTFMove(const clang::FunctionDecl *F)
@ None
The alignment was not explicit in code.
Definition ASTContext.h:178
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:5889
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:5879
std::optional< bool > isUncounted(const QualType T)
std::optional< bool > isUncheckedPtr(const QualType T)