1 //===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types -*- 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 // This file defines the visitor classes that are used to traverse non-trivial 10 // structs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_NONTRIVIALTYPEVISITOR_H 15 #define LLVM_CLANG_AST_NONTRIVIALTYPEVISITOR_H 16 17 #include "clang/AST/Type.h" 18 19 namespace clang { 20 21 template <class Derived, class RetTy = void> struct DestructedTypeVisitor { visitDestructedTypeVisitor22 template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { 23 return asDerived().visitWithKind(FT.isDestructedType(), FT, 24 std::forward<Ts>(Args)...); 25 } 26 27 template <class... Ts> visitWithKindDestructedTypeVisitor28 RetTy visitWithKind(QualType::DestructionKind DK, QualType FT, 29 Ts &&... Args) { 30 switch (DK) { 31 case QualType::DK_objc_strong_lifetime: 32 return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); 33 case QualType::DK_nontrivial_c_struct: 34 return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); 35 case QualType::DK_none: 36 return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); 37 case QualType::DK_cxx_destructor: 38 return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...); 39 case QualType::DK_objc_weak_lifetime: 40 return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); 41 } 42 43 llvm_unreachable("unknown destruction kind"); 44 } 45 asDerivedDestructedTypeVisitor46 Derived &asDerived() { return static_cast<Derived &>(*this); } 47 }; 48 49 template <class Derived, class RetTy = void> 50 struct DefaultInitializedTypeVisitor { visitDefaultInitializedTypeVisitor51 template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { 52 return asDerived().visitWithKind( 53 FT.isNonTrivialToPrimitiveDefaultInitialize(), FT, 54 std::forward<Ts>(Args)...); 55 } 56 57 template <class... Ts> visitWithKindDefaultInitializedTypeVisitor58 RetTy visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, 59 QualType FT, Ts &&... Args) { 60 switch (PDIK) { 61 case QualType::PDIK_ARCStrong: 62 return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); 63 case QualType::PDIK_ARCWeak: 64 return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); 65 case QualType::PDIK_Struct: 66 return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); 67 case QualType::PDIK_Trivial: 68 return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); 69 } 70 71 llvm_unreachable("unknown default-initialize kind"); 72 } 73 asDerivedDefaultInitializedTypeVisitor74 Derived &asDerived() { return static_cast<Derived &>(*this); } 75 }; 76 77 template <class Derived, bool IsMove, class RetTy = void> 78 struct CopiedTypeVisitor { visitCopiedTypeVisitor79 template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { 80 QualType::PrimitiveCopyKind PCK = 81 IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove() 82 : FT.isNonTrivialToPrimitiveCopy(); 83 return asDerived().visitWithKind(PCK, FT, std::forward<Ts>(Args)...); 84 } 85 86 template <class... Ts> visitWithKindCopiedTypeVisitor87 RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, 88 Ts &&... Args) { 89 asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...); 90 91 switch (PCK) { 92 case QualType::PCK_ARCStrong: 93 return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); 94 case QualType::PCK_ARCWeak: 95 return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); 96 case QualType::PCK_Struct: 97 return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); 98 case QualType::PCK_Trivial: 99 return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); 100 case QualType::PCK_VolatileTrivial: 101 return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...); 102 } 103 104 llvm_unreachable("unknown primitive copy kind"); 105 } 106 asDerivedCopiedTypeVisitor107 Derived &asDerived() { return static_cast<Derived &>(*this); } 108 }; 109 110 } // end namespace clang 111 112 #endif 113