Home | History | Annotate | Line # | Download | only in AST
      1 //===--- ASTTypeTraits.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 //  Provides a dynamic type identifier and a dynamically typed node container
     10 //  that can be used to store an AST base node at runtime in the same storage in
     11 //  a type safe way.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/AST/ASTTypeTraits.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/DeclCXX.h"
     18 #include "clang/AST/NestedNameSpecifier.h"
     19 #include "clang/AST/OpenMPClause.h"
     20 
     21 using namespace clang;
     22 
     23 const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
     24     {NKI_None, "<None>"},
     25     {NKI_None, "TemplateArgument"},
     26     {NKI_None, "TemplateArgumentLoc"},
     27     {NKI_None, "TemplateName"},
     28     {NKI_None, "NestedNameSpecifierLoc"},
     29     {NKI_None, "QualType"},
     30     {NKI_None, "TypeLoc"},
     31     {NKI_None, "CXXBaseSpecifier"},
     32     {NKI_None, "CXXCtorInitializer"},
     33     {NKI_None, "NestedNameSpecifier"},
     34     {NKI_None, "Decl"},
     35 #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" },
     36 #include "clang/AST/DeclNodes.inc"
     37     {NKI_None, "Stmt"},
     38 #define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED },
     39 #include "clang/AST/StmtNodes.inc"
     40     {NKI_None, "Type"},
     41 #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" },
     42 #include "clang/AST/TypeNodes.inc"
     43     {NKI_None, "OMPClause"},
     44 #define GEN_CLANG_CLAUSE_CLASS
     45 #define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},
     46 #include "llvm/Frontend/OpenMP/OMP.inc"
     47 };
     48 
     49 bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
     50   return isBaseOf(KindId, Other.KindId, Distance);
     51 }
     52 
     53 bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
     54                            unsigned *Distance) {
     55   if (Base == NKI_None || Derived == NKI_None) return false;
     56   unsigned Dist = 0;
     57   while (Derived != Base && Derived != NKI_None) {
     58     Derived = AllKindInfo[Derived].ParentId;
     59     ++Dist;
     60   }
     61   if (Distance)
     62     *Distance = Dist;
     63   return Derived == Base;
     64 }
     65 
     66 ASTNodeKind ASTNodeKind::getCladeKind() const {
     67   NodeKindId LastId = KindId;
     68   while (LastId) {
     69     NodeKindId ParentId = AllKindInfo[LastId].ParentId;
     70     if (ParentId == NKI_None)
     71       return LastId;
     72     LastId = ParentId;
     73   }
     74   return NKI_None;
     75 }
     76 
     77 StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
     78 
     79 ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1,
     80                                             ASTNodeKind Kind2) {
     81   if (Kind1.isBaseOf(Kind2)) return Kind2;
     82   if (Kind2.isBaseOf(Kind1)) return Kind1;
     83   return ASTNodeKind();
     84 }
     85 
     86 ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1,
     87                                                       ASTNodeKind Kind2) {
     88   NodeKindId Parent = Kind1.KindId;
     89   while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) {
     90     Parent = AllKindInfo[Parent].ParentId;
     91   }
     92   return ASTNodeKind(Parent);
     93 }
     94 
     95 ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) {
     96   switch (D.getKind()) {
     97 #define DECL(DERIVED, BASE)                                                    \
     98     case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);
     99 #define ABSTRACT_DECL(D)
    100 #include "clang/AST/DeclNodes.inc"
    101   };
    102   llvm_unreachable("invalid decl kind");
    103 }
    104 
    105 ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) {
    106   switch (S.getStmtClass()) {
    107     case Stmt::NoStmtClass: return NKI_None;
    108 #define STMT(CLASS, PARENT)                                                    \
    109     case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);
    110 #define ABSTRACT_STMT(S)
    111 #include "clang/AST/StmtNodes.inc"
    112   }
    113   llvm_unreachable("invalid stmt kind");
    114 }
    115 
    116 ASTNodeKind ASTNodeKind::getFromNode(const Type &T) {
    117   switch (T.getTypeClass()) {
    118 #define TYPE(Class, Base)                                                      \
    119     case Type::Class: return ASTNodeKind(NKI_##Class##Type);
    120 #define ABSTRACT_TYPE(Class, Base)
    121 #include "clang/AST/TypeNodes.inc"
    122   }
    123   llvm_unreachable("invalid type kind");
    124  }
    125 
    126 ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
    127   switch (C.getClauseKind()) {
    128 #define GEN_CLANG_CLAUSE_CLASS
    129 #define CLAUSE_CLASS(Enum, Str, Class)                                         \
    130   case llvm::omp::Clause::Enum:                                                \
    131     return ASTNodeKind(NKI_##Class);
    132 #define CLAUSE_NO_CLASS(Enum, Str)                                             \
    133   case llvm::omp::Clause::Enum:                                                \
    134     llvm_unreachable("unexpected OpenMP clause kind");
    135 #include "llvm/Frontend/OpenMP/OMP.inc"
    136   }
    137   llvm_unreachable("invalid stmt kind");
    138 }
    139 
    140 void DynTypedNode::print(llvm::raw_ostream &OS,
    141                          const PrintingPolicy &PP) const {
    142   if (const TemplateArgument *TA = get<TemplateArgument>())
    143     TA->print(PP, OS, /*IncludeType*/ true);
    144   else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
    145     TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
    146   else if (const TemplateName *TN = get<TemplateName>())
    147     TN->print(OS, PP);
    148   else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
    149     NNS->print(OS, PP);
    150   else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
    151     if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier())
    152       NNS->print(OS, PP);
    153     else
    154       OS << "(empty NestedNameSpecifierLoc)";
    155   } else if (const QualType *QT = get<QualType>())
    156     QT->print(OS, PP);
    157   else if (const TypeLoc *TL = get<TypeLoc>())
    158     TL->getType().print(OS, PP);
    159   else if (const Decl *D = get<Decl>())
    160     D->print(OS, PP);
    161   else if (const Stmt *S = get<Stmt>())
    162     S->printPretty(OS, nullptr, PP);
    163   else if (const Type *T = get<Type>())
    164     QualType(T, 0).print(OS, PP);
    165   else
    166     OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
    167 }
    168 
    169 void DynTypedNode::dump(llvm::raw_ostream &OS,
    170                         const ASTContext &Context) const {
    171   if (const Decl *D = get<Decl>())
    172     D->dump(OS);
    173   else if (const Stmt *S = get<Stmt>())
    174     S->dump(OS, Context);
    175   else if (const Type *T = get<Type>())
    176     T->dump(OS, Context);
    177   else
    178     OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
    179 }
    180 
    181 SourceRange DynTypedNode::getSourceRange() const {
    182   if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
    183     return CCI->getSourceRange();
    184   if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
    185     return NNSL->getSourceRange();
    186   if (const TypeLoc *TL = get<TypeLoc>())
    187     return TL->getSourceRange();
    188   if (const Decl *D = get<Decl>())
    189     return D->getSourceRange();
    190   if (const Stmt *S = get<Stmt>())
    191     return S->getSourceRange();
    192   if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
    193     return TAL->getSourceRange();
    194   if (const auto *C = get<OMPClause>())
    195     return SourceRange(C->getBeginLoc(), C->getEndLoc());
    196   if (const auto *CBS = get<CXXBaseSpecifier>())
    197     return CBS->getSourceRange();
    198   return SourceRange();
    199 }
    200