1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H |
16 | #define LLVM_CLANG_AST_ASTTYPETRAITS_H |
17 | |
18 | #include "clang/AST/ASTFwd.h" |
19 | #include "clang/AST/Decl.h" |
20 | #include "clang/AST/NestedNameSpecifier.h" |
21 | #include "clang/AST/OpenMPClause.h" |
22 | #include "clang/AST/Stmt.h" |
23 | #include "clang/AST/TemplateBase.h" |
24 | #include "clang/AST/TypeLoc.h" |
25 | #include "clang/Basic/LLVM.h" |
26 | #include "llvm/ADT/DenseMapInfo.h" |
27 | #include "llvm/Support/AlignOf.h" |
28 | |
29 | namespace llvm { |
30 | |
31 | class raw_ostream; |
32 | |
33 | } |
34 | |
35 | namespace clang { |
36 | |
37 | struct PrintingPolicy; |
38 | |
39 | namespace ast_type_traits { |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | class ASTNodeKind { |
47 | public: |
48 | |
49 | ASTNodeKind() : KindId(NKI_None) {} |
50 | |
51 | |
52 | template <class T> |
53 | static ASTNodeKind getFromNodeKind() { |
54 | return ASTNodeKind(KindToKindId<T>::Id); |
55 | } |
56 | |
57 | |
58 | |
59 | static ASTNodeKind getFromNode(const Decl &D); |
60 | static ASTNodeKind getFromNode(const Stmt &S); |
61 | static ASTNodeKind getFromNode(const Type &T); |
62 | static ASTNodeKind getFromNode(const OMPClause &C); |
63 | |
64 | |
65 | |
66 | bool isSame(ASTNodeKind Other) const { |
67 | return KindId != NKI_None && KindId == Other.KindId; |
68 | } |
69 | |
70 | |
71 | bool isNone() const { return KindId == NKI_None; } |
72 | |
73 | |
74 | |
75 | |
76 | bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; |
77 | |
78 | |
79 | StringRef asStringRef() const; |
80 | |
81 | |
82 | bool operator<(const ASTNodeKind &Other) const { |
83 | return KindId < Other.KindId; |
84 | } |
85 | |
86 | |
87 | |
88 | |
89 | static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); |
90 | |
91 | |
92 | |
93 | |
94 | static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, |
95 | ASTNodeKind Kind2); |
96 | |
97 | |
98 | struct DenseMapInfo { |
99 | |
100 | static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } |
101 | |
102 | |
103 | static inline ASTNodeKind getTombstoneKey() { |
104 | return ASTNodeKind(NKI_NumberOfKinds); |
105 | } |
106 | static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } |
107 | static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { |
108 | return LHS.KindId == RHS.KindId; |
109 | } |
110 | }; |
111 | |
112 | |
113 | |
114 | bool hasPointerIdentity() const { |
115 | return KindId > NKI_LastKindWithoutPointerIdentity; |
116 | } |
117 | |
118 | private: |
119 | |
120 | |
121 | |
122 | enum NodeKindId { |
123 | NKI_None, |
124 | NKI_TemplateArgument, |
125 | NKI_TemplateName, |
126 | NKI_NestedNameSpecifierLoc, |
127 | NKI_QualType, |
128 | NKI_TypeLoc, |
129 | NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, |
130 | NKI_CXXCtorInitializer, |
131 | NKI_NestedNameSpecifier, |
132 | NKI_Decl, |
133 | #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, |
134 | #include "clang/AST/DeclNodes.inc" |
135 | NKI_Stmt, |
136 | #define STMT(DERIVED, BASE) NKI_##DERIVED, |
137 | #include "clang/AST/StmtNodes.inc" |
138 | NKI_Type, |
139 | #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, |
140 | #include "clang/AST/TypeNodes.def" |
141 | NKI_OMPClause, |
142 | #define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class, |
143 | #include "clang/Basic/OpenMPKinds.def" |
144 | NKI_NumberOfKinds |
145 | }; |
146 | |
147 | |
148 | ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); |
155 | |
156 | |
157 | |
158 | |
159 | template <class T> struct KindToKindId { |
160 | static const NodeKindId Id = NKI_None; |
161 | }; |
162 | template <class T> |
163 | struct KindToKindId<const T> : KindToKindId<T> {}; |
164 | |
165 | |
166 | struct KindInfo { |
167 | |
168 | NodeKindId ParentId; |
169 | |
170 | const char *Name; |
171 | }; |
172 | static const KindInfo AllKindInfo[NKI_NumberOfKinds]; |
173 | |
174 | NodeKindId KindId; |
175 | }; |
176 | |
177 | #define KIND_TO_KIND_ID(Class) \ |
178 | template <> struct ASTNodeKind::KindToKindId<Class> { \ |
179 | static const NodeKindId Id = NKI_##Class; \ |
180 | }; |
181 | KIND_TO_KIND_ID(CXXCtorInitializer) |
182 | KIND_TO_KIND_ID(TemplateArgument) |
183 | KIND_TO_KIND_ID(TemplateName) |
184 | KIND_TO_KIND_ID(NestedNameSpecifier) |
185 | KIND_TO_KIND_ID(NestedNameSpecifierLoc) |
186 | KIND_TO_KIND_ID(QualType) |
187 | KIND_TO_KIND_ID(TypeLoc) |
188 | KIND_TO_KIND_ID(Decl) |
189 | KIND_TO_KIND_ID(Stmt) |
190 | KIND_TO_KIND_ID(Type) |
191 | KIND_TO_KIND_ID(OMPClause) |
192 | #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) |
193 | #include "clang/AST/DeclNodes.inc" |
194 | #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) |
195 | #include "clang/AST/StmtNodes.inc" |
196 | #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) |
197 | #include "clang/AST/TypeNodes.def" |
198 | #define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class) |
199 | #include "clang/Basic/OpenMPKinds.def" |
200 | #undef KIND_TO_KIND_ID |
201 | |
202 | inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { |
203 | OS << K.asStringRef(); |
204 | return OS; |
205 | } |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | |
219 | class DynTypedNode { |
220 | public: |
221 | |
222 | template <typename T> |
223 | static DynTypedNode create(const T &Node) { |
224 | return BaseConverter<T>::create(Node); |
225 | } |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | |
238 | |
239 | template <typename T> |
240 | const T *get() const { |
241 | return BaseConverter<T>::get(NodeKind, Storage.buffer); |
242 | } |
243 | |
244 | |
245 | |
246 | |
247 | template <typename T> |
248 | const T &getUnchecked() const { |
249 | return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); |
250 | } |
251 | |
252 | ASTNodeKind getNodeKind() const { return NodeKind; } |
253 | |
254 | |
255 | |
256 | |
257 | |
258 | |
259 | const void *getMemoizationData() const { |
260 | return NodeKind.hasPointerIdentity() |
261 | ? *reinterpret_cast<void *const *>(Storage.buffer) |
262 | : nullptr; |
263 | } |
264 | |
265 | |
266 | void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; |
267 | |
268 | |
269 | void dump(llvm::raw_ostream &OS, SourceManager &SM) const; |
270 | |
271 | |
272 | |
273 | SourceRange getSourceRange() const; |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | bool operator<(const DynTypedNode &Other) const { |
282 | if (!NodeKind.isSame(Other.NodeKind)) |
283 | return NodeKind < Other.NodeKind; |
284 | |
285 | if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) |
286 | return getUnchecked<QualType>().getAsOpaquePtr() < |
287 | Other.getUnchecked<QualType>().getAsOpaquePtr(); |
288 | |
289 | if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) { |
290 | auto TLA = getUnchecked<TypeLoc>(); |
291 | auto TLB = Other.getUnchecked<TypeLoc>(); |
292 | return std::make_pair(TLA.getType().getAsOpaquePtr(), |
293 | TLA.getOpaqueData()) < |
294 | std::make_pair(TLB.getType().getAsOpaquePtr(), |
295 | TLB.getOpaqueData()); |
296 | } |
297 | |
298 | if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( |
299 | NodeKind)) { |
300 | auto NNSLA = getUnchecked<NestedNameSpecifierLoc>(); |
301 | auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>(); |
302 | return std::make_pair(NNSLA.getNestedNameSpecifier(), |
303 | NNSLA.getOpaqueData()) < |
304 | std::make_pair(NNSLB.getNestedNameSpecifier(), |
305 | NNSLB.getOpaqueData()); |
306 | } |
307 | |
308 | assert(getMemoizationData() && Other.getMemoizationData()); |
309 | return getMemoizationData() < Other.getMemoizationData(); |
310 | } |
311 | bool operator==(const DynTypedNode &Other) const { |
312 | |
313 | |
314 | if (!NodeKind.isSame(Other.NodeKind)) |
315 | return false; |
316 | |
317 | |
318 | if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) |
319 | return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); |
320 | |
321 | if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) |
322 | return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>(); |
323 | |
324 | if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind)) |
325 | return getUnchecked<NestedNameSpecifierLoc>() == |
326 | Other.getUnchecked<NestedNameSpecifierLoc>(); |
327 | |
328 | assert(getMemoizationData() && Other.getMemoizationData()); |
329 | return getMemoizationData() == Other.getMemoizationData(); |
330 | } |
331 | bool operator!=(const DynTypedNode &Other) const { |
332 | return !operator==(Other); |
333 | } |
334 | |
335 | |
336 | |
337 | struct DenseMapInfo { |
338 | static inline DynTypedNode getEmptyKey() { |
339 | DynTypedNode Node; |
340 | Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey(); |
341 | return Node; |
342 | } |
343 | static inline DynTypedNode getTombstoneKey() { |
344 | DynTypedNode Node; |
345 | Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey(); |
346 | return Node; |
347 | } |
348 | static unsigned getHashValue(const DynTypedNode &Val) { |
349 | |
350 | if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) { |
351 | auto TL = Val.getUnchecked<TypeLoc>(); |
352 | return llvm::hash_combine(TL.getType().getAsOpaquePtr(), |
353 | TL.getOpaqueData()); |
354 | } |
355 | |
356 | if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( |
357 | Val.NodeKind)) { |
358 | auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>(); |
359 | return llvm::hash_combine(NNSL.getNestedNameSpecifier(), |
360 | NNSL.getOpaqueData()); |
361 | } |
362 | |
363 | assert(Val.getMemoizationData()); |
364 | return llvm::hash_value(Val.getMemoizationData()); |
365 | } |
366 | static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) { |
367 | auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey(); |
368 | auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey(); |
369 | return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) && |
370 | ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) || |
371 | (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) && |
372 | ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) || |
373 | LHS == RHS; |
374 | } |
375 | }; |
376 | |
377 | private: |
378 | |
379 | template <typename T, typename EnablerT = void> struct BaseConverter; |
380 | |
381 | |
382 | template <typename T, typename BaseT> struct DynCastPtrConverter { |
383 | static const T *get(ASTNodeKind NodeKind, const char Storage[]) { |
384 | if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) |
385 | return &getUnchecked(NodeKind, Storage); |
386 | return nullptr; |
387 | } |
388 | static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { |
389 | ().isBaseOf(NodeKind)", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ASTTypeTraits.h", 389, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); |
390 | return *cast<T>(static_cast<const BaseT *>( |
391 | *reinterpret_cast<const void *const *>(Storage))); |
392 | } |
393 | static DynTypedNode create(const BaseT &Node) { |
394 | DynTypedNode Result; |
395 | Result.NodeKind = ASTNodeKind::getFromNode(Node); |
396 | new (Result.Storage.buffer) const void *(&Node); |
397 | return Result; |
398 | } |
399 | }; |
400 | |
401 | |
402 | template <typename T> struct PtrConverter { |
403 | static const T *get(ASTNodeKind NodeKind, const char Storage[]) { |
404 | if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) |
405 | return &getUnchecked(NodeKind, Storage); |
406 | return nullptr; |
407 | } |
408 | static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { |
409 | ().isSame(NodeKind)", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ASTTypeTraits.h", 409, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); |
410 | return *static_cast<const T *>( |
411 | *reinterpret_cast<const void *const *>(Storage)); |
412 | } |
413 | static DynTypedNode create(const T &Node) { |
414 | DynTypedNode Result; |
415 | Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); |
416 | new (Result.Storage.buffer) const void *(&Node); |
417 | return Result; |
418 | } |
419 | }; |
420 | |
421 | |
422 | template <typename T> struct ValueConverter { |
423 | static const T *get(ASTNodeKind NodeKind, const char Storage[]) { |
424 | if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) |
425 | return reinterpret_cast<const T *>(Storage); |
426 | return nullptr; |
427 | } |
428 | static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { |
429 | ().isSame(NodeKind)", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ASTTypeTraits.h", 429, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); |
430 | return *reinterpret_cast<const T *>(Storage); |
431 | } |
432 | static DynTypedNode create(const T &Node) { |
433 | DynTypedNode Result; |
434 | Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); |
435 | new (Result.Storage.buffer) T(Node); |
436 | return Result; |
437 | } |
438 | }; |
439 | |
440 | ASTNodeKind NodeKind; |
441 | |
442 | |
443 | |
444 | |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | llvm::AlignedCharArrayUnion<const void *, TemplateArgument, |
451 | NestedNameSpecifierLoc, QualType, |
452 | TypeLoc> Storage; |
453 | }; |
454 | |
455 | template <typename T> |
456 | struct DynTypedNode::BaseConverter< |
457 | T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> |
458 | : public DynCastPtrConverter<T, Decl> {}; |
459 | |
460 | template <typename T> |
461 | struct DynTypedNode::BaseConverter< |
462 | T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> |
463 | : public DynCastPtrConverter<T, Stmt> {}; |
464 | |
465 | template <typename T> |
466 | struct DynTypedNode::BaseConverter< |
467 | T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> |
468 | : public DynCastPtrConverter<T, Type> {}; |
469 | |
470 | template <typename T> |
471 | struct DynTypedNode::BaseConverter< |
472 | T, typename std::enable_if<std::is_base_of<OMPClause, T>::value>::type> |
473 | : public DynCastPtrConverter<T, OMPClause> {}; |
474 | |
475 | template <> |
476 | struct DynTypedNode::BaseConverter< |
477 | NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; |
478 | |
479 | template <> |
480 | struct DynTypedNode::BaseConverter< |
481 | CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; |
482 | |
483 | template <> |
484 | struct DynTypedNode::BaseConverter< |
485 | TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; |
486 | |
487 | template <> |
488 | struct DynTypedNode::BaseConverter< |
489 | TemplateName, void> : public ValueConverter<TemplateName> {}; |
490 | |
491 | template <> |
492 | struct DynTypedNode::BaseConverter< |
493 | NestedNameSpecifierLoc, |
494 | void> : public ValueConverter<NestedNameSpecifierLoc> {}; |
495 | |
496 | template <> |
497 | struct DynTypedNode::BaseConverter<QualType, |
498 | void> : public ValueConverter<QualType> {}; |
499 | |
500 | template <> |
501 | struct DynTypedNode::BaseConverter< |
502 | TypeLoc, void> : public ValueConverter<TypeLoc> {}; |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { |
509 | static const T *get(ASTNodeKind NodeKind, const char Storage[]) { |
510 | return NULL; |
511 | } |
512 | }; |
513 | |
514 | } |
515 | } |
516 | |
517 | namespace llvm { |
518 | |
519 | template <> |
520 | struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> |
521 | : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; |
522 | |
523 | template <> |
524 | struct DenseMapInfo<clang::ast_type_traits::DynTypedNode> |
525 | : clang::ast_type_traits::DynTypedNode::DenseMapInfo {}; |
526 | |
527 | } |
528 | |
529 | #endif |
530 | |