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