clang 22.0.0git
ASTTypeTraits.cpp
Go to the documentation of this file.
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
18#include "clang/AST/Attr.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/DeclObjC.h"
23#include "clang/AST/TypeLoc.h"
24
25using namespace clang;
26
27const 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
62 return isBaseOf(KindId, Other.KindId);
63}
64
65bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
66 return isBaseOf(KindId, Other.KindId, Distance);
67}
68
69bool 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
78bool 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
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
102StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
103
105 ASTNodeKind Kind2) {
106 if (Kind1.isBaseOf(Kind2)) return Kind2;
107 if (Kind2.isBaseOf(Kind1)) return Kind1;
108 return ASTNodeKind();
109}
110
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
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
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
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
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
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
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
186void 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 (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
221void 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
237SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) 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 if (IncludeQualifier)
244 return TL->getSourceRange();
245 switch (TL->getTypeLocClass()) {
246 case TypeLoc::DependentName:
247 return TL->castAs<DependentNameTypeLoc>().getNameLoc();
248 case TypeLoc::TemplateSpecialization: {
250 return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
251 }
252 case TypeLoc::DependentTemplateSpecialization: {
254 return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
255 }
256 case TypeLoc::Enum:
257 case TypeLoc::Record:
258 case TypeLoc::InjectedClassName:
259 return TL->castAs<TagTypeLoc>().getNameLoc();
260 case TypeLoc::Typedef:
261 return TL->castAs<TypedefTypeLoc>().getNameLoc();
262 case TypeLoc::UnresolvedUsing:
263 return TL->castAs<UnresolvedUsingTypeLoc>().getNameLoc();
264 case TypeLoc::Using:
265 return TL->castAs<UsingTypeLoc>().getNameLoc();
266 default:
267 return TL->getSourceRange();
268 }
269 }
270 if (const Decl *D = get<Decl>())
271 return D->getSourceRange();
272 if (const Stmt *S = get<Stmt>())
273 return S->getSourceRange();
274 if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
275 return TAL->getSourceRange();
276 if (const auto *C = get<OMPClause>())
277 return SourceRange(C->getBeginLoc(), C->getEndLoc());
278 if (const auto *CBS = get<CXXBaseSpecifier>())
279 return CBS->getSourceRange();
280 if (const auto *A = get<Attr>())
281 return A->getRange();
282 if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
283 return P->getSourceRange();
284 if (const ConceptReference *C = get<ConceptReference>())
285 return C->getSourceRange();
286 return SourceRange();
287}
This file provides AST data structures related to concepts.
Defines the clang::ASTContext interface.
NodeId Parent
Definition: ASTDiff.cpp:191
StringRef P
const Decl * D
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP AST classes for clauses.
Defines the clang::TypeLoc interface and its subclasses.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
Kind identifier.
Definition: ASTTypeTraits.h:51
StringRef asStringRef() const
String representation of the kind.
bool isBaseOf(ASTNodeKind Other) const
Returns true if this is a base kind of (or same as) Other.
constexpr ASTNodeKind()
Empty identifier. It matches nothing.
Definition: ASTTypeTraits.h:54
ASTNodeKind getCladeKind() const
static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived common ancestor between Kind1 and Kind2.
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived type between Kind1 and Kind2.
static ASTNodeKind getFromNode(const Decl &D)
Attr - This represents one attribute.
Definition: Attr.h:44
attr::Kind getKind() const
Definition: Attr.h:90
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2369
A reference to a concept and its template args, as it appears in the code.
Definition: ASTConcept.h:126
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void dump() const
Definition: ASTDumper.cpp:220
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Kind getKind() const
Definition: DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:427
void dump(llvm::raw_ostream &OS, const ASTContext &Context) const
Dumps the node to the given output stream.
SourceRange getSourceRange(bool IncludeQualifier=false) const
For nodes which represent textual entities in the source code, return their SourceRange.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const
Prints the node to the given output stream.
A C++ nested-name-specifier augmented with source location information.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
A (possibly-)qualified type.
Definition: TypeBase.h:937
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition: Stmt.h:85
@ NoStmtClass
Definition: Stmt.h:88
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:528
Represents a template argument.
Definition: TemplateBase.h:61
Represents a C++ template name within the type system.
Definition: TemplateName.h:222
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
The base class of the type hierarchy.
Definition: TypeBase.h:1833
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
void dump() const
Definition: ASTDumper.cpp:196
TypeClass getTypeClass() const
Definition: TypeBase.h:2403
Wrapper for source info for typedefs.
Definition: TypeLoc.h:782
Wrapper for source info for unresolved typename using decls.
Definition: TypeLoc.h:787
Wrapper for source info for types used via transparent aliases.
Definition: TypeLoc.h:790
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
@ Other
Other implicit parameter.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57