clang  20.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 
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"
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 
62  return isBaseOf(KindId, Other.KindId);
63 }
64 
65 bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
66  return isBaseOf(KindId, Other.KindId, Distance);
67 }
68 
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 
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 
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 
102 StringRef 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 
186 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 
221 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 
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 }
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:187
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:46
attr::Kind getKind() const
Definition: Attr.h:92
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2304
A reference to a concept and its template args, as it appears in the code.
Definition: ASTConcept.h:124
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void dump() const
Definition: ASTDumper.cpp:219
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Kind getKind() const
Definition: DeclBase.h:449
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:434
SourceRange getSourceRange() const
For nodes which represent textual entities in the source code, return their SourceRange.
void dump(llvm::raw_ostream &OS, const ASTContext &Context) const
Dumps the node to the given output stream.
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: Type.h:941
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:84
@ NoStmtClass
Definition: Stmt.h:87
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:524
Represents a template argument.
Definition: TemplateBase.h:61
Represents a C++ template name within the type system.
Definition: TemplateName.h:203
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
The base class of the type hierarchy.
Definition: Type.h:1829
void dump() const
Definition: ASTDumper.cpp:195
TypeClass getTypeClass() const
Definition: Type.h:2334
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