File: ASTTypeTraits.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (238 lines) | stat: -rw-r--r-- 8,711 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//===--- ASTTypeTraits.cpp --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  Provides a dynamic type identifier and a dynamically typed node container
//  that can be used to store an AST base node at runtime in the same storage in
//  a type safe way.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/TypeLoc.h"

using namespace clang;

const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
    {NKI_None, "<None>"},
    {NKI_None, "TemplateArgument"},
    {NKI_None, "TemplateArgumentLoc"},
    {NKI_None, "LambdaCapture"},
    {NKI_None, "TemplateName"},
    {NKI_None, "NestedNameSpecifierLoc"},
    {NKI_None, "QualType"},
#define TYPELOC(CLASS, PARENT) {NKI_##PARENT, #CLASS "TypeLoc"},
#include "clang/AST/TypeLocNodes.def"
    {NKI_None, "TypeLoc"},
    {NKI_None, "CXXBaseSpecifier"},
    {NKI_None, "CXXCtorInitializer"},
    {NKI_None, "NestedNameSpecifier"},
    {NKI_None, "Decl"},
#define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" },
#include "clang/AST/DeclNodes.inc"
    {NKI_None, "Stmt"},
#define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED },
#include "clang/AST/StmtNodes.inc"
    {NKI_None, "Type"},
#define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" },
#include "clang/AST/TypeNodes.inc"
    {NKI_None, "OMPClause"},
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},
#include "llvm/Frontend/OpenMP/OMP.inc"
    {NKI_None, "Attr"},
#define ATTR(A) {NKI_Attr, #A "Attr"},
#include "clang/Basic/AttrList.inc"
    {NKI_None, "ObjCProtocolLoc"},
};

bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
  return isBaseOf(KindId, Other.KindId, Distance);
}

bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
                           unsigned *Distance) {
  if (Base == NKI_None || Derived == NKI_None) return false;
  unsigned Dist = 0;
  while (Derived != Base && Derived != NKI_None) {
    Derived = AllKindInfo[Derived].ParentId;
    ++Dist;
  }
  if (Distance)
    *Distance = Dist;
  return Derived == Base;
}

ASTNodeKind ASTNodeKind::getCladeKind() const {
  NodeKindId LastId = KindId;
  while (LastId) {
    NodeKindId ParentId = AllKindInfo[LastId].ParentId;
    if (ParentId == NKI_None)
      return LastId;
    LastId = ParentId;
  }
  return NKI_None;
}

StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }

ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1,
                                            ASTNodeKind Kind2) {
  if (Kind1.isBaseOf(Kind2)) return Kind2;
  if (Kind2.isBaseOf(Kind1)) return Kind1;
  return ASTNodeKind();
}

ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1,
                                                      ASTNodeKind Kind2) {
  NodeKindId Parent = Kind1.KindId;
  while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) {
    Parent = AllKindInfo[Parent].ParentId;
  }
  return ASTNodeKind(Parent);
}

ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) {
  switch (D.getKind()) {
#define DECL(DERIVED, BASE)                                                    \
    case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl);
#define ABSTRACT_DECL(D)
#include "clang/AST/DeclNodes.inc"
  };
  llvm_unreachable("invalid decl kind");
}

ASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) {
  switch (S.getStmtClass()) {
    case Stmt::NoStmtClass: return NKI_None;
#define STMT(CLASS, PARENT)                                                    \
    case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS);
#define ABSTRACT_STMT(S)
#include "clang/AST/StmtNodes.inc"
  }
  llvm_unreachable("invalid stmt kind");
}

ASTNodeKind ASTNodeKind::getFromNode(const Type &T) {
  switch (T.getTypeClass()) {
#define TYPE(Class, Base)                                                      \
    case Type::Class: return ASTNodeKind(NKI_##Class##Type);
#define ABSTRACT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.inc"
  }
  llvm_unreachable("invalid type kind");
 }

 ASTNodeKind ASTNodeKind::getFromNode(const TypeLoc &T) {
   switch (T.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT)                                                 \
  case TypeLoc::CLASS:                                                         \
    return ASTNodeKind(NKI_##CLASS##TypeLoc);
#include "clang/AST/TypeLocNodes.def"
   }
   llvm_unreachable("invalid typeloc kind");
 }

ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
  switch (C.getClauseKind()) {
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class)                                         \
  case llvm::omp::Clause::Enum:                                                \
    return ASTNodeKind(NKI_##Class);
#define CLAUSE_NO_CLASS(Enum, Str)                                             \
  case llvm::omp::Clause::Enum:                                                \
    llvm_unreachable("unexpected OpenMP clause kind");
#include "llvm/Frontend/OpenMP/OMP.inc"
  }
  llvm_unreachable("invalid omp clause kind");
}

ASTNodeKind ASTNodeKind::getFromNode(const Attr &A) {
  switch (A.getKind()) {
#define ATTR(A)                                                                \
  case attr::A:                                                                \
    return ASTNodeKind(NKI_##A##Attr);
#include "clang/Basic/AttrList.inc"
  }
  llvm_unreachable("invalid attr kind");
}

void DynTypedNode::print(llvm::raw_ostream &OS,
                         const PrintingPolicy &PP) const {
  if (const TemplateArgument *TA = get<TemplateArgument>())
    TA->print(PP, OS, /*IncludeType*/ true);
  else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
    TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
  else if (const TemplateName *TN = get<TemplateName>())
    TN->print(OS, PP);
  else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
    NNS->print(OS, PP);
  else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) {
    if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier())
      NNS->print(OS, PP);
    else
      OS << "(empty NestedNameSpecifierLoc)";
  } else if (const QualType *QT = get<QualType>())
    QT->print(OS, PP);
  else if (const TypeLoc *TL = get<TypeLoc>())
    TL->getType().print(OS, PP);
  else if (const Decl *D = get<Decl>())
    D->print(OS, PP);
  else if (const Stmt *S = get<Stmt>())
    S->printPretty(OS, nullptr, PP);
  else if (const Type *T = get<Type>())
    QualType(T, 0).print(OS, PP);
  else if (const Attr *A = get<Attr>())
    A->printPretty(OS, PP);
  else if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
    P->getProtocol()->print(OS, PP);
  else
    OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
}

void DynTypedNode::dump(llvm::raw_ostream &OS,
                        const ASTContext &Context) const {
  if (const Decl *D = get<Decl>())
    D->dump(OS);
  else if (const Stmt *S = get<Stmt>())
    S->dump(OS, Context);
  else if (const Type *T = get<Type>())
    T->dump(OS, Context);
  else
    OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}

SourceRange DynTypedNode::getSourceRange() const {
  if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
    return CCI->getSourceRange();
  if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
    return NNSL->getSourceRange();
  if (const TypeLoc *TL = get<TypeLoc>())
    return TL->getSourceRange();
  if (const Decl *D = get<Decl>())
    return D->getSourceRange();
  if (const Stmt *S = get<Stmt>())
    return S->getSourceRange();
  if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
    return TAL->getSourceRange();
  if (const auto *C = get<OMPClause>())
    return SourceRange(C->getBeginLoc(), C->getEndLoc());
  if (const auto *CBS = get<CXXBaseSpecifier>())
    return CBS->getSourceRange();
  if (const auto *A = get<Attr>())
    return A->getRange();
  if (const ObjCProtocolLoc *P = get<ObjCProtocolLoc>())
    return P->getSourceRange();
  return SourceRange();
}