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_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 {
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