Home | History | Annotate | Line # | Download | only in AST
      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 {
     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 } // end namespace clang
    111 
    112 #endif
    113