1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H |
15 | #define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H |
16 | |
17 | #include "clang/AST/Type.h" |
18 | |
19 | namespace clang { |
20 | |
21 | template <class Derived, class RetTy = void> struct DestructedTypeVisitor { |
22 | 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> |
28 | 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 | |
46 | Derived &asDerived() { return static_cast<Derived &>(*this); } |
47 | }; |
48 | |
49 | template <class Derived, class RetTy = void> |
50 | struct DefaultInitializedTypeVisitor { |
51 | 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> |
58 | 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 | |
74 | Derived &asDerived() { return static_cast<Derived &>(*this); } |
75 | }; |
76 | |
77 | template <class Derived, bool IsMove, class RetTy = void> |
78 | struct CopiedTypeVisitor { |
79 | 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> |
87 | 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 | |
107 | Derived &asDerived() { return static_cast<Derived &>(*this); } |
108 | }; |
109 | |
110 | } |
111 | |
112 | #endif |
113 | |