clang 24.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) || isRetainPtrOrOSPtr(Name) ||
143 Name == "unique_ptr" || Name == "UniqueRef" || Name == "LazyUniqueRef";
144}
145
146static bool isWeakPtrClass(const std::string &Name) {
147 return Name == "WeakPtr" || Name == "SingleThreadPackedWeakPtr" ||
148 Name == "SingleThreadWeakPtr" || Name == "ThreadSafeWeakPtr" ||
149 Name == "ThreadSafeWeakOrStrongPtr" || Name == "InlineWeakPtr";
150}
151
152bool isSmartPtrClass(const std::string &Name) {
153 return isRefType(Name) || isCheckedPtr(Name) || isRetainPtrOrOSPtr(Name) ||
154 isWeakPtrClass(Name) || Name == "WeakPtrFactory" ||
155 Name == "WeakPtrFactoryWithBitField" || Name == "WeakPtrImplBase" ||
156 Name == "WeakPtrImplBaseSingleThread" ||
157 Name == "ThreadSafeWeakOrStrongPtr" ||
158 Name == "ThreadSafeWeakPtrControlBlock" ||
159 Name == "ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr";
160}
161
163 if (auto *Ctor = dyn_cast_or_null<CXXConstructorDecl>(F))
164 return safeGetName(Ctor->getParent());
165 return safeGetName(F);
166}
167
169 assert(F);
170 auto FunctionName = getConstructorName(F);
171 return isRefType(FunctionName) || FunctionName == "adoptRef" ||
172 FunctionName == "UniqueRef" || FunctionName == "makeUniqueRef" ||
173 FunctionName == "makeUniqueRefWithoutFastMallocCheck"
174
175 || FunctionName == "String" || FunctionName == "AtomString" ||
176 FunctionName == "UniqueString"
177 // FIXME: Implement as attribute.
178 || FunctionName == "Identifier";
179}
180
182 assert(F);
184}
185
187 auto FunctionName = getConstructorName(F);
188 return isRetainPtrOrOSPtr(FunctionName) || FunctionName == "adoptNS" ||
189 FunctionName == "adoptNSNullable" || FunctionName == "adoptCF" ||
190 FunctionName == "adoptCFNullable" || FunctionName == "retainPtr" ||
191 FunctionName == "adoptNSArc" || FunctionName == "adoptOSObject" ||
192 FunctionName == "adoptOSObjectArc";
193}
194
199
201 auto FnName = safeGetName(F);
202 auto *Namespace = F->getParent();
203 if (!Namespace)
204 return false;
205 auto *TUDeck = Namespace->getParent();
206 if (!isa_and_nonnull<TranslationUnitDecl>(TUDeck))
207 return false;
208 auto NsName = safeGetName(Namespace);
209 return (NsName == "WTF" || NsName == "std") && FnName == "move";
210}
211
212template <typename Predicate>
213static bool isPtrOfType(const clang::QualType T, Predicate Pred) {
214 QualType type = T;
215 while (!type.isNull()) {
216 if (auto *SpecialT = type->getAs<TemplateSpecializationType>()) {
217 auto *Decl = SpecialT->getTemplateName().getAsTemplateDecl();
218 return Decl && Pred(Decl->getNameAsString());
219 } else if (auto *DTS = type->getAs<DeducedTemplateSpecializationType>()) {
220 auto *Decl = DTS->getTemplateName().getAsTemplateDecl();
221 return Decl && Pred(Decl->getNameAsString());
222 } else if (auto *RD = type->getAs<RecordType>()) {
223 auto *Decl = RD->getDecl();
224 return Decl && Pred(Decl->getNameAsString());
225 } else
226 break;
227 }
228 return false;
229}
230
232 return isPtrOfType(
233 T, [](auto Name) { return isRefType(Name) || isCheckedPtr(Name); });
234}
235
237 return isPtrOfType(T, [](auto Name) { return isRetainPtrOrOSPtr(Name); });
238}
239
241 return isPtrOfType(T, [](auto Name) { return isOwnerPtr(Name); });
242}
243
244std::optional<bool> isUncounted(const QualType T) {
245 if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
246 if (auto *Decl = Subst->getAssociatedDecl()) {
248 return false;
249 }
250 }
251 return isUncounted(T->getAsCXXRecordDecl());
252}
253
254std::optional<bool> isUnchecked(const QualType T) {
255 if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
256 if (auto *Decl = Subst->getAssociatedDecl()) {
258 return false;
259 }
260 }
261 return isUnchecked(T->getAsCXXRecordDecl());
262}
263
265 const TranslationUnitDecl *TUD) {
266 IsARCEnabled = TUD->getLangOpts().ObjCAutoRefCount;
267 DefaultSynthProperties = TUD->getLangOpts().ObjCDefaultSynthProperties;
268}
269
271 auto QT = TD->getUnderlyingType();
272 if (!QT->isPointerType())
273 return;
274
275 auto PointeeQT = QT->getPointeeType();
276 const RecordType *RT = PointeeQT->getAsCanonical<RecordType>();
277 if (!RT) {
278 if (TD->hasAttr<ObjCBridgeAttr>() || TD->hasAttr<ObjCBridgeMutableAttr>()) {
279 RecordlessTypes.insert(TD->getASTContext()
281 /*Qualifier=*/std::nullopt, TD)
282 .getTypePtr());
283 }
284 return;
285 }
286
287 for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
288 if (Redecl->getAttr<ObjCBridgeAttr>() ||
289 Redecl->getAttr<ObjCBridgeMutableAttr>()) {
290 CFPointees.insert({RT, TD});
291 return;
292 }
293 }
294}
295
296bool RetainTypeChecker::isUnretained(const QualType QT, bool ignoreARC) {
297 if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC))
298 return true;
299 if (auto *RT = dyn_cast_or_null<RecordType>(
301 return CFPointees.contains(RT);
302 return RecordlessTypes.contains(QT.getTypePtr());
303}
304
306 if (auto *TT = dyn_cast_or_null<TypedefType>(QT.getTypePtrOrNull())) {
307 if (auto *TD = dyn_cast<TypedefDecl>(TT->getDecl()))
308 return TD;
309 }
310 QT = QT.getCanonicalType();
311 auto PointeeQT = QT->getPointeeType();
312 auto *PointeeType = PointeeQT.getTypePtrOrNull();
313 if (!PointeeType)
314 return nullptr;
315 auto *RD = dyn_cast<RecordType>(PointeeType);
316 if (!RD)
317 return nullptr;
318 return CFPointees.lookup(RD);
319}
320
321std::optional<bool> isUncounted(const CXXRecordDecl* Class)
322{
323 // Keep isRefCounted first as it's cheaper.
324 if (!Class || isRefCounted(Class))
325 return false;
326
327 std::optional<bool> IsRefCountable = isRefCountable(Class);
328 if (!IsRefCountable)
329 return std::nullopt;
330
331 return (*IsRefCountable);
332}
333
334std::optional<bool> isUnchecked(const CXXRecordDecl *Class) {
335 if (!Class || isCheckedPtr(Class))
336 return false; // Cheaper than below
338}
339
340std::optional<bool> isUncountedPtr(const QualType T) {
341 if (T->isPointerType() || T->isReferenceType()) {
342 if (auto *CXXRD = T->getPointeeCXXRecordDecl())
343 return isUncounted(CXXRD);
344 }
345 return false;
346}
347
348std::optional<bool> isUncheckedPtr(const QualType T) {
349 if (T->isPointerType() || T->isReferenceType()) {
350 if (auto *CXXRD = T->getPointeeCXXRecordDecl())
351 return isUnchecked(CXXRD);
352 }
353 return false;
354}
355
356std::optional<bool> isGetterOfSafePtr(const CXXMethodDecl *M) {
357 assert(M);
358
359 const CXXRecordDecl *calleeMethodsClass = M->getParent();
360 std::string className = safeGetName(calleeMethodsClass);
361 std::string method = safeGetName(M);
362
363 auto OpType = M->getOverloadedOperator();
364 if (isCheckedPtr(className) &&
365 (method == "get" || method == "ptr" || OpType == OO_Star))
366 return true;
367
368 if ((isRefType(className) &&
369 (method == "get" || method == "ptr" || OpType == OO_Star)) ||
370 ((className == "String" || className == "AtomString" ||
371 className == "AtomStringImpl" || className == "UniqueString" ||
372 className == "UniqueStringImpl" || className == "Identifier") &&
373 method == "impl"))
374 return true;
375
376 if (isRetainPtrOrOSPtr(className) && method == "get")
377 return true;
378
379 // Ref<T> -> T conversion
380 // FIXME: Currently allowing any Ref<T> -> whatever cast.
381 if (isRefType(className)) {
382 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
383 QualType QT = maybeRefToRawOperator->getConversionType();
384 const Type *T = QT.getTypePtrOrNull();
385 return T && (T->isPointerType() || T->isReferenceType());
386 }
387 }
388
389 if (isCheckedPtr(className)) {
390 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
391 QualType QT = maybeRefToRawOperator->getConversionType();
392 const Type *T = QT.getTypePtrOrNull();
393 return T && (T->isPointerType() || T->isReferenceType());
394 }
395 }
396
397 if (isRetainPtrOrOSPtr(className)) {
398 if (auto *maybeRefToRawOperator = dyn_cast<CXXConversionDecl>(M)) {
399 QualType QT = maybeRefToRawOperator->getConversionType();
400 const Type *T = QT.getTypePtrOrNull();
401 return T && (T->isPointerType() || T->isReferenceType() ||
402 T->isObjCObjectPointerType());
403 }
404 }
405 return false;
406}
407
409 assert(R);
410 if (auto *TmplR = R->getTemplateInstantiationPattern()) {
411 // FIXME: String/AtomString/UniqueString
412 const auto &ClassName = safeGetName(TmplR);
413 return isRefType(ClassName);
414 }
415 return false;
416}
417
419 assert(R);
420 if (auto *TmplR = R->getTemplateInstantiationPattern()) {
421 const auto &ClassName = safeGetName(TmplR);
422 return isCheckedPtr(ClassName);
423 }
424 return false;
425}
426
428 assert(R);
429 if (auto *TmplR = R->getTemplateInstantiationPattern())
430 return isRetainPtrOrOSPtr(safeGetName(TmplR));
431 return false;
432}
433
434bool isWeakPtr(const CXXRecordDecl *R) {
435 assert(R);
436 if (auto *TmplR = R->getTemplateInstantiationPattern())
437 return isWeakPtrClass(safeGetName(TmplR));
438 return false;
439}
440
441bool isSmartPtr(const CXXRecordDecl *R) {
442 assert(R);
443 if (auto *TmplR = R->getTemplateInstantiationPattern())
444 return isSmartPtrClass(safeGetName(TmplR));
445 return false;
446}
447
453
455 auto RetType = FD->getReturnType();
456 auto *Type = RetType.getTypePtrOrNull();
457 if (auto *MacroQualified = dyn_cast_or_null<MacroQualifiedType>(Type))
458 Type = MacroQualified->desugar().getTypePtrOrNull();
459 auto *Attr = dyn_cast_or_null<AttributedType>(Type);
460 if (!Attr)
462 auto *AnnotateType = dyn_cast_or_null<AnnotateTypeAttr>(Attr->getAttr());
463 if (!AnnotateType)
465 auto Annotation = AnnotateType->getAnnotation();
466 if (Annotation == "webkit.pointerconversion")
468 if (Annotation == "webkit.nodelete")
471}
472
474 assert(F);
475 if (isCtorOfRefCounted(F))
476 return true;
477
478 // FIXME: check # of params == 1
479 const auto FunctionName = safeGetName(F);
480 if (FunctionName == "getPtr" || FunctionName == "WeakPtr" ||
481 FunctionName == "dynamicDowncast" || FunctionName == "downcast" ||
482 FunctionName == "checkedDowncast" || FunctionName == "bit_cast" ||
483 FunctionName == "uncheckedDowncast" || FunctionName == "bitwise_cast" ||
484 FunctionName == "bridge_cast" || FunctionName == "bridge_id_cast" ||
485 FunctionName == "dynamic_cf_cast" || FunctionName == "checked_cf_cast" ||
486 FunctionName == "dynamic_objc_cast" ||
487 FunctionName == "checked_objc_cast")
488 return true;
489
491 return true;
492
493 return false;
494}
495
499
501 if (llvm::any_of(F->redecls(), isNoDeleteFunctionDecl))
502 return true;
503
504 const auto *MD = dyn_cast<CXXMethodDecl>(F);
505 if (!MD || !MD->isVirtual())
506 return false;
507
508 auto Overriders = llvm::to_vector(MD->overridden_methods());
509 while (!Overriders.empty()) {
510 const auto *Fn = Overriders.pop_back_val();
511 llvm::append_range(Overriders, Fn->overridden_methods());
513 return true;
514 }
515
516 return false;
517}
518
520 if (!F || !F->getDeclName().isIdentifier())
521 return false;
522 auto Name = F->getName();
523 return Name.starts_with("__builtin") || Name == "__libcpp_verbose_abort" ||
524 Name.starts_with("os_log") || Name.starts_with("_os_log");
525}
526
527bool isSingleton(const NamedDecl *F) {
528 assert(F);
529 // FIXME: check # of params == 1
530 if (auto *MethodDecl = dyn_cast<CXXMethodDecl>(F)) {
531 if (!MethodDecl->isStatic())
532 return false;
533 }
534 const auto &NameStr = safeGetName(F);
535 StringRef Name = NameStr; // FIXME: Make safeGetName return StringRef.
536 return Name == "singleton" || Name.ends_with("Singleton");
537}
538
539// We only care about statements so let's use the simple
540// (non-recursive) visitor.
542 : public ConstStmtVisitor<TrivialFunctionAnalysisVisitor, bool> {
543
544 // Returns false if at least one child is non-trivial.
545 bool VisitChildren(const Stmt *S) {
546 for (const Stmt *Child : S->children()) {
547 if (Child && !Visit(Child)) {
548 if (OffendingStmt && !*OffendingStmt)
549 *OffendingStmt = Child;
550 return false;
551 }
552 }
553
554 return true;
555 }
556
557 template <typename StmtOrDecl, typename CheckFunction>
558 bool WithCachedResult(const StmtOrDecl *S, CheckFunction Function) {
559 auto CacheIt = Cache.find(S);
560 if (CacheIt != Cache.end() && !OffendingStmt)
561 return CacheIt->second;
562
563 // Treat a recursive statement to be trivial until proven otherwise.
564 auto [RecursiveIt, IsNew] = RecursiveFn.insert(std::make_pair(S, true));
565 if (!IsNew)
566 return RecursiveIt->second;
567
568 bool Result = Function();
569
570 if (!Result) {
571 for (auto &It : RecursiveFn)
572 It.second = false;
573 }
574 RecursiveIt = RecursiveFn.find(S);
575 assert(RecursiveIt != RecursiveFn.end());
576 Result = RecursiveIt->second;
577 RecursiveFn.erase(RecursiveIt);
578 Cache[S] = Result;
579
580 return Result;
581 }
582
583 bool CanTriviallyDestruct(QualType Ty) {
584 if (Ty.isNull())
585 return false;
586
587 // T*, T& or T&& does not run its destructor.
588 if (Ty->isPointerOrReferenceType())
589 return true;
590
591 // FIXME: Handle a case when there is a local autorelease pool.
592 if (Ty->isObjCObjectPointerType()) {
593 auto Type = Ty.isDestructedType();
595 return true;
596 // strong lifetime in ARC could dealloc an object.
597 }
598
599 // Fundamental types (integral, nullptr_t, etc...) don't have destructors.
601 return true;
602
603 if (const auto *R = Ty->getAsCXXRecordDecl()) {
604 // C++ trivially destructible classes are fine.
605 if (R->hasDefinition() && R->hasTrivialDestructor())
606 return true;
607
608 if (HasFieldWithNonTrivialDtor(R))
609 return false;
610
611 // For Webkit, side-effects are fine as long as we don't delete objects,
612 // so check recursively.
613 if (const auto *Dtor = R->getDestructor())
614 return IsFunctionTrivial(Dtor);
615 }
616
617 // Structs in C are trivial.
618 if (Ty->isRecordType())
619 return true;
620
621 // For arrays it depends on the element type.
622 // FIXME: We should really use ASTContext::getAsArrayType instead.
623 if (const auto *AT = Ty->getAsArrayTypeUnsafe())
624 return CanTriviallyDestruct(AT->getElementType());
625
626 return false; // Otherwise it's likely not trivial.
627 }
628
629 bool HasFieldWithNonTrivialDtor(const CXXRecordDecl *Cls) {
630 auto CacheIt = FieldDtorCache.find(Cls);
631 if (CacheIt != FieldDtorCache.end())
632 return CacheIt->second;
633
634 bool Result = ([&] {
635 auto HasNonTrivialField = [&](const CXXRecordDecl *R) {
636 for (const FieldDecl *F : R->fields()) {
637 if (!CanTriviallyDestruct(F->getType()))
638 return true;
639 }
640 return false;
641 };
642
643 if (HasNonTrivialField(Cls))
644 return true;
645
646 if (!Cls->hasDefinition())
647 return false;
648
649 CXXBasePaths Paths;
650 Paths.setOrigin(const_cast<CXXRecordDecl *>(Cls));
651 return Cls->lookupInBases(
652 [&](const CXXBaseSpecifier *B, CXXBasePath &) {
653 auto *T = B->getType().getTypePtrOrNull();
654 if (!T)
655 return false;
656 auto *R = T->getAsCXXRecordDecl();
657 return R && HasNonTrivialField(R);
658 },
659 Paths, /*LookupInDependent =*/true);
660 })();
661
662 FieldDtorCache[Cls] = Result;
663
664 return Result;
665 }
666
667public:
668 using CacheTy = TrivialFunctionAnalysis::CacheTy;
669
671 const Stmt **OffendingStmt = nullptr)
672 : Cache(Cache), OffendingStmt(OffendingStmt) {}
673
674 bool IsFunctionTrivial(const Decl *D) {
675 const Stmt **SavedOffendingStmt = std::exchange(OffendingStmt, nullptr);
676 auto Result = WithCachedResult(D, [&]() {
677 auto *FnDecl = dyn_cast<FunctionDecl>(D);
678 auto *MethodDecl = dyn_cast<CXXMethodDecl>(D);
679 auto *CtorDecl = dyn_cast<CXXConstructorDecl>(D);
680 auto *DtorDecl = dyn_cast<CXXDestructorDecl>(D);
681
682 if (FnDecl) {
683 if (isNoDeleteFunction(FnDecl))
684 return true;
685 if (MethodDecl && MethodDecl->isVirtual())
686 return false;
687 for (auto *Param : FnDecl->parameters()) {
688 if (!HasTrivialDestructor(Param))
689 return false;
690 }
691 }
692 if (CtorDecl) {
693 for (auto *CtorInit : CtorDecl->inits()) {
694 if (!Visit(CtorInit->getInit()))
695 return false;
696 }
697 }
698 // An implicit or =default special member runs no user code when it is
699 // trivial in the C++ standard sense, so it cannot delete. Such a
700 // member's synthesized body is typically absent from the AST until
701 // codegen materialises it, which the generic null-body check below
702 // would otherwise conservatively classify as non-trivial.
703 if (MethodDecl && !MethodDecl->isUserProvided()) {
704 if (CtorDecl) {
705 const CXXRecordDecl *RD = CtorDecl->getParent();
706 if ((CtorDecl->isDefaultConstructor() &&
708 (CtorDecl->isCopyConstructor() &&
710 (CtorDecl->isMoveConstructor() &&
712 return true;
713 }
714 if (DtorDecl && DtorDecl->getParent()->hasTrivialDestructor())
715 return true;
716 }
717 const Stmt *Body = D->getBody();
718 if (!Body)
719 return false;
720 return Visit(Body);
721 });
722 OffendingStmt = SavedOffendingStmt;
723 return Result;
724 }
725
727 return WithCachedResult(
728 VD, [&] { return CanTriviallyDestruct(VD->getType()); });
729 }
730
731 bool IsStatementTrivial(const Stmt *S) {
732 auto CacheIt = Cache.find(S);
733 if (CacheIt != Cache.end())
734 return CacheIt->second;
735 bool Result = Visit(S);
736 Cache[S] = Result;
737 return Result;
738 }
739
740 bool VisitStmt(const Stmt *S) {
741 // All statements are non-trivial unless overriden later.
742 // Don't even recurse into children by default.
743 return false;
744 }
745
747 // Ignore attributes.
748 return Visit(AS->getSubStmt());
749 }
750
752 // A compound statement is allowed as long each individual sub-statement
753 // is trivial.
754 return WithCachedResult(CS, [&]() { return VisitChildren(CS); });
755 }
756
758 return WithCachedResult(CBS, [&]() { return VisitChildren(CBS); });
759 }
760
761 bool VisitReturnStmt(const ReturnStmt *RS) {
762 // A return statement is allowed as long as the return value is trivial. A
763 // returned smart-pointer prvalue is special: under guaranteed copy elision
764 // the temporary *is* the function's return slot, so it is destructed by the
765 // caller, not here. Hence we may ignore that temporary's destructor.
766 if (auto *RV = RS->getRetValue())
768 return true;
769 }
770
771 bool VisitDeclStmt(const DeclStmt *DS) {
772 for (auto &Decl : DS->decls()) {
773 // FIXME: Handle DecompositionDecls.
774 if (auto *VD = dyn_cast<VarDecl>(Decl)) {
775 if (!HasTrivialDestructor(VD))
776 return false;
777 }
778 }
779 return VisitChildren(DS);
780 }
781 bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
782 bool VisitIfStmt(const IfStmt *IS) {
783 return WithCachedResult(IS, [&]() { return VisitChildren(IS); });
784 }
785 bool VisitForStmt(const ForStmt *FS) {
786 return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
787 }
789 return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
790 }
791 bool VisitWhileStmt(const WhileStmt *WS) {
792 return WithCachedResult(WS, [&]() { return VisitChildren(WS); });
793 }
794 bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
795 bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
796 bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
797
798 // break, continue, goto, and label statements are always trivial.
799 bool VisitBreakStmt(const BreakStmt *) { return true; }
800 bool VisitContinueStmt(const ContinueStmt *) { return true; }
801 bool VisitGotoStmt(const GotoStmt *) { return true; }
802 bool VisitLabelStmt(const LabelStmt *) { return true; }
803
805 // Unary operators are trivial if its operand is trivial except co_await.
806 return UO->getOpcode() != UO_Coawait && Visit(UO->getSubExpr());
807 }
808
810 // Binary operators are trivial if their operands are trivial.
811 return Visit(BO->getLHS()) && Visit(BO->getRHS());
812 }
813
815 // Compound assignment operator such as |= is trivial if its
816 // subexpresssions are trivial.
817 return VisitChildren(CAO);
818 }
819
821 return VisitChildren(ASE);
822 }
823
825 // Ternary operators are trivial if their conditions & values are trivial.
826 return VisitChildren(CO);
827 }
828
829 bool VisitAtomicExpr(const AtomicExpr *E) { return VisitChildren(E); }
830
832 // Any static_assert is considered trivial.
833 return true;
834 }
835
836 bool VisitCallExpr(const CallExpr *CE) {
837 if (!checkArguments(CE))
838 return false;
839
840 auto *Callee = CE->getDirectCallee();
841 if (!Callee)
842 return false;
843
844 if (isPtrConversion(Callee))
845 return true;
846
847 const auto &Name = safeGetName(Callee);
848
849 if (Callee->isInStdNamespace() &&
850 (Name == "addressof" || Name == "forward" || Name == "move"))
851 return true;
852
853 if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
854 Name == "WTFReportBacktrace" ||
855 Name == "WTFCrashWithSecurityImplication" || Name == "WTFCrash" ||
856 Name == "WTFReportAssertionFailure" || Name == "isMainThread" ||
857 Name == "isMainThreadOrGCThread" || Name == "isMainRunLoop" ||
858 Name == "isWebThread" || Name == "isUIThread" ||
859 Name == "mayBeGCThread" || Name == "compilerFenceForCrash" ||
861 return true;
862
863 return IsFunctionTrivial(Callee);
864 }
865
866 bool VisitGCCAsmStmt(const GCCAsmStmt *AS) {
867 return AS->getAsmString() == "brk #0xc471";
868 }
869
870 bool
872 // Non-type template paramter is compile time constant and trivial.
873 return true;
874 }
875
877 return VisitChildren(E);
878 }
879
881 // A predefined identifier such as "func" is considered trivial.
882 return true;
883 }
884
886 // offsetof(T, D) is considered trivial.
887 return true;
888 }
889
891 if (!checkArguments(MCE))
892 return false;
893
894 bool TrivialThis = Visit(MCE->getImplicitObjectArgument());
895 if (!TrivialThis)
896 return false;
897
898 auto *Callee = MCE->getMethodDecl();
899 if (!Callee)
900 return false;
901
902 if (isa<CXXDestructorDecl>(Callee) &&
903 !CanTriviallyDestruct(MCE->getObjectType()))
904 return false;
905
906 auto Name = safeGetName(Callee);
907 if (Name == "ref" || Name == "incrementCheckedPtrCount")
908 return true;
909
910 std::optional<bool> IsGetterOfRefCounted = isGetterOfSafePtr(Callee);
911 if (IsGetterOfRefCounted && *IsGetterOfRefCounted)
912 return true;
913
914 // Recursively descend into the callee to confirm that it's trivial as well.
915 return IsFunctionTrivial(Callee);
916 }
917
919 if (!checkArguments(OCE))
920 return false;
921 auto *Callee = OCE->getCalleeDecl();
922 if (!Callee)
923 return false;
924 // Recursively descend into the callee to confirm that it's trivial as well.
925 return IsFunctionTrivial(Callee);
926 }
927
929 auto *SemanticExpr = Op->getSemanticForm();
930 return SemanticExpr && Visit(SemanticExpr);
931 }
932
934 if (auto *Expr = E->getExpr()) {
935 if (!Visit(Expr))
936 return false;
937 }
938 return true;
939 }
940
942 return Visit(E->getExpr());
943 }
944
945 bool checkArguments(const CallExpr *CE) {
946 for (const Expr *Arg : CE->arguments()) {
947 if (Arg && !Visit(Arg))
948 return false;
949 }
950 return true;
951 }
952
953 // Triviality check for a return value that may elide a smart-pointer
954 // temporary's destructor.
955 //
956 // This is only valid for *return values*: a returned class prvalue is
957 // constructed directly into the function's return slot (C++17 guaranteed copy
958 // elision), so the temporary is destructed by the caller rather than here.
959 //
960 // It is deliberately NOT applied to call/constructor arguments. An argument
961 // temporary's lifetime ends at the full-expression *in this function* (the
962 // caller destroys arguments, e.g. per the Itanium C++ ABI), so its destructor
963 // runs here and may invoke delete. Proving otherwise would require
964 // interprocedural ownership analysis, so arguments are checked normally.
966 QualType OriginalQT = Arg->getType();
967 auto *Type = OriginalQT.getTypePtrOrNull();
968 if (!Type)
969 return Visit(Arg);
970 auto *CXXRD = Type->getAsCXXRecordDecl();
971 if (!CXXRD || !isSmartPtrClass(safeGetName(CXXRD)))
972 return Visit(Arg);
973 Arg = Arg->IgnoreParenCasts();
974 if (!Arg->isPRValue())
975 return Visit(Arg);
976 if (auto *Init = dyn_cast<InitListExpr>(Arg)) {
977 if (Init->getNumInits() == 1)
978 Arg = Init->getInit(0);
979 }
980 if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg)) {
981 // Only elide when the temporary *is* the returned object, i.e. it has the
982 // same smart-pointer type as the return value. Compare canonical,
983 // unqualified types rather than relying on exact QualType identity, which
984 // is sensitive to sugar (typedefs/aliases) and cv-qualifiers.
985 if (OriginalQT.getCanonicalType().getUnqualifiedType() ==
986 BTE->getType().getCanonicalType().getUnqualifiedType())
987 return Visit(BTE->getSubExpr());
988 }
989 return Visit(Arg);
990 }
991
993 if (CE->getNumArgs() == 1) {
994 auto *InnerArg = CE->getArg(0);
995 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(InnerArg)) {
996 auto *InnerExpr = MTE->getSubExpr();
997 if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(InnerExpr))
998 InnerExpr = BTE->getSubExpr();
999 auto InnerQT = InnerExpr->getType();
1000 if (auto *InnerDecl = InnerQT->getAsCXXRecordDecl()) {
1001 auto *OuterCls = CE->getConstructor()->getParent();
1002 if (isRefType(safeGetName(OuterCls)) &&
1003 isRefType(safeGetName(InnerDecl)))
1004 return Visit(InnerExpr);
1005 }
1006 }
1007 }
1008
1009 for (const Expr *Arg : CE->arguments()) {
1010 if (Arg && !Visit(Arg))
1011 return false;
1012 }
1013
1014 // Recursively descend into the callee to confirm that it's trivial.
1015 return IsFunctionTrivial(CE->getConstructor());
1016 }
1017
1021
1022 bool VisitCXXNewExpr(const CXXNewExpr *NE) { return VisitChildren(NE); }
1023
1025 return Visit(ICE->getSubExpr());
1026 }
1027
1029 return Visit(ECE->getSubExpr());
1030 }
1031
1033 return Visit(VMT->getSubExpr());
1034 }
1035
1037 if (auto *Temp = BTE->getTemporary()) {
1038 if (!IsFunctionTrivial(Temp->getDestructor()))
1039 return false;
1040 }
1041 return Visit(BTE->getSubExpr());
1042 }
1043
1045 return Visit(AILE->getCommonExpr()) && Visit(AILE->getSubExpr());
1046 }
1047
1049 return true; // The current array index in VisitArrayInitLoopExpr is always
1050 // trivial.
1051 }
1052
1054 return Visit(OVE->getSourceExpr());
1055 }
1056
1058 return Visit(EWC->getSubExpr());
1059 }
1060
1061 bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
1062
1064 for (const Expr *Child : ILE->inits()) {
1065 if (Child && !Visit(Child))
1066 return false;
1067 }
1068 return true;
1069 }
1070
1071 bool VisitMemberExpr(const MemberExpr *ME) {
1072 // Field access is allowed but the base pointer may itself be non-trivial.
1073 return Visit(ME->getBase());
1074 }
1075
1077 // The expression 'this' is always trivial, be it explicit or implicit.
1078 return true;
1079 }
1080
1082 // nullptr is trivial.
1083 return true;
1084 }
1085
1087 // The use of a variable is trivial.
1088 return true;
1089 }
1090
1091 // Constant literal expressions are always trivial
1092 bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
1093 bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
1094 bool VisitFixedPointLiteral(const FixedPointLiteral *E) { return true; }
1095 bool VisitCharacterLiteral(const CharacterLiteral *E) { return true; }
1096 bool VisitStringLiteral(const StringLiteral *E) { return true; }
1097 bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return true; }
1098
1100 // Constant expressions are trivial.
1101 return true;
1102 }
1103
1105 // An implicit value initialization is trvial.
1106 return true;
1107 }
1108
1109private:
1110 CacheTy &Cache;
1111 CacheTy FieldDtorCache;
1112 CacheTy RecursiveFn;
1113 const Stmt **OffendingStmt;
1114};
1115
1116bool TrivialFunctionAnalysis::isTrivialImpl(
1117 const Decl *D, TrivialFunctionAnalysis::CacheTy &Cache,
1118 const Stmt **OffendingStmt) {
1119 TrivialFunctionAnalysisVisitor V(Cache, OffendingStmt);
1120 return V.IsFunctionTrivial(D);
1121}
1122
1123bool TrivialFunctionAnalysis::isTrivialImpl(
1124 const Stmt *S, TrivialFunctionAnalysis::CacheTy &Cache,
1125 const Stmt **OffendingStmt) {
1126 TrivialFunctionAnalysisVisitor V(Cache, OffendingStmt);
1127 return V.IsStatementTrivial(S);
1128}
1129
1130bool TrivialFunctionAnalysis::hasTrivialDtorImpl(const VarDecl *VD,
1131 CacheTy &Cache) {
1133 return V.HasTrivialDestructor(VD);
1134}
1135
1136} // 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:4954
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:6071
Represents a loop initializing the elements of an array.
Definition Expr.h:6018
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:6033
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:6038
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2765
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6978
Attr - This represents one attribute.
Definition Attr.h:46
Represents an attribute applied to a statement.
Definition Stmt.h:2215
Stmt * getSubStmt()
Definition Stmt.h:2251
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
Expr * getRHS() const
Definition Expr.h:4134
BreakStmt - This represents a break.
Definition Stmt.h:3147
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
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
Represents binding an expression to a temporary.
Definition ExprCXX.h:1497
CXXTemporary * getTemporary()
Definition ExprCXX.h:1515
const Expr * getSubExpr() const
Definition ExprCXX.h:1519
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition ExprCXX.h:727
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1695
arg_range arguments()
Definition ExprCXX.h:1676
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1615
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Definition ExprCXX.h:1692
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1274
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1381
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1138
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:136
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1755
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
Definition ExprCXX.h:1792
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:183
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:774
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:755
QualType getObjectType() const
Retrieve the type of the object argument.
Definition ExprCXX.cpp:767
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2149
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2292
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2359
The null pointer literal (C++11 [lex.nullptr])
Definition ExprCXX.h:772
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:85
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasTrivialDefaultConstructor() const
Determine whether this class has a trivial default constructor (C++11 [class.ctor]p5).
Definition DeclCXX.h:1255
bool hasTrivialMoveConstructor() const
Determine whether this class has a trivial move constructor (C++11 [class.copy]p12)
Definition DeclCXX.h:1316
bool hasTrivialCopyConstructor() const
Determine whether this class has a trivial copy constructor (C++ [class.copy]p6, C++11 [class....
Definition DeclCXX.h:1293
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
A rewritten comparison expression that was originally written using operator syntax.
Definition ExprCXX.h:290
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:308
Represents the this expression in C++.
Definition ExprCXX.h:1158
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3170
arg_range arguments()
Definition Expr.h:3239
Decl * getCalleeDecl()
Definition Expr.h:3164
CaseStmt - Represent a case statement.
Definition Stmt.h:1932
Expr * getSubExpr()
Definition Expr.h:3770
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4344
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1752
ConditionalOperator - The ?
Definition Expr.h:4435
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:1102
ContinueStmt - This represents a continue.
Definition Stmt.h:3131
Represents the body of a coroutine.
Definition StmtCXX.h:321
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1290
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
decl_range decls()
Definition Stmt.h:1691
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
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:1104
bool hasAttr() const
Definition DeclBase.h:585
const LangOptions & getLangOpts() const LLVM_READONLY
Helper to get the language options from the ASTContext.
Definition DeclBase.cpp:556
bool isIdentifier() const
Predicate functions for querying what type of name this is.
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2844
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3972
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
Definition ExprCXX.h:3714
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:3128
bool isPRValue() const
Definition Expr.h:286
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3295
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2900
const Expr * getSubExpr() const
Definition Expr.h:1082
Represents a function declaration or definition.
Definition Decl.h:2059
QualType getReturnType() const
Definition Decl.h:2976
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition Decl.cpp:4171
This represents a GCC inline-assembly statement extension.
Definition Stmt.h:3458
std::string getAsmString() const
Definition Stmt.cpp:574
GotoStmt - This represents a direct goto.
Definition Stmt.h:2981
IfStmt - This represents an if/then/else.
Definition Stmt.h:2271
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3897
Represents an implicitly-generated value initialization of an object of a given type.
Definition Expr.h:6107
Describes an C or C++ initializer list.
Definition Expr.h:5352
ArrayRef< Expr * > inits() const
Definition Expr.h:5405
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2158
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4973
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4990
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3408
Expr * getBase() const
Definition Expr.h:3485
This represents a decl that may have a name.
Definition Decl.h:275
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2571
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1198
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1248
ParenExpr - This represents a parenthesized expression, e.g.
Definition Expr.h:2226
const Expr * getSubExpr() const
Definition Expr.h:2243
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2049
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:8501
QualType getCanonicalType() const
Definition TypeBase.h:8553
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8595
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8505
const TypedefDecl * getCanonicalDecl(QualType)
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:3172
Expr * getRetValue()
Definition Stmt.h:3199
Represents a C++11 static_assert declaration.
Definition DeclCXX.h:4165
Stmt - This represents one statement.
Definition Stmt.h:85
child_range children()
Definition Stmt.cpp:304
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1819
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition ExprCXX.h:4717
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2521
The top declaration context.
Definition Decl.h:106
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 VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
bool VisitDeclRefExpr(const DeclRefExpr *DRE)
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E)
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *Op)
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 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)
TrivialFunctionAnalysisVisitor(CacheTy &Cache, const Stmt **OffendingStmt=nullptr)
bool VisitReturnStmt(const ReturnStmt *RS)
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isFundamentalType() const
Tests whether the type is categorized as a fundamental type.
Definition TypeBase.h:8701
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 getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9232
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9390
bool isPointerOrReferenceType() const
Definition TypeBase.h:8742
bool isObjCObjectPointerType() const
Definition TypeBase.h:8917
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2998
bool isRecordType() const
Definition TypeBase.h:8865
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Definition Decl.h:3802
QualType getUnderlyingType() const
Definition Decl.h:3752
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2669
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
Expr * getSubExpr() const
Definition Expr.h:2329
Opcode getOpcode() const
Definition Expr.h:2324
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2709
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
bool isCocoaObjectRef(QualType T)
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
static bool isNoDeleteFunctionDecl(const FunctionDecl *F)
bool isPtrConversion(const FunctionDecl *F)
static bool isWeakPtrClass(const std::string &Name)
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:125
bool isRetainPtrOrOSPtrType(const clang::QualType T)
bool isCtorOfRetainPtrOrOSPtr(const clang::FunctionDecl *F)
@ Result
The result type of a method or function.
Definition TypeBase.h:906
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)
std::string getConstructorName(const clang::FunctionDecl *F)
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:98
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:176
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:6040
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:6030
std::optional< bool > isUncounted(const QualType T)
std::optional< bool > isUncheckedPtr(const QualType T)
bool isWeakPtr(const CXXRecordDecl *R)