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