clang 23.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 {NKI_None, "OffsetOfNode"},
60};
61
63 return isBaseOf(KindId, Other.KindId);
64}
65
66bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
67 return isBaseOf(KindId, Other.KindId, Distance);
68}
69
70bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) {
71 if (Base == NKI_None || Derived == NKI_None)
72 return false;
73 while (Derived != Base && Derived != NKI_None) {
74 Derived = AllKindInfo[Derived].ParentId;
75 }
76 return Derived == Base;
77}
78
79bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
80 unsigned *Distance) {
81 if (Base == NKI_None || Derived == NKI_None) return false;
82 unsigned Dist = 0;
83 while (Derived != Base && Derived != NKI_None) {
84 Derived = AllKindInfo[Derived].ParentId;
85 ++Dist;
86 }
87 if (Distance)
88 *Distance = Dist;
89 return Derived == Base;
90}
91
93 NodeKindId LastId = KindId;
94 while (LastId) {
95 NodeKindId ParentId = AllKindInfo[LastId].ParentId;
96 if (ParentId == NKI_None)
97 return LastId;
98 LastId = ParentId;
99 }
100 return NKI_None;
101}
102
103StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
104
106 ASTNodeKind Kind2) {
107 if (Kind1.isBaseOf(Kind2)) return Kind2;
108 if (Kind2.isBaseOf(Kind1)) return Kind1;
109 return ASTNodeKind();
110}
111
113 ASTNodeKind Kind2) {
114 NodeKindId Parent = Kind1.KindId;
115 while (!isBaseOf(Parent, Kind2.KindId) && Parent != NKI_None) {
116 Parent = AllKindInfo[Parent].ParentId;
117 }
118 return ASTNodeKind(Parent);
119}
120
122 switch (D.getKind()) {
123#define DECL(DERIVED, BASE) \
124 case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);
125#define ABSTRACT_DECL(D)
126#include "clang/AST/DeclNodes.inc"
127 };
128 llvm_unreachable("invalid decl kind");
129}
130
132 switch (S.getStmtClass()) {
133 case Stmt::NoStmtClass: return NKI_None;
134#define STMT(CLASS, PARENT) \
135 case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);
136#define ABSTRACT_STMT(S)
137#include "clang/AST/StmtNodes.inc"
138 }
139 llvm_unreachable("invalid stmt kind");
140}
141
143 switch (T.getTypeClass()) {
144#define TYPE(Class, Base) \
145 case Type::Class: return ASTNodeKind(NKI_##Class##Type);
146#define ABSTRACT_TYPE(Class, Base)
147#include "clang/AST/TypeNodes.inc"
148 }
149 llvm_unreachable("invalid type kind");
150 }
151
153 switch (T.getTypeLocClass()) {
154#define ABSTRACT_TYPELOC(CLASS, PARENT)
155#define TYPELOC(CLASS, PARENT) \
156 case TypeLoc::CLASS: \
157 return ASTNodeKind(NKI_##CLASS##TypeLoc);
158#include "clang/AST/TypeLocNodes.def"
159 }
160 llvm_unreachable("invalid typeloc kind");
161 }
162
164 switch (C.getClauseKind()) {
165#define GEN_CLANG_CLAUSE_CLASS
166#define CLAUSE_CLASS(Enum, Str, Class) \
167 case llvm::omp::Clause::Enum: \
168 return ASTNodeKind(NKI_##Class);
169#define CLAUSE_NO_CLASS(Enum, Str) \
170 case llvm::omp::Clause::Enum: \
171 llvm_unreachable("unexpected OpenMP clause kind");
172#include "llvm/Frontend/OpenMP/OMP.inc"
173 }
174 llvm_unreachable("invalid omp clause kind");
175}
176
178 switch (A.getKind()) {
179#define ATTR(A) \
180 case attr::A: \
181 return ASTNodeKind(NKI_##A##Attr);
182#include "clang/Basic/AttrList.inc"
183 }
184 llvm_unreachable("invalid attr kind");
185}
186
187void DynTypedNode::print(llvm::raw_ostream &OS,
188 const PrintingPolicy &PP) const {
189 if (const TemplateArgument *TA = get<TemplateArgument>())
190 TA->print(PP, OS, /*IncludeType*/ true);
191 else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
192 TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
193 else if (const TemplateName *TN = get<TemplateName>())
194 TN->print(OS, PP);
195 else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
196 NNS->print(OS, PP);
197 else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
198 if (NestedNameSpecifier NNS = NNSL->getNestedNameSpecifier())
199 NNS.print(OS, PP);
200 else
201 OS << "(empty NestedNameSpecifierLoc)";
202 } else if (const QualType *QT = get<QualType>())
203 QT->print(OS, PP);
204 else if (const TypeLoc *TL = get<TypeLoc>())
205 TL->getType().print(OS, PP);
206 else if (const Decl *D = get<Decl>())
207 D->print(OS, PP);
208 else if (const Stmt *S = get<Stmt>())
209 S->printPretty(OS, nullptr, PP);
210 else if (const Type *T = get<Type>())
211 QualType(T, 0).print(OS, PP);
212 else if (const Attr *A = get<Attr>())
213 A->printPretty(OS, PP);
214 else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
215 P->getProtocol()->print(OS, PP);
216 else if (const ConceptReference *C = get<ConceptReference>())
217 C->print(OS, PP);
218 else
219 OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
220}
221
222void DynTypedNode::dump(llvm::raw_ostream &OS,
223 const ASTContext &Context) const {
224 if (const Decl *D = get<Decl>())
225 D->dump(OS);
226 else if (const Stmt *S = get<Stmt>())
227 S->dump(OS, Context);
228 else if (const Type *T = get<Type>())
229 T->dump(OS, Context);
230 else if (const ConceptReference *C = get<ConceptReference>())
231 C->dump(OS);
232 else if (const TypeLoc *TL = get<TypeLoc>())
233 TL->dump(OS, Context);
234 else
235 OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
236}
237
238SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) const {
240 return CCI->getSourceRange();
242 return NNSL->getSourceRange();
243 if (const TypeLoc *TL = get<TypeLoc>()) {
244 if (IncludeQualifier)
245 return TL->getSourceRange();
246 switch (TL->getTypeLocClass()) {
247 case TypeLoc::DependentName:
248 return TL->castAs<DependentNameTypeLoc>().getNameLoc();
249 case TypeLoc::TemplateSpecialization: {
250 auto T = TL->castAs<TemplateSpecializationTypeLoc>();
251 return SourceRange(T.getTemplateNameLoc(), T.getEndLoc());
252 }
253 case TypeLoc::Enum:
254 case TypeLoc::Record:
255 case TypeLoc::InjectedClassName:
256 return TL->castAs<TagTypeLoc>().getNameLoc();
257 case TypeLoc::Typedef:
258 return TL->castAs<TypedefTypeLoc>().getNameLoc();
259 case TypeLoc::UnresolvedUsing:
260 return TL->castAs<UnresolvedUsingTypeLoc>().getNameLoc();
261 case TypeLoc::Using:
262 return TL->castAs<UsingTypeLoc>().getNameLoc();
263 default:
264 return TL->getSourceRange();
265 }
266 }
267 if (const Decl *D = get<Decl>())
268 return D->getSourceRange();
269 if (const Stmt *S = get<Stmt>())
270 return S->getSourceRange();
272 return TAL->getSourceRange();
273 if (const auto *C = get<OMPClause>())
274 return SourceRange(C->getBeginLoc(), C->getEndLoc());
275 if (const auto *CBS = get<CXXBaseSpecifier>())
276 return CBS->getSourceRange();
277 if (const auto *A = get<Attr>())
278 return A->getRange();
279 if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
280 return P->getSourceRange();
282 return C->getSourceRange();
283 if (const OffsetOfNode *O = get<OffsetOfNode>())
284 return O->getSourceRange();
285 return SourceRange();
286}
This file provides AST data structures related to concepts.
Defines the clang::ASTContext interface.
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:227
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.
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:46
attr::Kind getKind() const
Definition Attr.h:92
Represents a C++ base or member initializer.
Definition DeclCXX.h:2389
A reference to a concept and its template args, as it appears in the code.
Definition ASTConcept.h:130
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
Kind getKind() const
Definition DeclBase.h:450
const T * get() const
Retrieve the stored node as type T.
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.
Helper class for OffsetOfExpr.
Definition Expr.h:2424
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:86
@ NoStmtClass
Definition Stmt.h:89
StmtClass getStmtClass() const
Definition Stmt.h:1499
Location wrapper for a TemplateArgument.
Represents a template argument.
Represents a C++ template name within the type system.
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
The base class of the type hierarchy.
Definition TypeBase.h:1871
Wrapper for source info for typedefs.
Definition TypeLoc.h:777
Wrapper for source info for unresolved typename using decls.
Definition TypeLoc.h:782
Wrapper for source info for types used via transparent aliases.
Definition TypeLoc.h:785
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
Definition Decl.h:1761
Describes how types, statements, expressions, and declarations should be printed.