clang  15.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/ASTContext.h"
17 #include "clang/AST/Attr.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclObjC.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/TypeLoc.h"
23 
24 using namespace clang;
25 
26 const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
27  {NKI_None, "<None>"},
28  {NKI_None, "TemplateArgument"},
29  {NKI_None, "TemplateArgumentLoc"},
30  {NKI_None, "LambdaCapture"},
31  {NKI_None, "TemplateName"},
32  {NKI_None, "NestedNameSpecifierLoc"},
33  {NKI_None, "QualType"},
34 #define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
35 #include "clang/AST/TypeLocNodes.def"
36  {NKI_None, "TypeLoc"},
37  {NKI_None, "CXXBaseSpecifier"},
38  {NKI_None, "CXXCtorInitializer"},
39  {NKI_None, "NestedNameSpecifier"},
40  {NKI_None, "Decl"},
41 #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" },
42 #include "clang/AST/DeclNodes.inc"
43  {NKI_None, "Stmt"},
44 #define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED },
45 #include "clang/AST/StmtNodes.inc"
46  {NKI_None, "Type"},
47 #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" },
48 #include "clang/AST/TypeNodes.inc"
49  {NKI_None, "OMPClause"},
50 #define GEN_CLANG_CLAUSE_CLASS
51 #define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},
52 #include "llvm/Frontend/OpenMP/OMP.inc"
53  {NKI_None, "Attr"},
54 #define ATTR(A) {NKI_Attr, #A "Attr"},
55 #include "clang/Basic/AttrList.inc"
56  {NKI_None, "ObjCProtocolLoc"},
57 };
58 
59 bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
60  return isBaseOf(KindId, Other.KindId, Distance);
61 }
62 
63 bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
64  unsigned *Distance) {
65  if (Base == NKI_None || Derived == NKI_None) return false;
66  unsigned Dist = 0;
67  while (Derived != Base && Derived != NKI_None) {
68  Derived = AllKindInfo[Derived].ParentId;
69  ++Dist;
70  }
71  if (Distance)
72  *Distance = Dist;
73  return Derived == Base;
74 }
75 
77  NodeKindId LastId = KindId;
78  while (LastId) {
79  NodeKindId ParentId = AllKindInfo[LastId].ParentId;
80  if (ParentId == NKI_None)
81  return LastId;
82  LastId = ParentId;
83  }
84  return NKI_None;
85 }
86 
87 StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
88 
90  ASTNodeKind Kind2) {
91  if (Kind1.isBaseOf(Kind2)) return Kind2;
92  if (Kind2.isBaseOf(Kind1)) return Kind1;
93  return ASTNodeKind();
94 }
95 
97  ASTNodeKind Kind2) {
98  NodeKindId Parent = Kind1.KindId;
99  while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) {
100  Parent = AllKindInfo[Parent].ParentId;
101  }
102  return ASTNodeKind(Parent);
103 }
104 
106  switch (D.getKind()) {
107 #define DECL(DERIVED, BASE) \
108  case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);
109 #define ABSTRACT_DECL(D)
110 #include "clang/AST/DeclNodes.inc"
111  };
112  llvm_unreachable("invalid decl kind");
113 }
114 
116  switch (S.getStmtClass()) {
117  case Stmt::NoStmtClass: return NKI_None;
118 #define STMT(CLASS, PARENT) \
119  case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);
120 #define ABSTRACT_STMT(S)
121 #include "clang/AST/StmtNodes.inc"
122  }
123  llvm_unreachable("invalid stmt kind");
124 }
125 
127  switch (T.getTypeClass()) {
128 #define TYPE(Class, Base) \
129  case Type::Class: return ASTNodeKind(NKI_##Class##Type);
130 #define ABSTRACT_TYPE(Class, Base)
131 #include "clang/AST/TypeNodes.inc"
132  }
133  llvm_unreachable("invalid type kind");
134  }
135 
137  switch (T.getTypeLocClass()) {
138 #define ABSTRACT_TYPELOC(CLASS, PARENT)
139 #define TYPELOC(CLASS, PARENT) \
140  case TypeLoc::CLASS: \
141  return ASTNodeKind(NKI_##CLASS##TypeLoc);
142 #include "clang/AST/TypeLocNodes.def"
143  }
144  llvm_unreachable("invalid typeloc kind");
145  }
146 
148  switch (C.getClauseKind()) {
149 #define GEN_CLANG_CLAUSE_CLASS
150 #define CLAUSE_CLASS(Enum, Str, Class) \
151  case llvm::omp::Clause::Enum: \
152  return ASTNodeKind(NKI_##Class);
153 #define CLAUSE_NO_CLASS(Enum, Str) \
154  case llvm::omp::Clause::Enum: \
155  llvm_unreachable("unexpected OpenMP clause kind");
156 #include "llvm/Frontend/OpenMP/OMP.inc"
157  }
158  llvm_unreachable("invalid omp clause kind");
159 }
160 
162  switch (A.getKind()) {
163 #define ATTR(A) \
164  case attr::A: \
165  return ASTNodeKind(NKI_##A##Attr);
166 #include "clang/Basic/AttrList.inc"
167  }
168  llvm_unreachable("invalid attr kind");
169 }
170 
171 void DynTypedNode::print(llvm::raw_ostream &OS,
172  const PrintingPolicy &PP) const {
173  if (const TemplateArgument *TA = get<TemplateArgument>())
174  TA->print(PP, OS, /*IncludeType*/ true);
175  else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
176  TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
177  else if (const TemplateName *TN = get<TemplateName>())
178  TN->print(OS, PP);
179  else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
180  NNS->print(OS, PP);
181  else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
182  if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier())
183  NNS->print(OS, PP);
184  else
185  OS << "(empty NestedNameSpecifierLoc)";
186  } else if (const QualType *QT = get<QualType>())
187  QT->print(OS, PP);
188  else if (const TypeLoc *TL = get<TypeLoc>())
189  TL->getType().print(OS, PP);
190  else if (const Decl *D = get<Decl>())
191  D->print(OS, PP);
192  else if (const Stmt *S = get<Stmt>())
193  S->printPretty(OS, nullptr, PP);
194  else if (const Type *T = get<Type>())
195  QualType(T, 0).print(OS, PP);
196  else if (const Attr *A = get<Attr>())
197  A->printPretty(OS, PP);
198  else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
199  P->getProtocol()->print(OS, PP);
200  else
201  OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
202 }
203 
204 void DynTypedNode::dump(llvm::raw_ostream &OS,
205  const ASTContext &Context) const {
206  if (const Decl *D = get<Decl>())
207  D->dump(OS);
208  else if (const Stmt *S = get<Stmt>())
209  S->dump(OS, Context);
210  else if (const Type *T = get<Type>())
211  T->dump(OS, Context);
212  else
213  OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
214 }
215 
217  if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
218  return CCI->getSourceRange();
219  if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
220  return NNSL->getSourceRange();
221  if (const TypeLoc *TL = get<TypeLoc>())
222  return TL->getSourceRange();
223  if (const Decl *D = get<Decl>())
224  return D->getSourceRange();
225  if (const Stmt *S = get<Stmt>())
226  return S->getSourceRange();
227  if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
228  return TAL->getSourceRange();
229  if (const auto *C = get<OMPClause>())
230  return SourceRange(C->getBeginLoc(), C->getEndLoc());
231  if (const auto *CBS = get<CXXBaseSpecifier>())
232  return CBS->getSourceRange();
233  if (const auto *A = get<Attr>())
234  return A->getRange();
235  if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
236  return P->getSourceRange();
237  return SourceRange();
238 }
clang::ASTNodeKind::isBaseOf
bool isBaseOf(ASTNodeKind Other, unsigned *Distance=nullptr) const
Returns true if this is a base kind of (or same as) Other.
Definition: ASTTypeTraits.cpp:59
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:210
clang::DynTypedNode::dump
void dump(llvm::raw_ostream &OS, const ASTContext &Context) const
Dumps the node to the given output stream.
Definition: ASTTypeTraits.cpp:204
clang::ASTNodeKind::getMostDerivedCommonAncestor
static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived common ancestor between Kind1 and Kind2.
Definition: ASTTypeTraits.cpp:96
clang::DynTypedNode::getSourceRange
SourceRange getSourceRange() const
For nodes which represent textual entities in the source code, return their SourceRange.
Definition: ASTTypeTraits.cpp:216
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:731
Attr.h
clang::NestedNameSpecifier
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
Definition: NestedNameSpecifier.h:50
DeclCXX.h
clang::PrintingPolicy
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
clang::ASTNodeKind::ASTNodeKind
ASTNodeKind()
Empty identifier. It matches nothing.
Definition: ASTTypeTraits.h:54
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1556
clang::Stmt::NoStmtClass
@ NoStmtClass
Definition: Stmt.h:73
DeclObjC.h
clang::Decl::getKind
Kind getKind() const
Definition: DeclBase.h:435
clang::OMPClause
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:208
NestedNameSpecifier.h
clang::TemplateArgument
Represents a template argument.
Definition: TemplateBase.h:61
clang::Attr::getKind
attr::Kind getKind() const
Definition: Attr.h:81
clang::TemplateArgumentLoc
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:457
ASTContext.h
clang::NestedNameSpecifierLoc
A C++ nested-name-specifier augmented with source location information.
Definition: NestedNameSpecifier.h:243
Base
clang::Type::getTypeClass
TypeClass getTypeClass() const
Definition: Type.h:1927
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::TemplateName
Represents a C++ template name within the type system.
Definition: TemplateName.h:192
clang::DynTypedNode::print
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const
Prints the node to the given output stream.
Definition: ASTTypeTraits.cpp:171
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
OpenMPClause.h
clang::TypeLoc
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:58
ASTTypeTraits.h
clang::ASTNodeKind
Kind identifier.
Definition: ASTTypeTraits.h:51
clang::TypeLoc::getTypeLocClass
TypeLocClass getTypeLocClass() const
Definition: TypeLoc.h:115
clang
Definition: CalledOnceCheck.h:17
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:70
clang::Attr
Attr - This represents one attribute.
Definition: Attr.h:41
Parent
NodeId Parent
Definition: ASTDiff.cpp:192
clang::QualType::print
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Definition: TypePrinter.cpp:2316
clang::ASTNodeKind::getMostDerivedType
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2)
Return the most derived type between Kind1 and Kind2.
Definition: ASTTypeTraits.cpp:89
clang::CXXCtorInitializer
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2205
clang::ASTNodeKind::getCladeKind
ASTNodeKind getCladeKind() const
Definition: ASTTypeTraits.cpp:76
clang::ObjCProtocolLoc
Definition: TypeLoc.h:2635
clang::ASTNodeKind::asStringRef
StringRef asStringRef() const
String representation of the kind.
Definition: ASTTypeTraits.cpp:87
clang::ASTNodeKind::getFromNode
static ASTNodeKind getFromNode(const Decl &D)
Definition: ASTTypeTraits.cpp:105
TypeLoc.h