1 | //===- TypeLoc.h - Type Source Info Wrapper ---------------------*- 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 | /// \file |
10 | /// Defines the clang::TypeLoc interface and its subclasses. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_AST_TYPELOC_H |
15 | #define LLVM_CLANG_AST_TYPELOC_H |
16 | |
17 | #include "clang/AST/ASTConcept.h" |
18 | #include "clang/AST/DeclarationName.h" |
19 | #include "clang/AST/NestedNameSpecifier.h" |
20 | #include "clang/AST/TemplateBase.h" |
21 | #include "clang/AST/Type.h" |
22 | #include "clang/Basic/LLVM.h" |
23 | #include "clang/Basic/SourceLocation.h" |
24 | #include "clang/Basic/Specifiers.h" |
25 | #include "llvm/ADT/ArrayRef.h" |
26 | #include "llvm/Support/Casting.h" |
27 | #include "llvm/Support/Compiler.h" |
28 | #include "llvm/Support/MathExtras.h" |
29 | #include <algorithm> |
30 | #include <cassert> |
31 | #include <cstdint> |
32 | #include <cstring> |
33 | |
34 | namespace clang { |
35 | |
36 | class Attr; |
37 | class ASTContext; |
38 | class CXXRecordDecl; |
39 | class ConceptDecl; |
40 | class Expr; |
41 | class ObjCInterfaceDecl; |
42 | class ObjCProtocolDecl; |
43 | class ObjCTypeParamDecl; |
44 | class ParmVarDecl; |
45 | class TemplateTypeParmDecl; |
46 | class UnqualTypeLoc; |
47 | class UnresolvedUsingTypenameDecl; |
48 | |
49 | // Predeclare all the type nodes. |
50 | #define ABSTRACT_TYPELOC(Class, Base) |
51 | #define TYPELOC(Class, Base) \ |
52 | class Class##TypeLoc; |
53 | #include "clang/AST/TypeLocNodes.def" |
54 | |
55 | /// Base wrapper for a particular "section" of type source info. |
56 | /// |
57 | /// A client should use the TypeLoc subclasses through castAs()/getAs() |
58 | /// in order to get at the actual information. |
59 | class TypeLoc { |
60 | protected: |
61 | // The correctness of this relies on the property that, for Type *Ty, |
62 | // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty |
63 | const void *Ty = nullptr; |
64 | void *Data = nullptr; |
65 | |
66 | public: |
67 | TypeLoc() = default; |
68 | TypeLoc(QualType ty, void *opaqueData) |
69 | : Ty(ty.getAsOpaquePtr()), Data(opaqueData) {} |
70 | TypeLoc(const Type *ty, void *opaqueData) |
71 | : Ty(ty), Data(opaqueData) {} |
72 | |
73 | /// Convert to the specified TypeLoc type, asserting that this TypeLoc |
74 | /// is of the desired type. |
75 | /// |
76 | /// \pre T::isKind(*this) |
77 | template<typename T> |
78 | T castAs() const { |
79 | assert(T::isKind(*this)); |
80 | T t; |
81 | TypeLoc& tl = t; |
82 | tl = *this; |
83 | return t; |
84 | } |
85 | |
86 | /// Convert to the specified TypeLoc type, returning a null TypeLoc if |
87 | /// this TypeLoc is not of the desired type. |
88 | template<typename T> |
89 | T getAs() const { |
90 | if (!T::isKind(*this)) |
91 | return {}; |
92 | T t; |
93 | TypeLoc& tl = t; |
94 | tl = *this; |
95 | return t; |
96 | } |
97 | |
98 | /// Convert to the specified TypeLoc type, returning a null TypeLoc if |
99 | /// this TypeLoc is not of the desired type. It will consider type |
100 | /// adjustments from a type that was written as a T to another type that is |
101 | /// still canonically a T (ignores parens, attributes, elaborated types, etc). |
102 | template <typename T> |
103 | T getAsAdjusted() const; |
104 | |
105 | /// The kinds of TypeLocs. Equivalent to the Type::TypeClass enum, |
106 | /// except it also defines a Qualified enum that corresponds to the |
107 | /// QualifiedLoc class. |
108 | enum TypeLocClass { |
109 | #define ABSTRACT_TYPE(Class, Base) |
110 | #define TYPE(Class, Base) \ |
111 | Class = Type::Class, |
112 | #include "clang/AST/TypeNodes.inc" |
113 | Qualified |
114 | }; |
115 | |
116 | TypeLocClass getTypeLocClass() const { |
117 | if (getType().hasLocalQualifiers()) return Qualified; |
118 | return (TypeLocClass) getType()->getTypeClass(); |
119 | } |
120 | |
121 | bool isNull() const { return !Ty; } |
122 | explicit operator bool() const { return Ty; } |
123 | |
124 | /// Returns the size of type source info data block for the given type. |
125 | static unsigned getFullDataSizeForType(QualType Ty); |
126 | |
127 | /// Returns the alignment of type source info data block for |
128 | /// the given type. |
129 | static unsigned getLocalAlignmentForType(QualType Ty); |
130 | |
131 | /// Get the type for which this source info wrapper provides |
132 | /// information. |
133 | QualType getType() const { |
134 | return QualType::getFromOpaquePtr(Ptr: Ty); |
135 | } |
136 | |
137 | const Type *getTypePtr() const { |
138 | return QualType::getFromOpaquePtr(Ptr: Ty).getTypePtr(); |
139 | } |
140 | |
141 | /// Get the pointer where source information is stored. |
142 | void *getOpaqueData() const { |
143 | return Data; |
144 | } |
145 | |
146 | /// Get the begin source location. |
147 | SourceLocation getBeginLoc() const; |
148 | |
149 | /// Get the end source location. |
150 | SourceLocation getEndLoc() const; |
151 | |
152 | /// Get the full source range. |
153 | SourceRange getSourceRange() const LLVM_READONLY { |
154 | return SourceRange(getBeginLoc(), getEndLoc()); |
155 | } |
156 | |
157 | |
158 | /// Get the local source range. |
159 | SourceRange getLocalSourceRange() const { |
160 | return getLocalSourceRangeImpl(TL: *this); |
161 | } |
162 | |
163 | /// Returns the size of the type source info data block. |
164 | unsigned getFullDataSize() const { |
165 | return getFullDataSizeForType(Ty: getType()); |
166 | } |
167 | |
168 | /// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the |
169 | /// TypeLoc is a PointerLoc and next TypeLoc is for "int". |
170 | TypeLoc getNextTypeLoc() const { |
171 | return getNextTypeLocImpl(TL: *this); |
172 | } |
173 | |
174 | /// Skips past any qualifiers, if this is qualified. |
175 | UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header |
176 | |
177 | TypeLoc IgnoreParens() const; |
178 | |
179 | /// Find a type with the location of an explicit type qualifier. |
180 | /// |
181 | /// The result, if non-null, will be one of: |
182 | /// QualifiedTypeLoc |
183 | /// AtomicTypeLoc |
184 | /// AttributedTypeLoc, for those type attributes that behave as qualifiers |
185 | TypeLoc findExplicitQualifierLoc() const; |
186 | |
187 | /// Get the typeloc of an AutoType whose type will be deduced for a variable |
188 | /// with an initializer of this type. This looks through declarators like |
189 | /// pointer types, but not through decltype or typedefs. |
190 | AutoTypeLoc getContainedAutoTypeLoc() const; |
191 | |
192 | /// Get the SourceLocation of the template keyword (if any). |
193 | SourceLocation getTemplateKeywordLoc() const; |
194 | |
195 | /// Initializes this to state that every location in this |
196 | /// type is the given location. |
197 | /// |
198 | /// This method exists to provide a simple transition for code that |
199 | /// relies on location-less types. |
200 | void initialize(ASTContext &Context, SourceLocation Loc) const { |
201 | initializeImpl(Context, TL: *this, Loc); |
202 | } |
203 | |
204 | /// Initializes this by copying its information from another |
205 | /// TypeLoc of the same type. |
206 | void initializeFullCopy(TypeLoc Other) { |
207 | assert(getType() == Other.getType()); |
208 | copy(other: Other); |
209 | } |
210 | |
211 | /// Initializes this by copying its information from another |
212 | /// TypeLoc of the same type. The given size must be the full data |
213 | /// size. |
214 | void initializeFullCopy(TypeLoc Other, unsigned Size) { |
215 | assert(getType() == Other.getType()); |
216 | assert(getFullDataSize() == Size); |
217 | copy(other: Other); |
218 | } |
219 | |
220 | /// Copies the other type loc into this one. |
221 | void copy(TypeLoc other); |
222 | |
223 | friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) { |
224 | return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; |
225 | } |
226 | |
227 | friend bool operator!=(const TypeLoc &LHS, const TypeLoc &RHS) { |
228 | return !(LHS == RHS); |
229 | } |
230 | |
231 | /// Find the location of the nullability specifier (__nonnull, |
232 | /// __nullable, or __null_unspecifier), if there is one. |
233 | SourceLocation findNullabilityLoc() const; |
234 | |
235 | void dump() const; |
236 | void dump(llvm::raw_ostream &, const ASTContext &) const; |
237 | |
238 | private: |
239 | static bool isKind(const TypeLoc&) { |
240 | return true; |
241 | } |
242 | |
243 | static void initializeImpl(ASTContext &Context, TypeLoc TL, |
244 | SourceLocation Loc); |
245 | static TypeLoc getNextTypeLocImpl(TypeLoc TL); |
246 | static TypeLoc IgnoreParensImpl(TypeLoc TL); |
247 | static SourceRange getLocalSourceRangeImpl(TypeLoc TL); |
248 | }; |
249 | |
250 | inline TypeSourceInfo::TypeSourceInfo(QualType ty, size_t DataSize) : Ty(ty) { |
251 | // Init data attached to the object. See getTypeLoc. |
252 | memset(s: static_cast<void *>(this + 1), c: 0, n: DataSize); |
253 | } |
254 | |
255 | /// Return the TypeLoc for a type source info. |
256 | inline TypeLoc TypeSourceInfo::getTypeLoc() const { |
257 | // TODO: is this alignment already sufficient? |
258 | return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); |
259 | } |
260 | |
261 | /// Wrapper of type source information for a type with |
262 | /// no direct qualifiers. |
263 | class UnqualTypeLoc : public TypeLoc { |
264 | public: |
265 | UnqualTypeLoc() = default; |
266 | UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} |
267 | |
268 | const Type *getTypePtr() const { |
269 | return reinterpret_cast<const Type*>(Ty); |
270 | } |
271 | |
272 | TypeLocClass getTypeLocClass() const { |
273 | return (TypeLocClass) getTypePtr()->getTypeClass(); |
274 | } |
275 | |
276 | private: |
277 | friend class TypeLoc; |
278 | |
279 | static bool isKind(const TypeLoc &TL) { |
280 | return !TL.getType().hasLocalQualifiers(); |
281 | } |
282 | }; |
283 | |
284 | /// Wrapper of type source information for a type with |
285 | /// non-trivial direct qualifiers. |
286 | /// |
287 | /// Currently, we intentionally do not provide source location for |
288 | /// type qualifiers. |
289 | class QualifiedTypeLoc : public TypeLoc { |
290 | public: |
291 | SourceRange getLocalSourceRange() const { return {}; } |
292 | |
293 | UnqualTypeLoc getUnqualifiedLoc() const { |
294 | unsigned align = |
295 | TypeLoc::getLocalAlignmentForType(Ty: QualType(getTypePtr(), 0)); |
296 | auto dataInt = reinterpret_cast<uintptr_t>(Data); |
297 | dataInt = llvm::alignTo(Value: dataInt, Align: align); |
298 | return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt)); |
299 | } |
300 | |
301 | /// Initializes the local data of this type source info block to |
302 | /// provide no information. |
303 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
304 | // do nothing |
305 | } |
306 | |
307 | void copyLocal(TypeLoc other) { |
308 | // do nothing |
309 | } |
310 | |
311 | TypeLoc getNextTypeLoc() const { |
312 | return getUnqualifiedLoc(); |
313 | } |
314 | |
315 | /// Returns the size of the type source info data block that is |
316 | /// specific to this type. |
317 | unsigned getLocalDataSize() const { |
318 | // In fact, we don't currently preserve any location information |
319 | // for qualifiers. |
320 | return 0; |
321 | } |
322 | |
323 | /// Returns the alignment of the type source info data block that is |
324 | /// specific to this type. |
325 | unsigned getLocalDataAlignment() const { |
326 | // We don't preserve any location information. |
327 | return 1; |
328 | } |
329 | |
330 | private: |
331 | friend class TypeLoc; |
332 | |
333 | static bool isKind(const TypeLoc &TL) { |
334 | return TL.getType().hasLocalQualifiers(); |
335 | } |
336 | }; |
337 | |
338 | inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { |
339 | if (QualifiedTypeLoc Loc = getAs<QualifiedTypeLoc>()) |
340 | return Loc.getUnqualifiedLoc(); |
341 | return castAs<UnqualTypeLoc>(); |
342 | } |
343 | |
344 | /// A metaprogramming base class for TypeLoc classes which correspond |
345 | /// to a particular Type subclass. It is accepted for a single |
346 | /// TypeLoc class to correspond to multiple Type classes. |
347 | /// |
348 | /// \tparam Base a class from which to derive |
349 | /// \tparam Derived the class deriving from this one |
350 | /// \tparam TypeClass the concrete Type subclass associated with this |
351 | /// location type |
352 | /// \tparam LocalData the structure type of local location data for |
353 | /// this type |
354 | /// |
355 | /// TypeLocs with non-constant amounts of local data should override |
356 | /// getExtraLocalDataSize(); getExtraLocalData() will then point to |
357 | /// this extra memory. |
358 | /// |
359 | /// TypeLocs with an inner type should define |
360 | /// QualType getInnerType() const |
361 | /// and getInnerTypeLoc() will then point to this inner type's |
362 | /// location data. |
363 | /// |
364 | /// A word about hierarchies: this template is not designed to be |
365 | /// derived from multiple times in a hierarchy. It is also not |
366 | /// designed to be used for classes where subtypes might provide |
367 | /// different amounts of source information. It should be subclassed |
368 | /// only at the deepest portion of the hierarchy where all children |
369 | /// have identical source information; if that's an abstract type, |
370 | /// then further descendents should inherit from |
371 | /// InheritingConcreteTypeLoc instead. |
372 | template <class Base, class Derived, class TypeClass, class LocalData> |
373 | class ConcreteTypeLoc : public Base { |
374 | friend class TypeLoc; |
375 | |
376 | const Derived *asDerived() const { |
377 | return static_cast<const Derived*>(this); |
378 | } |
379 | |
380 | static bool isKind(const TypeLoc &TL) { |
381 | return !TL.getType().hasLocalQualifiers() && |
382 | Derived::classofType(TL.getTypePtr()); |
383 | } |
384 | |
385 | static bool classofType(const Type *Ty) { |
386 | return TypeClass::classof(Ty); |
387 | } |
388 | |
389 | public: |
390 | unsigned getLocalDataAlignment() const { |
391 | return std::max(unsigned(alignof(LocalData)), |
392 | asDerived()->getExtraLocalDataAlignment()); |
393 | } |
394 | |
395 | unsigned getLocalDataSize() const { |
396 | unsigned size = sizeof(LocalData); |
397 | unsigned = asDerived()->getExtraLocalDataAlignment(); |
398 | size = llvm::alignTo(Value: size, Align: extraAlign); |
399 | size += asDerived()->getExtraLocalDataSize(); |
400 | return size; |
401 | } |
402 | |
403 | void copyLocal(Derived other) { |
404 | // Some subclasses have no data to copy. |
405 | if (asDerived()->getLocalDataSize() == 0) return; |
406 | |
407 | // Copy the fixed-sized local data. |
408 | memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData)); |
409 | |
410 | // Copy the variable-sized local data. We need to do this |
411 | // separately because the padding in the source and the padding in |
412 | // the destination might be different. |
413 | memcpy(getExtraLocalData(), other.getExtraLocalData(), |
414 | asDerived()->getExtraLocalDataSize()); |
415 | } |
416 | |
417 | TypeLoc getNextTypeLoc() const { |
418 | return getNextTypeLoc(asDerived()->getInnerType()); |
419 | } |
420 | |
421 | const TypeClass *getTypePtr() const { |
422 | return cast<TypeClass>(Base::getTypePtr()); |
423 | } |
424 | |
425 | protected: |
426 | unsigned () const { |
427 | return 0; |
428 | } |
429 | |
430 | unsigned () const { |
431 | return 1; |
432 | } |
433 | |
434 | LocalData *getLocalData() const { |
435 | return static_cast<LocalData*>(Base::Data); |
436 | } |
437 | |
438 | /// Gets a pointer past the Info structure; useful for classes with |
439 | /// local data that can't be captured in the Info (e.g. because it's |
440 | /// of variable size). |
441 | void *() const { |
442 | unsigned size = sizeof(LocalData); |
443 | unsigned = asDerived()->getExtraLocalDataAlignment(); |
444 | size = llvm::alignTo(Value: size, Align: extraAlign); |
445 | return reinterpret_cast<char *>(Base::Data) + size; |
446 | } |
447 | |
448 | void *getNonLocalData() const { |
449 | auto data = reinterpret_cast<uintptr_t>(Base::Data); |
450 | data += asDerived()->getLocalDataSize(); |
451 | data = llvm::alignTo(data, getNextTypeAlign()); |
452 | return reinterpret_cast<void*>(data); |
453 | } |
454 | |
455 | struct HasNoInnerType {}; |
456 | HasNoInnerType getInnerType() const { return HasNoInnerType(); } |
457 | |
458 | TypeLoc getInnerTypeLoc() const { |
459 | return TypeLoc(asDerived()->getInnerType(), getNonLocalData()); |
460 | } |
461 | |
462 | private: |
463 | unsigned getInnerTypeSize() const { |
464 | return getInnerTypeSize(asDerived()->getInnerType()); |
465 | } |
466 | |
467 | unsigned getInnerTypeSize(HasNoInnerType _) const { |
468 | return 0; |
469 | } |
470 | |
471 | unsigned getInnerTypeSize(QualType _) const { |
472 | return getInnerTypeLoc().getFullDataSize(); |
473 | } |
474 | |
475 | unsigned getNextTypeAlign() const { |
476 | return getNextTypeAlign(asDerived()->getInnerType()); |
477 | } |
478 | |
479 | unsigned getNextTypeAlign(HasNoInnerType _) const { |
480 | return 1; |
481 | } |
482 | |
483 | unsigned getNextTypeAlign(QualType T) const { |
484 | return TypeLoc::getLocalAlignmentForType(Ty: T); |
485 | } |
486 | |
487 | TypeLoc getNextTypeLoc(HasNoInnerType _) const { return {}; } |
488 | |
489 | TypeLoc getNextTypeLoc(QualType T) const { |
490 | return TypeLoc(T, getNonLocalData()); |
491 | } |
492 | }; |
493 | |
494 | /// A metaprogramming class designed for concrete subtypes of abstract |
495 | /// types where all subtypes share equivalently-structured source |
496 | /// information. See the note on ConcreteTypeLoc. |
497 | template <class Base, class Derived, class TypeClass> |
498 | class InheritingConcreteTypeLoc : public Base { |
499 | friend class TypeLoc; |
500 | |
501 | static bool classofType(const Type *Ty) { |
502 | return TypeClass::classof(Ty); |
503 | } |
504 | |
505 | static bool isKind(const TypeLoc &TL) { |
506 | return !TL.getType().hasLocalQualifiers() && |
507 | Derived::classofType(TL.getTypePtr()); |
508 | } |
509 | static bool isKind(const UnqualTypeLoc &TL) { |
510 | return Derived::classofType(TL.getTypePtr()); |
511 | } |
512 | |
513 | public: |
514 | const TypeClass *getTypePtr() const { |
515 | return cast<TypeClass>(Base::getTypePtr()); |
516 | } |
517 | }; |
518 | |
519 | struct TypeSpecLocInfo { |
520 | SourceLocation NameLoc; |
521 | }; |
522 | |
523 | /// A reasonable base class for TypeLocs that correspond to |
524 | /// types that are written as a type-specifier. |
525 | class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
526 | TypeSpecTypeLoc, |
527 | Type, |
528 | TypeSpecLocInfo> { |
529 | public: |
530 | enum { |
531 | LocalDataSize = sizeof(TypeSpecLocInfo), |
532 | LocalDataAlignment = alignof(TypeSpecLocInfo) |
533 | }; |
534 | |
535 | SourceLocation getNameLoc() const { |
536 | return this->getLocalData()->NameLoc; |
537 | } |
538 | |
539 | void setNameLoc(SourceLocation Loc) { |
540 | this->getLocalData()->NameLoc = Loc; |
541 | } |
542 | |
543 | SourceRange getLocalSourceRange() const { |
544 | return SourceRange(getNameLoc(), getNameLoc()); |
545 | } |
546 | |
547 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
548 | setNameLoc(Loc); |
549 | } |
550 | |
551 | private: |
552 | friend class TypeLoc; |
553 | |
554 | static bool isKind(const TypeLoc &TL); |
555 | }; |
556 | |
557 | struct BuiltinLocInfo { |
558 | SourceRange BuiltinRange; |
559 | }; |
560 | |
561 | /// Wrapper for source info for builtin types. |
562 | class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
563 | BuiltinTypeLoc, |
564 | BuiltinType, |
565 | BuiltinLocInfo> { |
566 | public: |
567 | SourceLocation getBuiltinLoc() const { |
568 | return getLocalData()->BuiltinRange.getBegin(); |
569 | } |
570 | |
571 | void setBuiltinLoc(SourceLocation Loc) { |
572 | getLocalData()->BuiltinRange = Loc; |
573 | } |
574 | |
575 | void expandBuiltinRange(SourceRange Range) { |
576 | SourceRange &BuiltinRange = getLocalData()->BuiltinRange; |
577 | if (!BuiltinRange.getBegin().isValid()) { |
578 | BuiltinRange = Range; |
579 | } else { |
580 | BuiltinRange.setBegin(std::min(Range.getBegin(), BuiltinRange.getBegin())); |
581 | BuiltinRange.setEnd(std::max(Range.getEnd(), BuiltinRange.getEnd())); |
582 | } |
583 | } |
584 | |
585 | SourceLocation getNameLoc() const { return getBuiltinLoc(); } |
586 | |
587 | WrittenBuiltinSpecs& getWrittenBuiltinSpecs() { |
588 | return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); |
589 | } |
590 | const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { |
591 | return *(static_cast<WrittenBuiltinSpecs*>(getExtraLocalData())); |
592 | } |
593 | |
594 | bool () const { |
595 | BuiltinType::Kind bk = getTypePtr()->getKind(); |
596 | return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) || |
597 | (bk >= BuiltinType::Short && bk <= BuiltinType::Ibm128) || |
598 | bk == BuiltinType::UChar || bk == BuiltinType::SChar; |
599 | } |
600 | |
601 | unsigned () const { |
602 | return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; |
603 | } |
604 | |
605 | unsigned () const { |
606 | return needsExtraLocalData() ? alignof(WrittenBuiltinSpecs) : 1; |
607 | } |
608 | |
609 | SourceRange getLocalSourceRange() const { |
610 | return getLocalData()->BuiltinRange; |
611 | } |
612 | |
613 | TypeSpecifierSign getWrittenSignSpec() const { |
614 | if (needsExtraLocalData()) |
615 | return static_cast<TypeSpecifierSign>(getWrittenBuiltinSpecs().Sign); |
616 | else |
617 | return TypeSpecifierSign::Unspecified; |
618 | } |
619 | |
620 | bool hasWrittenSignSpec() const { |
621 | return getWrittenSignSpec() != TypeSpecifierSign::Unspecified; |
622 | } |
623 | |
624 | void setWrittenSignSpec(TypeSpecifierSign written) { |
625 | if (needsExtraLocalData()) |
626 | getWrittenBuiltinSpecs().Sign = static_cast<unsigned>(written); |
627 | } |
628 | |
629 | TypeSpecifierWidth getWrittenWidthSpec() const { |
630 | if (needsExtraLocalData()) |
631 | return static_cast<TypeSpecifierWidth>(getWrittenBuiltinSpecs().Width); |
632 | else |
633 | return TypeSpecifierWidth::Unspecified; |
634 | } |
635 | |
636 | bool hasWrittenWidthSpec() const { |
637 | return getWrittenWidthSpec() != TypeSpecifierWidth::Unspecified; |
638 | } |
639 | |
640 | void setWrittenWidthSpec(TypeSpecifierWidth written) { |
641 | if (needsExtraLocalData()) |
642 | getWrittenBuiltinSpecs().Width = static_cast<unsigned>(written); |
643 | } |
644 | |
645 | TypeSpecifierType getWrittenTypeSpec() const; |
646 | |
647 | bool hasWrittenTypeSpec() const { |
648 | return getWrittenTypeSpec() != TST_unspecified; |
649 | } |
650 | |
651 | void setWrittenTypeSpec(TypeSpecifierType written) { |
652 | if (needsExtraLocalData()) |
653 | getWrittenBuiltinSpecs().Type = written; |
654 | } |
655 | |
656 | bool hasModeAttr() const { |
657 | if (needsExtraLocalData()) |
658 | return getWrittenBuiltinSpecs().ModeAttr; |
659 | else |
660 | return false; |
661 | } |
662 | |
663 | void setModeAttr(bool written) { |
664 | if (needsExtraLocalData()) |
665 | getWrittenBuiltinSpecs().ModeAttr = written; |
666 | } |
667 | |
668 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
669 | setBuiltinLoc(Loc); |
670 | if (needsExtraLocalData()) { |
671 | WrittenBuiltinSpecs &wbs = getWrittenBuiltinSpecs(); |
672 | wbs.Sign = static_cast<unsigned>(TypeSpecifierSign::Unspecified); |
673 | wbs.Width = static_cast<unsigned>(TypeSpecifierWidth::Unspecified); |
674 | wbs.Type = TST_unspecified; |
675 | wbs.ModeAttr = false; |
676 | } |
677 | } |
678 | }; |
679 | |
680 | /// Wrapper for source info for types used via transparent aliases. |
681 | class UsingTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
682 | UsingTypeLoc, UsingType> { |
683 | public: |
684 | QualType getUnderlyingType() const { |
685 | return getTypePtr()->getUnderlyingType(); |
686 | } |
687 | UsingShadowDecl *getFoundDecl() const { return getTypePtr()->getFoundDecl(); } |
688 | }; |
689 | |
690 | /// Wrapper for source info for typedefs. |
691 | class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
692 | TypedefTypeLoc, |
693 | TypedefType> { |
694 | public: |
695 | TypedefNameDecl *getTypedefNameDecl() const { |
696 | return getTypePtr()->getDecl(); |
697 | } |
698 | }; |
699 | |
700 | /// Wrapper for source info for injected class names of class |
701 | /// templates. |
702 | class InjectedClassNameTypeLoc : |
703 | public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
704 | InjectedClassNameTypeLoc, |
705 | InjectedClassNameType> { |
706 | public: |
707 | CXXRecordDecl *getDecl() const { |
708 | return getTypePtr()->getDecl(); |
709 | } |
710 | }; |
711 | |
712 | /// Wrapper for source info for unresolved typename using decls. |
713 | class UnresolvedUsingTypeLoc : |
714 | public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
715 | UnresolvedUsingTypeLoc, |
716 | UnresolvedUsingType> { |
717 | public: |
718 | UnresolvedUsingTypenameDecl *getDecl() const { |
719 | return getTypePtr()->getDecl(); |
720 | } |
721 | }; |
722 | |
723 | /// Wrapper for source info for tag types. Note that this only |
724 | /// records source info for the name itself; a type written 'struct foo' |
725 | /// should be represented as an ElaboratedTypeLoc. We currently |
726 | /// only do that when C++ is enabled because of the expense of |
727 | /// creating an ElaboratedType node for so many type references in C. |
728 | class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
729 | TagTypeLoc, |
730 | TagType> { |
731 | public: |
732 | TagDecl *getDecl() const { return getTypePtr()->getDecl(); } |
733 | |
734 | /// True if the tag was defined in this type specifier. |
735 | bool isDefinition() const; |
736 | }; |
737 | |
738 | /// Wrapper for source info for record types. |
739 | class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, |
740 | RecordTypeLoc, |
741 | RecordType> { |
742 | public: |
743 | RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } |
744 | }; |
745 | |
746 | /// Wrapper for source info for enum types. |
747 | class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, |
748 | EnumTypeLoc, |
749 | EnumType> { |
750 | public: |
751 | EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } |
752 | }; |
753 | |
754 | /// Wrapper for template type parameters. |
755 | class TemplateTypeParmTypeLoc : |
756 | public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
757 | TemplateTypeParmTypeLoc, |
758 | TemplateTypeParmType> { |
759 | public: |
760 | TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } |
761 | }; |
762 | |
763 | struct ObjCTypeParamTypeLocInfo { |
764 | SourceLocation NameLoc; |
765 | }; |
766 | |
767 | /// ProtocolLAngleLoc, ProtocolRAngleLoc, and the source locations for |
768 | /// protocol qualifiers are stored after Info. |
769 | class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
770 | ObjCTypeParamTypeLoc, |
771 | ObjCTypeParamType, |
772 | ObjCTypeParamTypeLocInfo> { |
773 | // SourceLocations are stored after Info, one for each protocol qualifier. |
774 | SourceLocation *getProtocolLocArray() const { |
775 | return (SourceLocation*)this->getExtraLocalData() + 2; |
776 | } |
777 | |
778 | public: |
779 | ObjCTypeParamDecl *getDecl() const { return getTypePtr()->getDecl(); } |
780 | |
781 | SourceLocation getNameLoc() const { |
782 | return this->getLocalData()->NameLoc; |
783 | } |
784 | |
785 | void setNameLoc(SourceLocation Loc) { |
786 | this->getLocalData()->NameLoc = Loc; |
787 | } |
788 | |
789 | SourceLocation getProtocolLAngleLoc() const { |
790 | return getNumProtocols() ? |
791 | *((SourceLocation*)this->getExtraLocalData()) : |
792 | SourceLocation(); |
793 | } |
794 | |
795 | void setProtocolLAngleLoc(SourceLocation Loc) { |
796 | *((SourceLocation*)this->getExtraLocalData()) = Loc; |
797 | } |
798 | |
799 | SourceLocation getProtocolRAngleLoc() const { |
800 | return getNumProtocols() ? |
801 | *((SourceLocation*)this->getExtraLocalData() + 1) : |
802 | SourceLocation(); |
803 | } |
804 | |
805 | void setProtocolRAngleLoc(SourceLocation Loc) { |
806 | *((SourceLocation*)this->getExtraLocalData() + 1) = Loc; |
807 | } |
808 | |
809 | unsigned getNumProtocols() const { |
810 | return this->getTypePtr()->getNumProtocols(); |
811 | } |
812 | |
813 | SourceLocation getProtocolLoc(unsigned i) const { |
814 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
815 | return getProtocolLocArray()[i]; |
816 | } |
817 | |
818 | void setProtocolLoc(unsigned i, SourceLocation Loc) { |
819 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
820 | getProtocolLocArray()[i] = Loc; |
821 | } |
822 | |
823 | ObjCProtocolDecl *getProtocol(unsigned i) const { |
824 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
825 | return *(this->getTypePtr()->qual_begin() + i); |
826 | } |
827 | |
828 | ArrayRef<SourceLocation> getProtocolLocs() const { |
829 | return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols()); |
830 | } |
831 | |
832 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
833 | |
834 | unsigned () const { |
835 | if (!this->getNumProtocols()) return 0; |
836 | // When there are protocol qualifers, we have LAngleLoc and RAngleLoc |
837 | // as well. |
838 | return (this->getNumProtocols() + 2) * sizeof(SourceLocation) ; |
839 | } |
840 | |
841 | unsigned () const { |
842 | return alignof(SourceLocation); |
843 | } |
844 | |
845 | SourceRange getLocalSourceRange() const { |
846 | SourceLocation start = getNameLoc(); |
847 | SourceLocation end = getProtocolRAngleLoc(); |
848 | if (end.isInvalid()) return SourceRange(start, start); |
849 | return SourceRange(start, end); |
850 | } |
851 | }; |
852 | |
853 | /// Wrapper for substituted template type parameters. |
854 | class SubstTemplateTypeParmTypeLoc : |
855 | public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
856 | SubstTemplateTypeParmTypeLoc, |
857 | SubstTemplateTypeParmType> { |
858 | }; |
859 | |
860 | /// Wrapper for substituted template type parameters. |
861 | class SubstTemplateTypeParmPackTypeLoc : |
862 | public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
863 | SubstTemplateTypeParmPackTypeLoc, |
864 | SubstTemplateTypeParmPackType> { |
865 | }; |
866 | |
867 | struct AttributedLocInfo { |
868 | const Attr *TypeAttr; |
869 | }; |
870 | |
871 | /// Type source information for an attributed type. |
872 | class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
873 | AttributedTypeLoc, |
874 | AttributedType, |
875 | AttributedLocInfo> { |
876 | public: |
877 | attr::Kind getAttrKind() const { |
878 | return getTypePtr()->getAttrKind(); |
879 | } |
880 | |
881 | bool isQualifier() const { |
882 | return getTypePtr()->isQualifier(); |
883 | } |
884 | |
885 | /// The modified type, which is generally canonically different from |
886 | /// the attribute type. |
887 | /// int main(int, char**) __attribute__((noreturn)) |
888 | /// ~~~ ~~~~~~~~~~~~~ |
889 | TypeLoc getModifiedLoc() const { |
890 | return getInnerTypeLoc(); |
891 | } |
892 | |
893 | TypeLoc getEquivalentTypeLoc() const { |
894 | return TypeLoc(getTypePtr()->getEquivalentType(), getNonLocalData()); |
895 | } |
896 | |
897 | /// The type attribute. |
898 | const Attr *getAttr() const { |
899 | return getLocalData()->TypeAttr; |
900 | } |
901 | void setAttr(const Attr *A) { |
902 | getLocalData()->TypeAttr = A; |
903 | } |
904 | |
905 | template<typename T> const T *getAttrAs() { |
906 | return dyn_cast_or_null<T>(getAttr()); |
907 | } |
908 | |
909 | SourceRange getLocalSourceRange() const; |
910 | |
911 | void initializeLocal(ASTContext &Context, SourceLocation loc) { |
912 | setAttr(nullptr); |
913 | } |
914 | |
915 | QualType getInnerType() const { |
916 | return getTypePtr()->getModifiedType(); |
917 | } |
918 | }; |
919 | |
920 | struct BTFTagAttributedLocInfo {}; // Nothing. |
921 | |
922 | /// Type source information for an btf_tag attributed type. |
923 | class BTFTagAttributedTypeLoc |
924 | : public ConcreteTypeLoc<UnqualTypeLoc, BTFTagAttributedTypeLoc, |
925 | BTFTagAttributedType, BTFTagAttributedLocInfo> { |
926 | public: |
927 | TypeLoc getWrappedLoc() const { return getInnerTypeLoc(); } |
928 | |
929 | /// The btf_type_tag attribute. |
930 | const BTFTypeTagAttr *getAttr() const { return getTypePtr()->getAttr(); } |
931 | |
932 | template <typename T> T *getAttrAs() { |
933 | return dyn_cast_or_null<T>(getAttr()); |
934 | } |
935 | |
936 | SourceRange getLocalSourceRange() const; |
937 | |
938 | void initializeLocal(ASTContext &Context, SourceLocation loc) {} |
939 | |
940 | QualType getInnerType() const { return getTypePtr()->getWrappedType(); } |
941 | }; |
942 | |
943 | struct ObjCObjectTypeLocInfo { |
944 | SourceLocation TypeArgsLAngleLoc; |
945 | SourceLocation TypeArgsRAngleLoc; |
946 | SourceLocation ProtocolLAngleLoc; |
947 | SourceLocation ProtocolRAngleLoc; |
948 | bool HasBaseTypeAsWritten; |
949 | }; |
950 | |
951 | // A helper class for defining ObjC TypeLocs that can qualified with |
952 | // protocols. |
953 | // |
954 | // TypeClass basically has to be either ObjCInterfaceType or |
955 | // ObjCObjectPointerType. |
956 | class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
957 | ObjCObjectTypeLoc, |
958 | ObjCObjectType, |
959 | ObjCObjectTypeLocInfo> { |
960 | // TypeSourceInfo*'s are stored after Info, one for each type argument. |
961 | TypeSourceInfo **getTypeArgLocArray() const { |
962 | return (TypeSourceInfo**)this->getExtraLocalData(); |
963 | } |
964 | |
965 | // SourceLocations are stored after the type argument information, one for |
966 | // each Protocol. |
967 | SourceLocation *getProtocolLocArray() const { |
968 | return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs()); |
969 | } |
970 | |
971 | public: |
972 | SourceLocation getTypeArgsLAngleLoc() const { |
973 | return this->getLocalData()->TypeArgsLAngleLoc; |
974 | } |
975 | |
976 | void setTypeArgsLAngleLoc(SourceLocation Loc) { |
977 | this->getLocalData()->TypeArgsLAngleLoc = Loc; |
978 | } |
979 | |
980 | SourceLocation getTypeArgsRAngleLoc() const { |
981 | return this->getLocalData()->TypeArgsRAngleLoc; |
982 | } |
983 | |
984 | void setTypeArgsRAngleLoc(SourceLocation Loc) { |
985 | this->getLocalData()->TypeArgsRAngleLoc = Loc; |
986 | } |
987 | |
988 | unsigned getNumTypeArgs() const { |
989 | return this->getTypePtr()->getTypeArgsAsWritten().size(); |
990 | } |
991 | |
992 | TypeSourceInfo *getTypeArgTInfo(unsigned i) const { |
993 | assert(i < getNumTypeArgs() && "Index is out of bounds!" ); |
994 | return getTypeArgLocArray()[i]; |
995 | } |
996 | |
997 | void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) { |
998 | assert(i < getNumTypeArgs() && "Index is out of bounds!" ); |
999 | getTypeArgLocArray()[i] = TInfo; |
1000 | } |
1001 | |
1002 | SourceLocation getProtocolLAngleLoc() const { |
1003 | return this->getLocalData()->ProtocolLAngleLoc; |
1004 | } |
1005 | |
1006 | void setProtocolLAngleLoc(SourceLocation Loc) { |
1007 | this->getLocalData()->ProtocolLAngleLoc = Loc; |
1008 | } |
1009 | |
1010 | SourceLocation getProtocolRAngleLoc() const { |
1011 | return this->getLocalData()->ProtocolRAngleLoc; |
1012 | } |
1013 | |
1014 | void setProtocolRAngleLoc(SourceLocation Loc) { |
1015 | this->getLocalData()->ProtocolRAngleLoc = Loc; |
1016 | } |
1017 | |
1018 | unsigned getNumProtocols() const { |
1019 | return this->getTypePtr()->getNumProtocols(); |
1020 | } |
1021 | |
1022 | SourceLocation getProtocolLoc(unsigned i) const { |
1023 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
1024 | return getProtocolLocArray()[i]; |
1025 | } |
1026 | |
1027 | void setProtocolLoc(unsigned i, SourceLocation Loc) { |
1028 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
1029 | getProtocolLocArray()[i] = Loc; |
1030 | } |
1031 | |
1032 | ObjCProtocolDecl *getProtocol(unsigned i) const { |
1033 | assert(i < getNumProtocols() && "Index is out of bounds!" ); |
1034 | return *(this->getTypePtr()->qual_begin() + i); |
1035 | } |
1036 | |
1037 | |
1038 | ArrayRef<SourceLocation> getProtocolLocs() const { |
1039 | return llvm::ArrayRef(getProtocolLocArray(), getNumProtocols()); |
1040 | } |
1041 | |
1042 | bool hasBaseTypeAsWritten() const { |
1043 | return getLocalData()->HasBaseTypeAsWritten; |
1044 | } |
1045 | |
1046 | void setHasBaseTypeAsWritten(bool HasBaseType) { |
1047 | getLocalData()->HasBaseTypeAsWritten = HasBaseType; |
1048 | } |
1049 | |
1050 | TypeLoc getBaseLoc() const { |
1051 | return getInnerTypeLoc(); |
1052 | } |
1053 | |
1054 | SourceRange getLocalSourceRange() const { |
1055 | SourceLocation start = getTypeArgsLAngleLoc(); |
1056 | if (start.isInvalid()) |
1057 | start = getProtocolLAngleLoc(); |
1058 | SourceLocation end = getProtocolRAngleLoc(); |
1059 | if (end.isInvalid()) |
1060 | end = getTypeArgsRAngleLoc(); |
1061 | return SourceRange(start, end); |
1062 | } |
1063 | |
1064 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
1065 | |
1066 | unsigned () const { |
1067 | return this->getNumTypeArgs() * sizeof(TypeSourceInfo *) |
1068 | + this->getNumProtocols() * sizeof(SourceLocation); |
1069 | } |
1070 | |
1071 | unsigned () const { |
1072 | static_assert(alignof(ObjCObjectTypeLoc) >= alignof(TypeSourceInfo *), |
1073 | "not enough alignment for tail-allocated data" ); |
1074 | return alignof(TypeSourceInfo *); |
1075 | } |
1076 | |
1077 | QualType getInnerType() const { |
1078 | return getTypePtr()->getBaseType(); |
1079 | } |
1080 | }; |
1081 | |
1082 | struct ObjCInterfaceLocInfo { |
1083 | SourceLocation NameLoc; |
1084 | SourceLocation NameEndLoc; |
1085 | }; |
1086 | |
1087 | /// Wrapper for source info for ObjC interfaces. |
1088 | class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc, |
1089 | ObjCInterfaceTypeLoc, |
1090 | ObjCInterfaceType, |
1091 | ObjCInterfaceLocInfo> { |
1092 | public: |
1093 | ObjCInterfaceDecl *getIFaceDecl() const { |
1094 | return getTypePtr()->getDecl(); |
1095 | } |
1096 | |
1097 | SourceLocation getNameLoc() const { |
1098 | return getLocalData()->NameLoc; |
1099 | } |
1100 | |
1101 | void setNameLoc(SourceLocation Loc) { |
1102 | getLocalData()->NameLoc = Loc; |
1103 | } |
1104 | |
1105 | SourceRange getLocalSourceRange() const { |
1106 | return SourceRange(getNameLoc(), getNameEndLoc()); |
1107 | } |
1108 | |
1109 | SourceLocation getNameEndLoc() const { |
1110 | return getLocalData()->NameEndLoc; |
1111 | } |
1112 | |
1113 | void setNameEndLoc(SourceLocation Loc) { |
1114 | getLocalData()->NameEndLoc = Loc; |
1115 | } |
1116 | |
1117 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1118 | setNameLoc(Loc); |
1119 | setNameEndLoc(Loc); |
1120 | } |
1121 | }; |
1122 | |
1123 | struct MacroQualifiedLocInfo { |
1124 | SourceLocation ExpansionLoc; |
1125 | }; |
1126 | |
1127 | class MacroQualifiedTypeLoc |
1128 | : public ConcreteTypeLoc<UnqualTypeLoc, MacroQualifiedTypeLoc, |
1129 | MacroQualifiedType, MacroQualifiedLocInfo> { |
1130 | public: |
1131 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1132 | setExpansionLoc(Loc); |
1133 | } |
1134 | |
1135 | TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } |
1136 | |
1137 | const IdentifierInfo *getMacroIdentifier() const { |
1138 | return getTypePtr()->getMacroIdentifier(); |
1139 | } |
1140 | |
1141 | SourceLocation getExpansionLoc() const { |
1142 | return this->getLocalData()->ExpansionLoc; |
1143 | } |
1144 | |
1145 | void setExpansionLoc(SourceLocation Loc) { |
1146 | this->getLocalData()->ExpansionLoc = Loc; |
1147 | } |
1148 | |
1149 | QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); } |
1150 | |
1151 | SourceRange getLocalSourceRange() const { |
1152 | return getInnerLoc().getLocalSourceRange(); |
1153 | } |
1154 | }; |
1155 | |
1156 | struct ParenLocInfo { |
1157 | SourceLocation LParenLoc; |
1158 | SourceLocation RParenLoc; |
1159 | }; |
1160 | |
1161 | class ParenTypeLoc |
1162 | : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType, |
1163 | ParenLocInfo> { |
1164 | public: |
1165 | SourceLocation getLParenLoc() const { |
1166 | return this->getLocalData()->LParenLoc; |
1167 | } |
1168 | |
1169 | SourceLocation getRParenLoc() const { |
1170 | return this->getLocalData()->RParenLoc; |
1171 | } |
1172 | |
1173 | void setLParenLoc(SourceLocation Loc) { |
1174 | this->getLocalData()->LParenLoc = Loc; |
1175 | } |
1176 | |
1177 | void setRParenLoc(SourceLocation Loc) { |
1178 | this->getLocalData()->RParenLoc = Loc; |
1179 | } |
1180 | |
1181 | SourceRange getLocalSourceRange() const { |
1182 | return SourceRange(getLParenLoc(), getRParenLoc()); |
1183 | } |
1184 | |
1185 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1186 | setLParenLoc(Loc); |
1187 | setRParenLoc(Loc); |
1188 | } |
1189 | |
1190 | TypeLoc getInnerLoc() const { |
1191 | return getInnerTypeLoc(); |
1192 | } |
1193 | |
1194 | QualType getInnerType() const { |
1195 | return this->getTypePtr()->getInnerType(); |
1196 | } |
1197 | }; |
1198 | |
1199 | inline TypeLoc TypeLoc::IgnoreParens() const { |
1200 | if (ParenTypeLoc::isKind(*this)) |
1201 | return IgnoreParensImpl(TL: *this); |
1202 | return *this; |
1203 | } |
1204 | |
1205 | struct AdjustedLocInfo {}; // Nothing. |
1206 | |
1207 | class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, |
1208 | AdjustedType, AdjustedLocInfo> { |
1209 | public: |
1210 | TypeLoc getOriginalLoc() const { |
1211 | return getInnerTypeLoc(); |
1212 | } |
1213 | |
1214 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1215 | // do nothing |
1216 | } |
1217 | |
1218 | QualType getInnerType() const { |
1219 | // The inner type is the undecayed type, since that's what we have source |
1220 | // location information for. |
1221 | return getTypePtr()->getOriginalType(); |
1222 | } |
1223 | |
1224 | SourceRange getLocalSourceRange() const { return {}; } |
1225 | |
1226 | unsigned getLocalDataSize() const { |
1227 | // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique |
1228 | // anyway. TypeLocBuilder can't handle data sizes of 1. |
1229 | return 0; // No data. |
1230 | } |
1231 | }; |
1232 | |
1233 | /// Wrapper for source info for pointers decayed from arrays and |
1234 | /// functions. |
1235 | class DecayedTypeLoc : public InheritingConcreteTypeLoc< |
1236 | AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { |
1237 | }; |
1238 | |
1239 | struct PointerLikeLocInfo { |
1240 | SourceLocation StarLoc; |
1241 | }; |
1242 | |
1243 | /// A base class for |
1244 | template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> |
1245 | class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, |
1246 | TypeClass, LocalData> { |
1247 | public: |
1248 | SourceLocation getSigilLoc() const { |
1249 | return this->getLocalData()->StarLoc; |
1250 | } |
1251 | |
1252 | void setSigilLoc(SourceLocation Loc) { |
1253 | this->getLocalData()->StarLoc = Loc; |
1254 | } |
1255 | |
1256 | TypeLoc getPointeeLoc() const { |
1257 | return this->getInnerTypeLoc(); |
1258 | } |
1259 | |
1260 | SourceRange getLocalSourceRange() const { |
1261 | return SourceRange(getSigilLoc(), getSigilLoc()); |
1262 | } |
1263 | |
1264 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1265 | setSigilLoc(Loc); |
1266 | } |
1267 | |
1268 | QualType getInnerType() const { |
1269 | return this->getTypePtr()->getPointeeType(); |
1270 | } |
1271 | }; |
1272 | |
1273 | /// Wrapper for source info for pointers. |
1274 | class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, |
1275 | PointerType> { |
1276 | public: |
1277 | SourceLocation getStarLoc() const { |
1278 | return getSigilLoc(); |
1279 | } |
1280 | |
1281 | void setStarLoc(SourceLocation Loc) { |
1282 | setSigilLoc(Loc); |
1283 | } |
1284 | }; |
1285 | |
1286 | /// Wrapper for source info for block pointers. |
1287 | class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, |
1288 | BlockPointerType> { |
1289 | public: |
1290 | SourceLocation getCaretLoc() const { |
1291 | return getSigilLoc(); |
1292 | } |
1293 | |
1294 | void setCaretLoc(SourceLocation Loc) { |
1295 | setSigilLoc(Loc); |
1296 | } |
1297 | }; |
1298 | |
1299 | struct MemberPointerLocInfo : public PointerLikeLocInfo { |
1300 | TypeSourceInfo *ClassTInfo; |
1301 | }; |
1302 | |
1303 | /// Wrapper for source info for member pointers. |
1304 | class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, |
1305 | MemberPointerType, |
1306 | MemberPointerLocInfo> { |
1307 | public: |
1308 | SourceLocation getStarLoc() const { |
1309 | return getSigilLoc(); |
1310 | } |
1311 | |
1312 | void setStarLoc(SourceLocation Loc) { |
1313 | setSigilLoc(Loc); |
1314 | } |
1315 | |
1316 | const Type *getClass() const { |
1317 | return getTypePtr()->getClass(); |
1318 | } |
1319 | |
1320 | TypeSourceInfo *getClassTInfo() const { |
1321 | return getLocalData()->ClassTInfo; |
1322 | } |
1323 | |
1324 | void setClassTInfo(TypeSourceInfo* TI) { |
1325 | getLocalData()->ClassTInfo = TI; |
1326 | } |
1327 | |
1328 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1329 | setSigilLoc(Loc); |
1330 | setClassTInfo(nullptr); |
1331 | } |
1332 | |
1333 | SourceRange getLocalSourceRange() const { |
1334 | if (TypeSourceInfo *TI = getClassTInfo()) |
1335 | return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); |
1336 | else |
1337 | return SourceRange(getStarLoc()); |
1338 | } |
1339 | }; |
1340 | |
1341 | /// Wraps an ObjCPointerType with source location information. |
1342 | class ObjCObjectPointerTypeLoc : |
1343 | public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, |
1344 | ObjCObjectPointerType> { |
1345 | public: |
1346 | SourceLocation getStarLoc() const { |
1347 | return getSigilLoc(); |
1348 | } |
1349 | |
1350 | void setStarLoc(SourceLocation Loc) { |
1351 | setSigilLoc(Loc); |
1352 | } |
1353 | }; |
1354 | |
1355 | class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, |
1356 | ReferenceType> { |
1357 | public: |
1358 | QualType getInnerType() const { |
1359 | return getTypePtr()->getPointeeTypeAsWritten(); |
1360 | } |
1361 | }; |
1362 | |
1363 | class LValueReferenceTypeLoc : |
1364 | public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
1365 | LValueReferenceTypeLoc, |
1366 | LValueReferenceType> { |
1367 | public: |
1368 | SourceLocation getAmpLoc() const { |
1369 | return getSigilLoc(); |
1370 | } |
1371 | |
1372 | void setAmpLoc(SourceLocation Loc) { |
1373 | setSigilLoc(Loc); |
1374 | } |
1375 | }; |
1376 | |
1377 | class RValueReferenceTypeLoc : |
1378 | public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
1379 | RValueReferenceTypeLoc, |
1380 | RValueReferenceType> { |
1381 | public: |
1382 | SourceLocation getAmpAmpLoc() const { |
1383 | return getSigilLoc(); |
1384 | } |
1385 | |
1386 | void setAmpAmpLoc(SourceLocation Loc) { |
1387 | setSigilLoc(Loc); |
1388 | } |
1389 | }; |
1390 | |
1391 | struct FunctionLocInfo { |
1392 | SourceLocation LocalRangeBegin; |
1393 | SourceLocation LParenLoc; |
1394 | SourceLocation RParenLoc; |
1395 | SourceLocation LocalRangeEnd; |
1396 | }; |
1397 | |
1398 | /// Wrapper for source info for functions. |
1399 | class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
1400 | FunctionTypeLoc, |
1401 | FunctionType, |
1402 | FunctionLocInfo> { |
1403 | bool hasExceptionSpec() const { |
1404 | if (auto *FPT = dyn_cast<FunctionProtoType>(getTypePtr())) { |
1405 | return FPT->hasExceptionSpec(); |
1406 | } |
1407 | return false; |
1408 | } |
1409 | |
1410 | SourceRange *getExceptionSpecRangePtr() const { |
1411 | assert(hasExceptionSpec() && "No exception spec range" ); |
1412 | // After the Info comes the ParmVarDecl array, and after that comes the |
1413 | // exception specification information. |
1414 | return (SourceRange *)(getParmArray() + getNumParams()); |
1415 | } |
1416 | |
1417 | public: |
1418 | SourceLocation getLocalRangeBegin() const { |
1419 | return getLocalData()->LocalRangeBegin; |
1420 | } |
1421 | |
1422 | void setLocalRangeBegin(SourceLocation L) { |
1423 | getLocalData()->LocalRangeBegin = L; |
1424 | } |
1425 | |
1426 | SourceLocation getLocalRangeEnd() const { |
1427 | return getLocalData()->LocalRangeEnd; |
1428 | } |
1429 | |
1430 | void setLocalRangeEnd(SourceLocation L) { |
1431 | getLocalData()->LocalRangeEnd = L; |
1432 | } |
1433 | |
1434 | SourceLocation getLParenLoc() const { |
1435 | return this->getLocalData()->LParenLoc; |
1436 | } |
1437 | |
1438 | void setLParenLoc(SourceLocation Loc) { |
1439 | this->getLocalData()->LParenLoc = Loc; |
1440 | } |
1441 | |
1442 | SourceLocation getRParenLoc() const { |
1443 | return this->getLocalData()->RParenLoc; |
1444 | } |
1445 | |
1446 | void setRParenLoc(SourceLocation Loc) { |
1447 | this->getLocalData()->RParenLoc = Loc; |
1448 | } |
1449 | |
1450 | SourceRange getParensRange() const { |
1451 | return SourceRange(getLParenLoc(), getRParenLoc()); |
1452 | } |
1453 | |
1454 | SourceRange getExceptionSpecRange() const { |
1455 | if (hasExceptionSpec()) |
1456 | return *getExceptionSpecRangePtr(); |
1457 | return {}; |
1458 | } |
1459 | |
1460 | void setExceptionSpecRange(SourceRange R) { |
1461 | if (hasExceptionSpec()) |
1462 | *getExceptionSpecRangePtr() = R; |
1463 | } |
1464 | |
1465 | ArrayRef<ParmVarDecl *> getParams() const { |
1466 | return llvm::ArrayRef(getParmArray(), getNumParams()); |
1467 | } |
1468 | |
1469 | // ParmVarDecls* are stored after Info, one for each parameter. |
1470 | ParmVarDecl **getParmArray() const { |
1471 | return (ParmVarDecl**) getExtraLocalData(); |
1472 | } |
1473 | |
1474 | unsigned getNumParams() const { |
1475 | if (isa<FunctionNoProtoType>(getTypePtr())) |
1476 | return 0; |
1477 | return cast<FunctionProtoType>(getTypePtr())->getNumParams(); |
1478 | } |
1479 | |
1480 | ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } |
1481 | void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } |
1482 | |
1483 | TypeLoc getReturnLoc() const { |
1484 | return getInnerTypeLoc(); |
1485 | } |
1486 | |
1487 | SourceRange getLocalSourceRange() const { |
1488 | return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); |
1489 | } |
1490 | |
1491 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1492 | setLocalRangeBegin(Loc); |
1493 | setLParenLoc(Loc); |
1494 | setRParenLoc(Loc); |
1495 | setLocalRangeEnd(Loc); |
1496 | for (unsigned i = 0, e = getNumParams(); i != e; ++i) |
1497 | setParam(i, VD: nullptr); |
1498 | if (hasExceptionSpec()) |
1499 | setExceptionSpecRange(Loc); |
1500 | } |
1501 | |
1502 | /// Returns the size of the type source info data block that is |
1503 | /// specific to this type. |
1504 | unsigned () const { |
1505 | unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0; |
1506 | return (getNumParams() * sizeof(ParmVarDecl *)) + ExceptSpecSize; |
1507 | } |
1508 | |
1509 | unsigned () const { return alignof(ParmVarDecl *); } |
1510 | |
1511 | QualType getInnerType() const { return getTypePtr()->getReturnType(); } |
1512 | }; |
1513 | |
1514 | class FunctionProtoTypeLoc : |
1515 | public InheritingConcreteTypeLoc<FunctionTypeLoc, |
1516 | FunctionProtoTypeLoc, |
1517 | FunctionProtoType> { |
1518 | }; |
1519 | |
1520 | class FunctionNoProtoTypeLoc : |
1521 | public InheritingConcreteTypeLoc<FunctionTypeLoc, |
1522 | FunctionNoProtoTypeLoc, |
1523 | FunctionNoProtoType> { |
1524 | }; |
1525 | |
1526 | struct ArrayLocInfo { |
1527 | SourceLocation LBracketLoc, RBracketLoc; |
1528 | Expr *Size; |
1529 | }; |
1530 | |
1531 | /// Wrapper for source info for arrays. |
1532 | class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
1533 | ArrayTypeLoc, |
1534 | ArrayType, |
1535 | ArrayLocInfo> { |
1536 | public: |
1537 | SourceLocation getLBracketLoc() const { |
1538 | return getLocalData()->LBracketLoc; |
1539 | } |
1540 | |
1541 | void setLBracketLoc(SourceLocation Loc) { |
1542 | getLocalData()->LBracketLoc = Loc; |
1543 | } |
1544 | |
1545 | SourceLocation getRBracketLoc() const { |
1546 | return getLocalData()->RBracketLoc; |
1547 | } |
1548 | |
1549 | void setRBracketLoc(SourceLocation Loc) { |
1550 | getLocalData()->RBracketLoc = Loc; |
1551 | } |
1552 | |
1553 | SourceRange getBracketsRange() const { |
1554 | return SourceRange(getLBracketLoc(), getRBracketLoc()); |
1555 | } |
1556 | |
1557 | Expr *getSizeExpr() const { |
1558 | return getLocalData()->Size; |
1559 | } |
1560 | |
1561 | void setSizeExpr(Expr *Size) { |
1562 | getLocalData()->Size = Size; |
1563 | } |
1564 | |
1565 | TypeLoc getElementLoc() const { |
1566 | return getInnerTypeLoc(); |
1567 | } |
1568 | |
1569 | SourceRange getLocalSourceRange() const { |
1570 | return SourceRange(getLBracketLoc(), getRBracketLoc()); |
1571 | } |
1572 | |
1573 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1574 | setLBracketLoc(Loc); |
1575 | setRBracketLoc(Loc); |
1576 | setSizeExpr(nullptr); |
1577 | } |
1578 | |
1579 | QualType getInnerType() const { return getTypePtr()->getElementType(); } |
1580 | }; |
1581 | |
1582 | class ConstantArrayTypeLoc : |
1583 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1584 | ConstantArrayTypeLoc, |
1585 | ConstantArrayType> { |
1586 | }; |
1587 | |
1588 | class IncompleteArrayTypeLoc : |
1589 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1590 | IncompleteArrayTypeLoc, |
1591 | IncompleteArrayType> { |
1592 | }; |
1593 | |
1594 | class DependentSizedArrayTypeLoc : |
1595 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1596 | DependentSizedArrayTypeLoc, |
1597 | DependentSizedArrayType> { |
1598 | public: |
1599 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1600 | ArrayTypeLoc::initializeLocal(Context, Loc); |
1601 | setSizeExpr(getTypePtr()->getSizeExpr()); |
1602 | } |
1603 | }; |
1604 | |
1605 | class VariableArrayTypeLoc : |
1606 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1607 | VariableArrayTypeLoc, |
1608 | VariableArrayType> { |
1609 | }; |
1610 | |
1611 | // Location information for a TemplateName. Rudimentary for now. |
1612 | struct TemplateNameLocInfo { |
1613 | SourceLocation NameLoc; |
1614 | }; |
1615 | |
1616 | struct TemplateSpecializationLocInfo : TemplateNameLocInfo { |
1617 | SourceLocation TemplateKWLoc; |
1618 | SourceLocation LAngleLoc; |
1619 | SourceLocation RAngleLoc; |
1620 | }; |
1621 | |
1622 | class TemplateSpecializationTypeLoc : |
1623 | public ConcreteTypeLoc<UnqualTypeLoc, |
1624 | TemplateSpecializationTypeLoc, |
1625 | TemplateSpecializationType, |
1626 | TemplateSpecializationLocInfo> { |
1627 | public: |
1628 | SourceLocation getTemplateKeywordLoc() const { |
1629 | return getLocalData()->TemplateKWLoc; |
1630 | } |
1631 | |
1632 | void setTemplateKeywordLoc(SourceLocation Loc) { |
1633 | getLocalData()->TemplateKWLoc = Loc; |
1634 | } |
1635 | |
1636 | SourceLocation getLAngleLoc() const { |
1637 | return getLocalData()->LAngleLoc; |
1638 | } |
1639 | |
1640 | void setLAngleLoc(SourceLocation Loc) { |
1641 | getLocalData()->LAngleLoc = Loc; |
1642 | } |
1643 | |
1644 | SourceLocation getRAngleLoc() const { |
1645 | return getLocalData()->RAngleLoc; |
1646 | } |
1647 | |
1648 | void setRAngleLoc(SourceLocation Loc) { |
1649 | getLocalData()->RAngleLoc = Loc; |
1650 | } |
1651 | |
1652 | unsigned getNumArgs() const { |
1653 | return getTypePtr()->template_arguments().size(); |
1654 | } |
1655 | |
1656 | void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { |
1657 | getArgInfos()[i] = AI; |
1658 | } |
1659 | |
1660 | TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { |
1661 | return getArgInfos()[i]; |
1662 | } |
1663 | |
1664 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
1665 | return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], |
1666 | getArgLocInfo(i)); |
1667 | } |
1668 | |
1669 | SourceLocation getTemplateNameLoc() const { |
1670 | return getLocalData()->NameLoc; |
1671 | } |
1672 | |
1673 | void setTemplateNameLoc(SourceLocation Loc) { |
1674 | getLocalData()->NameLoc = Loc; |
1675 | } |
1676 | |
1677 | /// - Copy the location information from the given info. |
1678 | void copy(TemplateSpecializationTypeLoc Loc) { |
1679 | unsigned size = getFullDataSize(); |
1680 | assert(size == Loc.getFullDataSize()); |
1681 | |
1682 | // We're potentially copying Expr references here. We don't |
1683 | // bother retaining them because TypeSourceInfos live forever, so |
1684 | // as long as the Expr was retained when originally written into |
1685 | // the TypeLoc, we're okay. |
1686 | memcpy(Data, Loc.Data, size); |
1687 | } |
1688 | |
1689 | SourceRange getLocalSourceRange() const { |
1690 | if (getTemplateKeywordLoc().isValid()) |
1691 | return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); |
1692 | else |
1693 | return SourceRange(getTemplateNameLoc(), getRAngleLoc()); |
1694 | } |
1695 | |
1696 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1697 | setTemplateKeywordLoc(SourceLocation()); |
1698 | setTemplateNameLoc(Loc); |
1699 | setLAngleLoc(Loc); |
1700 | setRAngleLoc(Loc); |
1701 | initializeArgLocs(Context, Args: getTypePtr()->template_arguments(), |
1702 | ArgInfos: getArgInfos(), Loc); |
1703 | } |
1704 | |
1705 | static void initializeArgLocs(ASTContext &Context, |
1706 | ArrayRef<TemplateArgument> Args, |
1707 | TemplateArgumentLocInfo *ArgInfos, |
1708 | SourceLocation Loc); |
1709 | |
1710 | unsigned () const { |
1711 | return getNumArgs() * sizeof(TemplateArgumentLocInfo); |
1712 | } |
1713 | |
1714 | unsigned () const { |
1715 | return alignof(TemplateArgumentLocInfo); |
1716 | } |
1717 | |
1718 | private: |
1719 | TemplateArgumentLocInfo *getArgInfos() const { |
1720 | return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
1721 | } |
1722 | }; |
1723 | |
1724 | struct DependentAddressSpaceLocInfo { |
1725 | Expr *ExprOperand; |
1726 | SourceRange OperandParens; |
1727 | SourceLocation AttrLoc; |
1728 | }; |
1729 | |
1730 | class DependentAddressSpaceTypeLoc |
1731 | : public ConcreteTypeLoc<UnqualTypeLoc, |
1732 | DependentAddressSpaceTypeLoc, |
1733 | DependentAddressSpaceType, |
1734 | DependentAddressSpaceLocInfo> { |
1735 | public: |
1736 | /// The location of the attribute name, i.e. |
1737 | /// int * __attribute__((address_space(11))) |
1738 | /// ^~~~~~~~~~~~~ |
1739 | SourceLocation getAttrNameLoc() const { |
1740 | return getLocalData()->AttrLoc; |
1741 | } |
1742 | void setAttrNameLoc(SourceLocation loc) { |
1743 | getLocalData()->AttrLoc = loc; |
1744 | } |
1745 | |
1746 | /// The attribute's expression operand, if it has one. |
1747 | /// int * __attribute__((address_space(11))) |
1748 | /// ^~ |
1749 | Expr *getAttrExprOperand() const { |
1750 | return getLocalData()->ExprOperand; |
1751 | } |
1752 | void setAttrExprOperand(Expr *e) { |
1753 | getLocalData()->ExprOperand = e; |
1754 | } |
1755 | |
1756 | /// The location of the parentheses around the operand, if there is |
1757 | /// an operand. |
1758 | /// int * __attribute__((address_space(11))) |
1759 | /// ^ ^ |
1760 | SourceRange getAttrOperandParensRange() const { |
1761 | return getLocalData()->OperandParens; |
1762 | } |
1763 | void setAttrOperandParensRange(SourceRange range) { |
1764 | getLocalData()->OperandParens = range; |
1765 | } |
1766 | |
1767 | SourceRange getLocalSourceRange() const { |
1768 | SourceRange range(getAttrNameLoc()); |
1769 | range.setEnd(getAttrOperandParensRange().getEnd()); |
1770 | return range; |
1771 | } |
1772 | |
1773 | /// Returns the type before the address space attribute application |
1774 | /// area. |
1775 | /// int * __attribute__((address_space(11))) * |
1776 | /// ^ ^ |
1777 | QualType getInnerType() const { |
1778 | return this->getTypePtr()->getPointeeType(); |
1779 | } |
1780 | |
1781 | TypeLoc getPointeeTypeLoc() const { |
1782 | return this->getInnerTypeLoc(); |
1783 | } |
1784 | |
1785 | void initializeLocal(ASTContext &Context, SourceLocation loc) { |
1786 | setAttrNameLoc(loc); |
1787 | setAttrOperandParensRange(loc); |
1788 | setAttrOperandParensRange(SourceRange(loc)); |
1789 | setAttrExprOperand(getTypePtr()->getAddrSpaceExpr()); |
1790 | } |
1791 | }; |
1792 | |
1793 | //===----------------------------------------------------------------------===// |
1794 | // |
1795 | // All of these need proper implementations. |
1796 | // |
1797 | //===----------------------------------------------------------------------===// |
1798 | |
1799 | // FIXME: size expression and attribute locations (or keyword if we |
1800 | // ever fully support altivec syntax). |
1801 | struct VectorTypeLocInfo { |
1802 | SourceLocation NameLoc; |
1803 | }; |
1804 | |
1805 | class VectorTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, VectorTypeLoc, |
1806 | VectorType, VectorTypeLocInfo> { |
1807 | public: |
1808 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1809 | |
1810 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1811 | |
1812 | SourceRange getLocalSourceRange() const { |
1813 | return SourceRange(getNameLoc(), getNameLoc()); |
1814 | } |
1815 | |
1816 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1817 | setNameLoc(Loc); |
1818 | } |
1819 | |
1820 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1821 | |
1822 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1823 | }; |
1824 | |
1825 | // FIXME: size expression and attribute locations (or keyword if we |
1826 | // ever fully support altivec syntax). |
1827 | class DependentVectorTypeLoc |
1828 | : public ConcreteTypeLoc<UnqualTypeLoc, DependentVectorTypeLoc, |
1829 | DependentVectorType, VectorTypeLocInfo> { |
1830 | public: |
1831 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1832 | |
1833 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1834 | |
1835 | SourceRange getLocalSourceRange() const { |
1836 | return SourceRange(getNameLoc(), getNameLoc()); |
1837 | } |
1838 | |
1839 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1840 | setNameLoc(Loc); |
1841 | } |
1842 | |
1843 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1844 | |
1845 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1846 | }; |
1847 | |
1848 | // FIXME: size expression and attribute locations. |
1849 | class ExtVectorTypeLoc |
1850 | : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc, |
1851 | ExtVectorType> {}; |
1852 | |
1853 | // FIXME: attribute locations. |
1854 | // For some reason, this isn't a subtype of VectorType. |
1855 | class DependentSizedExtVectorTypeLoc |
1856 | : public ConcreteTypeLoc<UnqualTypeLoc, DependentSizedExtVectorTypeLoc, |
1857 | DependentSizedExtVectorType, VectorTypeLocInfo> { |
1858 | public: |
1859 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1860 | |
1861 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1862 | |
1863 | SourceRange getLocalSourceRange() const { |
1864 | return SourceRange(getNameLoc(), getNameLoc()); |
1865 | } |
1866 | |
1867 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1868 | setNameLoc(Loc); |
1869 | } |
1870 | |
1871 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1872 | |
1873 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1874 | }; |
1875 | |
1876 | struct MatrixTypeLocInfo { |
1877 | SourceLocation AttrLoc; |
1878 | SourceRange OperandParens; |
1879 | Expr *RowOperand; |
1880 | Expr *ColumnOperand; |
1881 | }; |
1882 | |
1883 | class MatrixTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, MatrixTypeLoc, |
1884 | MatrixType, MatrixTypeLocInfo> { |
1885 | public: |
1886 | /// The location of the attribute name, i.e. |
1887 | /// float __attribute__((matrix_type(4, 2))) |
1888 | /// ^~~~~~~~~~~~~~~~~ |
1889 | SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; } |
1890 | void setAttrNameLoc(SourceLocation loc) { getLocalData()->AttrLoc = loc; } |
1891 | |
1892 | /// The attribute's row operand, if it has one. |
1893 | /// float __attribute__((matrix_type(4, 2))) |
1894 | /// ^ |
1895 | Expr *getAttrRowOperand() const { return getLocalData()->RowOperand; } |
1896 | void setAttrRowOperand(Expr *e) { getLocalData()->RowOperand = e; } |
1897 | |
1898 | /// The attribute's column operand, if it has one. |
1899 | /// float __attribute__((matrix_type(4, 2))) |
1900 | /// ^ |
1901 | Expr *getAttrColumnOperand() const { return getLocalData()->ColumnOperand; } |
1902 | void setAttrColumnOperand(Expr *e) { getLocalData()->ColumnOperand = e; } |
1903 | |
1904 | /// The location of the parentheses around the operand, if there is |
1905 | /// an operand. |
1906 | /// float __attribute__((matrix_type(4, 2))) |
1907 | /// ^ ^ |
1908 | SourceRange getAttrOperandParensRange() const { |
1909 | return getLocalData()->OperandParens; |
1910 | } |
1911 | void setAttrOperandParensRange(SourceRange range) { |
1912 | getLocalData()->OperandParens = range; |
1913 | } |
1914 | |
1915 | SourceRange getLocalSourceRange() const { |
1916 | SourceRange range(getAttrNameLoc()); |
1917 | range.setEnd(getAttrOperandParensRange().getEnd()); |
1918 | return range; |
1919 | } |
1920 | |
1921 | void initializeLocal(ASTContext &Context, SourceLocation loc) { |
1922 | setAttrNameLoc(loc); |
1923 | setAttrOperandParensRange(loc); |
1924 | setAttrRowOperand(nullptr); |
1925 | setAttrColumnOperand(nullptr); |
1926 | } |
1927 | }; |
1928 | |
1929 | class ConstantMatrixTypeLoc |
1930 | : public InheritingConcreteTypeLoc<MatrixTypeLoc, ConstantMatrixTypeLoc, |
1931 | ConstantMatrixType> {}; |
1932 | |
1933 | class DependentSizedMatrixTypeLoc |
1934 | : public InheritingConcreteTypeLoc<MatrixTypeLoc, |
1935 | DependentSizedMatrixTypeLoc, |
1936 | DependentSizedMatrixType> {}; |
1937 | |
1938 | // FIXME: location of the '_Complex' keyword. |
1939 | class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
1940 | ComplexTypeLoc, |
1941 | ComplexType> { |
1942 | }; |
1943 | |
1944 | struct TypeofLocInfo { |
1945 | SourceLocation TypeofLoc; |
1946 | SourceLocation LParenLoc; |
1947 | SourceLocation RParenLoc; |
1948 | }; |
1949 | |
1950 | struct TypeOfExprTypeLocInfo : public TypeofLocInfo { |
1951 | }; |
1952 | |
1953 | struct TypeOfTypeLocInfo : public TypeofLocInfo { |
1954 | TypeSourceInfo *UnmodifiedTInfo; |
1955 | }; |
1956 | |
1957 | template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> |
1958 | class TypeofLikeTypeLoc |
1959 | : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { |
1960 | public: |
1961 | SourceLocation getTypeofLoc() const { |
1962 | return this->getLocalData()->TypeofLoc; |
1963 | } |
1964 | |
1965 | void setTypeofLoc(SourceLocation Loc) { |
1966 | this->getLocalData()->TypeofLoc = Loc; |
1967 | } |
1968 | |
1969 | SourceLocation getLParenLoc() const { |
1970 | return this->getLocalData()->LParenLoc; |
1971 | } |
1972 | |
1973 | void setLParenLoc(SourceLocation Loc) { |
1974 | this->getLocalData()->LParenLoc = Loc; |
1975 | } |
1976 | |
1977 | SourceLocation getRParenLoc() const { |
1978 | return this->getLocalData()->RParenLoc; |
1979 | } |
1980 | |
1981 | void setRParenLoc(SourceLocation Loc) { |
1982 | this->getLocalData()->RParenLoc = Loc; |
1983 | } |
1984 | |
1985 | SourceRange getParensRange() const { |
1986 | return SourceRange(getLParenLoc(), getRParenLoc()); |
1987 | } |
1988 | |
1989 | void setParensRange(SourceRange range) { |
1990 | setLParenLoc(range.getBegin()); |
1991 | setRParenLoc(range.getEnd()); |
1992 | } |
1993 | |
1994 | SourceRange getLocalSourceRange() const { |
1995 | return SourceRange(getTypeofLoc(), getRParenLoc()); |
1996 | } |
1997 | |
1998 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1999 | setTypeofLoc(Loc); |
2000 | setLParenLoc(Loc); |
2001 | setRParenLoc(Loc); |
2002 | } |
2003 | }; |
2004 | |
2005 | class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc, |
2006 | TypeOfExprType, |
2007 | TypeOfExprTypeLocInfo> { |
2008 | public: |
2009 | Expr* getUnderlyingExpr() const { |
2010 | return getTypePtr()->getUnderlyingExpr(); |
2011 | } |
2012 | |
2013 | // Reimplemented to account for GNU/C++ extension |
2014 | // typeof unary-expression |
2015 | // where there are no parentheses. |
2016 | SourceRange getLocalSourceRange() const; |
2017 | }; |
2018 | |
2019 | class TypeOfTypeLoc |
2020 | : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { |
2021 | public: |
2022 | QualType getUnmodifiedType() const { |
2023 | return this->getTypePtr()->getUnmodifiedType(); |
2024 | } |
2025 | |
2026 | TypeSourceInfo *getUnmodifiedTInfo() const { |
2027 | return this->getLocalData()->UnmodifiedTInfo; |
2028 | } |
2029 | |
2030 | void setUnmodifiedTInfo(TypeSourceInfo *TI) const { |
2031 | this->getLocalData()->UnmodifiedTInfo = TI; |
2032 | } |
2033 | |
2034 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2035 | }; |
2036 | |
2037 | // decltype(expression) abc; |
2038 | // ~~~~~~~~ DecltypeLoc |
2039 | // ~ RParenLoc |
2040 | // FIXME: add LParenLoc, it is tricky to support due to the limitation of |
2041 | // annotated-decltype token. |
2042 | struct DecltypeTypeLocInfo { |
2043 | SourceLocation DecltypeLoc; |
2044 | SourceLocation RParenLoc; |
2045 | }; |
2046 | class DecltypeTypeLoc |
2047 | : public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType, |
2048 | DecltypeTypeLocInfo> { |
2049 | public: |
2050 | Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } |
2051 | |
2052 | SourceLocation getDecltypeLoc() const { return getLocalData()->DecltypeLoc; } |
2053 | void setDecltypeLoc(SourceLocation Loc) { getLocalData()->DecltypeLoc = Loc; } |
2054 | |
2055 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2056 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2057 | |
2058 | SourceRange getLocalSourceRange() const { |
2059 | return SourceRange(getDecltypeLoc(), getRParenLoc()); |
2060 | } |
2061 | |
2062 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2063 | setDecltypeLoc(Loc); |
2064 | setRParenLoc(Loc); |
2065 | } |
2066 | }; |
2067 | |
2068 | struct PackIndexingTypeLocInfo { |
2069 | SourceLocation EllipsisLoc; |
2070 | }; |
2071 | |
2072 | class PackIndexingTypeLoc |
2073 | : public ConcreteTypeLoc<UnqualTypeLoc, PackIndexingTypeLoc, |
2074 | PackIndexingType, PackIndexingTypeLocInfo> { |
2075 | |
2076 | public: |
2077 | Expr *getIndexExpr() const { return getTypePtr()->getIndexExpr(); } |
2078 | QualType getPattern() const { return getTypePtr()->getPattern(); } |
2079 | |
2080 | SourceLocation getEllipsisLoc() const { return getLocalData()->EllipsisLoc; } |
2081 | void setEllipsisLoc(SourceLocation Loc) { getLocalData()->EllipsisLoc = Loc; } |
2082 | |
2083 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2084 | setEllipsisLoc(Loc); |
2085 | } |
2086 | |
2087 | TypeLoc getPatternLoc() const { return getInnerTypeLoc(); } |
2088 | |
2089 | QualType getInnerType() const { return this->getTypePtr()->getPattern(); } |
2090 | |
2091 | SourceRange getLocalSourceRange() const { |
2092 | return SourceRange(getEllipsisLoc(), getEllipsisLoc()); |
2093 | } |
2094 | }; |
2095 | |
2096 | struct UnaryTransformTypeLocInfo { |
2097 | // FIXME: While there's only one unary transform right now, future ones may |
2098 | // need different representations |
2099 | SourceLocation KWLoc, LParenLoc, RParenLoc; |
2100 | TypeSourceInfo *UnderlyingTInfo; |
2101 | }; |
2102 | |
2103 | class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2104 | UnaryTransformTypeLoc, |
2105 | UnaryTransformType, |
2106 | UnaryTransformTypeLocInfo> { |
2107 | public: |
2108 | SourceLocation getKWLoc() const { return getLocalData()->KWLoc; } |
2109 | void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; } |
2110 | |
2111 | SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; } |
2112 | void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; } |
2113 | |
2114 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2115 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2116 | |
2117 | TypeSourceInfo* getUnderlyingTInfo() const { |
2118 | return getLocalData()->UnderlyingTInfo; |
2119 | } |
2120 | |
2121 | void setUnderlyingTInfo(TypeSourceInfo *TInfo) { |
2122 | getLocalData()->UnderlyingTInfo = TInfo; |
2123 | } |
2124 | |
2125 | SourceRange getLocalSourceRange() const { |
2126 | return SourceRange(getKWLoc(), getRParenLoc()); |
2127 | } |
2128 | |
2129 | SourceRange getParensRange() const { |
2130 | return SourceRange(getLParenLoc(), getRParenLoc()); |
2131 | } |
2132 | |
2133 | void setParensRange(SourceRange Range) { |
2134 | setLParenLoc(Range.getBegin()); |
2135 | setRParenLoc(Range.getEnd()); |
2136 | } |
2137 | |
2138 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2139 | }; |
2140 | |
2141 | class DeducedTypeLoc |
2142 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc, |
2143 | DeducedType> {}; |
2144 | |
2145 | struct AutoTypeLocInfo : TypeSpecLocInfo { |
2146 | // For decltype(auto). |
2147 | SourceLocation RParenLoc; |
2148 | |
2149 | ConceptReference *CR = nullptr; |
2150 | }; |
2151 | |
2152 | class AutoTypeLoc |
2153 | : public ConcreteTypeLoc<DeducedTypeLoc, |
2154 | AutoTypeLoc, |
2155 | AutoType, |
2156 | AutoTypeLocInfo> { |
2157 | public: |
2158 | AutoTypeKeyword getAutoKeyword() const { |
2159 | return getTypePtr()->getKeyword(); |
2160 | } |
2161 | |
2162 | bool isDecltypeAuto() const { return getTypePtr()->isDecltypeAuto(); } |
2163 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2164 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2165 | |
2166 | bool isConstrained() const { |
2167 | return getTypePtr()->isConstrained(); |
2168 | } |
2169 | |
2170 | void setConceptReference(ConceptReference *CR) { getLocalData()->CR = CR; } |
2171 | |
2172 | ConceptReference *getConceptReference() const { return getLocalData()->CR; } |
2173 | |
2174 | // FIXME: Several of the following functions can be removed. Instead the |
2175 | // caller can directly work with the ConceptReference. |
2176 | const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const { |
2177 | if (const auto *CR = getConceptReference()) |
2178 | return CR->getNestedNameSpecifierLoc(); |
2179 | return NestedNameSpecifierLoc(); |
2180 | } |
2181 | |
2182 | SourceLocation getTemplateKWLoc() const { |
2183 | if (const auto *CR = getConceptReference()) |
2184 | return CR->getTemplateKWLoc(); |
2185 | return SourceLocation(); |
2186 | } |
2187 | |
2188 | SourceLocation getConceptNameLoc() const { |
2189 | if (const auto *CR = getConceptReference()) |
2190 | return CR->getConceptNameLoc(); |
2191 | return SourceLocation(); |
2192 | } |
2193 | |
2194 | NamedDecl *getFoundDecl() const { |
2195 | if (const auto *CR = getConceptReference()) |
2196 | return CR->getFoundDecl(); |
2197 | return nullptr; |
2198 | } |
2199 | |
2200 | ConceptDecl *getNamedConcept() const { |
2201 | if (const auto *CR = getConceptReference()) |
2202 | return CR->getNamedConcept(); |
2203 | return nullptr; |
2204 | } |
2205 | |
2206 | DeclarationNameInfo getConceptNameInfo() const { |
2207 | return getConceptReference()->getConceptNameInfo(); |
2208 | } |
2209 | |
2210 | bool hasExplicitTemplateArgs() const { |
2211 | return (getConceptReference() && |
2212 | getConceptReference()->getTemplateArgsAsWritten() && |
2213 | getConceptReference() |
2214 | ->getTemplateArgsAsWritten() |
2215 | ->getLAngleLoc() |
2216 | .isValid()); |
2217 | } |
2218 | |
2219 | SourceLocation getLAngleLoc() const { |
2220 | if (const auto *CR = getConceptReference()) |
2221 | if (const auto *TAAW = CR->getTemplateArgsAsWritten()) |
2222 | return TAAW->getLAngleLoc(); |
2223 | return SourceLocation(); |
2224 | } |
2225 | |
2226 | SourceLocation getRAngleLoc() const { |
2227 | if (const auto *CR = getConceptReference()) |
2228 | if (const auto *TAAW = CR->getTemplateArgsAsWritten()) |
2229 | return TAAW->getRAngleLoc(); |
2230 | return SourceLocation(); |
2231 | } |
2232 | |
2233 | unsigned getNumArgs() const { |
2234 | return getTypePtr()->getTypeConstraintArguments().size(); |
2235 | } |
2236 | |
2237 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
2238 | const auto *CR = getConceptReference(); |
2239 | assert(CR && "No ConceptReference" ); |
2240 | return CR->getTemplateArgsAsWritten()->getTemplateArgs()[i]; |
2241 | } |
2242 | |
2243 | SourceRange getLocalSourceRange() const { |
2244 | return {isConstrained() |
2245 | ? (getNestedNameSpecifierLoc() |
2246 | ? getNestedNameSpecifierLoc().getBeginLoc() |
2247 | : (getTemplateKWLoc().isValid() ? getTemplateKWLoc() |
2248 | : getConceptNameLoc())) |
2249 | : getNameLoc(), |
2250 | isDecltypeAuto() ? getRParenLoc() : getNameLoc()}; |
2251 | } |
2252 | |
2253 | void copy(AutoTypeLoc Loc) { |
2254 | unsigned size = getFullDataSize(); |
2255 | assert(size == Loc.getFullDataSize()); |
2256 | memcpy(Data, Loc.Data, size); |
2257 | } |
2258 | |
2259 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2260 | }; |
2261 | |
2262 | class DeducedTemplateSpecializationTypeLoc |
2263 | : public InheritingConcreteTypeLoc<DeducedTypeLoc, |
2264 | DeducedTemplateSpecializationTypeLoc, |
2265 | DeducedTemplateSpecializationType> { |
2266 | public: |
2267 | SourceLocation getTemplateNameLoc() const { |
2268 | return getNameLoc(); |
2269 | } |
2270 | |
2271 | void setTemplateNameLoc(SourceLocation Loc) { |
2272 | setNameLoc(Loc); |
2273 | } |
2274 | }; |
2275 | |
2276 | struct ElaboratedLocInfo { |
2277 | SourceLocation ElaboratedKWLoc; |
2278 | |
2279 | /// Data associated with the nested-name-specifier location. |
2280 | void *QualifierData; |
2281 | }; |
2282 | |
2283 | class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2284 | ElaboratedTypeLoc, |
2285 | ElaboratedType, |
2286 | ElaboratedLocInfo> { |
2287 | public: |
2288 | SourceLocation getElaboratedKeywordLoc() const { |
2289 | return !isEmpty() ? getLocalData()->ElaboratedKWLoc : SourceLocation(); |
2290 | } |
2291 | |
2292 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2293 | if (isEmpty()) { |
2294 | assert(Loc.isInvalid()); |
2295 | return; |
2296 | } |
2297 | getLocalData()->ElaboratedKWLoc = Loc; |
2298 | } |
2299 | |
2300 | NestedNameSpecifierLoc getQualifierLoc() const { |
2301 | return !isEmpty() ? NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2302 | getLocalData()->QualifierData) |
2303 | : NestedNameSpecifierLoc(); |
2304 | } |
2305 | |
2306 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2307 | assert(QualifierLoc.getNestedNameSpecifier() == |
2308 | getTypePtr()->getQualifier() && |
2309 | "Inconsistent nested-name-specifier pointer" ); |
2310 | if (isEmpty()) { |
2311 | assert(!QualifierLoc.hasQualifier()); |
2312 | return; |
2313 | } |
2314 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2315 | } |
2316 | |
2317 | SourceRange getLocalSourceRange() const { |
2318 | if (getElaboratedKeywordLoc().isValid()) |
2319 | if (getQualifierLoc()) |
2320 | return SourceRange(getElaboratedKeywordLoc(), |
2321 | getQualifierLoc().getEndLoc()); |
2322 | else |
2323 | return SourceRange(getElaboratedKeywordLoc()); |
2324 | else |
2325 | return getQualifierLoc().getSourceRange(); |
2326 | } |
2327 | |
2328 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2329 | |
2330 | TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); } |
2331 | |
2332 | QualType getInnerType() const { return getTypePtr()->getNamedType(); } |
2333 | |
2334 | bool isEmpty() const { |
2335 | return getTypePtr()->getKeyword() == ElaboratedTypeKeyword::None && |
2336 | !getTypePtr()->getQualifier(); |
2337 | } |
2338 | |
2339 | unsigned getLocalDataAlignment() const { |
2340 | // FIXME: We want to return 1 here in the empty case, but |
2341 | // there are bugs in how alignment is handled in TypeLocs |
2342 | // that prevent this from working. |
2343 | return ConcreteTypeLoc::getLocalDataAlignment(); |
2344 | } |
2345 | |
2346 | unsigned getLocalDataSize() const { |
2347 | return !isEmpty() ? ConcreteTypeLoc::getLocalDataSize() : 0; |
2348 | } |
2349 | |
2350 | void copy(ElaboratedTypeLoc Loc) { |
2351 | unsigned size = getFullDataSize(); |
2352 | assert(size == Loc.getFullDataSize()); |
2353 | memcpy(Data, Loc.Data, size); |
2354 | } |
2355 | }; |
2356 | |
2357 | // This is exactly the structure of an ElaboratedTypeLoc whose inner |
2358 | // type is some sort of TypeDeclTypeLoc. |
2359 | struct DependentNameLocInfo : ElaboratedLocInfo { |
2360 | SourceLocation NameLoc; |
2361 | }; |
2362 | |
2363 | class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2364 | DependentNameTypeLoc, |
2365 | DependentNameType, |
2366 | DependentNameLocInfo> { |
2367 | public: |
2368 | SourceLocation getElaboratedKeywordLoc() const { |
2369 | return this->getLocalData()->ElaboratedKWLoc; |
2370 | } |
2371 | |
2372 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2373 | this->getLocalData()->ElaboratedKWLoc = Loc; |
2374 | } |
2375 | |
2376 | NestedNameSpecifierLoc getQualifierLoc() const { |
2377 | return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2378 | getLocalData()->QualifierData); |
2379 | } |
2380 | |
2381 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2382 | assert(QualifierLoc.getNestedNameSpecifier() |
2383 | == getTypePtr()->getQualifier() && |
2384 | "Inconsistent nested-name-specifier pointer" ); |
2385 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2386 | } |
2387 | |
2388 | SourceLocation getNameLoc() const { |
2389 | return this->getLocalData()->NameLoc; |
2390 | } |
2391 | |
2392 | void setNameLoc(SourceLocation Loc) { |
2393 | this->getLocalData()->NameLoc = Loc; |
2394 | } |
2395 | |
2396 | SourceRange getLocalSourceRange() const { |
2397 | if (getElaboratedKeywordLoc().isValid()) |
2398 | return SourceRange(getElaboratedKeywordLoc(), getNameLoc()); |
2399 | else |
2400 | return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); |
2401 | } |
2402 | |
2403 | void copy(DependentNameTypeLoc Loc) { |
2404 | unsigned size = getFullDataSize(); |
2405 | assert(size == Loc.getFullDataSize()); |
2406 | memcpy(Data, Loc.Data, size); |
2407 | } |
2408 | |
2409 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2410 | }; |
2411 | |
2412 | struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { |
2413 | SourceLocation TemplateKWLoc; |
2414 | SourceLocation LAngleLoc; |
2415 | SourceLocation RAngleLoc; |
2416 | // followed by a TemplateArgumentLocInfo[] |
2417 | }; |
2418 | |
2419 | class DependentTemplateSpecializationTypeLoc : |
2420 | public ConcreteTypeLoc<UnqualTypeLoc, |
2421 | DependentTemplateSpecializationTypeLoc, |
2422 | DependentTemplateSpecializationType, |
2423 | DependentTemplateSpecializationLocInfo> { |
2424 | public: |
2425 | SourceLocation getElaboratedKeywordLoc() const { |
2426 | return this->getLocalData()->ElaboratedKWLoc; |
2427 | } |
2428 | |
2429 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2430 | this->getLocalData()->ElaboratedKWLoc = Loc; |
2431 | } |
2432 | |
2433 | NestedNameSpecifierLoc getQualifierLoc() const { |
2434 | if (!getLocalData()->QualifierData) |
2435 | return NestedNameSpecifierLoc(); |
2436 | |
2437 | return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2438 | getLocalData()->QualifierData); |
2439 | } |
2440 | |
2441 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2442 | if (!QualifierLoc) { |
2443 | // Even if we have a nested-name-specifier in the dependent |
2444 | // template specialization type, we won't record the nested-name-specifier |
2445 | // location information when this type-source location information is |
2446 | // part of a nested-name-specifier. |
2447 | getLocalData()->QualifierData = nullptr; |
2448 | return; |
2449 | } |
2450 | |
2451 | assert(QualifierLoc.getNestedNameSpecifier() |
2452 | == getTypePtr()->getQualifier() && |
2453 | "Inconsistent nested-name-specifier pointer" ); |
2454 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2455 | } |
2456 | |
2457 | SourceLocation getTemplateKeywordLoc() const { |
2458 | return getLocalData()->TemplateKWLoc; |
2459 | } |
2460 | |
2461 | void setTemplateKeywordLoc(SourceLocation Loc) { |
2462 | getLocalData()->TemplateKWLoc = Loc; |
2463 | } |
2464 | |
2465 | SourceLocation getTemplateNameLoc() const { |
2466 | return this->getLocalData()->NameLoc; |
2467 | } |
2468 | |
2469 | void setTemplateNameLoc(SourceLocation Loc) { |
2470 | this->getLocalData()->NameLoc = Loc; |
2471 | } |
2472 | |
2473 | SourceLocation getLAngleLoc() const { |
2474 | return this->getLocalData()->LAngleLoc; |
2475 | } |
2476 | |
2477 | void setLAngleLoc(SourceLocation Loc) { |
2478 | this->getLocalData()->LAngleLoc = Loc; |
2479 | } |
2480 | |
2481 | SourceLocation getRAngleLoc() const { |
2482 | return this->getLocalData()->RAngleLoc; |
2483 | } |
2484 | |
2485 | void setRAngleLoc(SourceLocation Loc) { |
2486 | this->getLocalData()->RAngleLoc = Loc; |
2487 | } |
2488 | |
2489 | unsigned getNumArgs() const { |
2490 | return getTypePtr()->template_arguments().size(); |
2491 | } |
2492 | |
2493 | void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { |
2494 | getArgInfos()[i] = AI; |
2495 | } |
2496 | |
2497 | TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { |
2498 | return getArgInfos()[i]; |
2499 | } |
2500 | |
2501 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
2502 | return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], |
2503 | getArgLocInfo(i)); |
2504 | } |
2505 | |
2506 | SourceRange getLocalSourceRange() const { |
2507 | if (getElaboratedKeywordLoc().isValid()) |
2508 | return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc()); |
2509 | else if (getQualifierLoc()) |
2510 | return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); |
2511 | else if (getTemplateKeywordLoc().isValid()) |
2512 | return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); |
2513 | else |
2514 | return SourceRange(getTemplateNameLoc(), getRAngleLoc()); |
2515 | } |
2516 | |
2517 | void copy(DependentTemplateSpecializationTypeLoc Loc) { |
2518 | unsigned size = getFullDataSize(); |
2519 | assert(size == Loc.getFullDataSize()); |
2520 | memcpy(Data, Loc.Data, size); |
2521 | } |
2522 | |
2523 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2524 | |
2525 | unsigned () const { |
2526 | return getNumArgs() * sizeof(TemplateArgumentLocInfo); |
2527 | } |
2528 | |
2529 | unsigned () const { |
2530 | return alignof(TemplateArgumentLocInfo); |
2531 | } |
2532 | |
2533 | private: |
2534 | TemplateArgumentLocInfo *getArgInfos() const { |
2535 | return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
2536 | } |
2537 | }; |
2538 | |
2539 | struct PackExpansionTypeLocInfo { |
2540 | SourceLocation EllipsisLoc; |
2541 | }; |
2542 | |
2543 | class PackExpansionTypeLoc |
2544 | : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, |
2545 | PackExpansionType, PackExpansionTypeLocInfo> { |
2546 | public: |
2547 | SourceLocation getEllipsisLoc() const { |
2548 | return this->getLocalData()->EllipsisLoc; |
2549 | } |
2550 | |
2551 | void setEllipsisLoc(SourceLocation Loc) { |
2552 | this->getLocalData()->EllipsisLoc = Loc; |
2553 | } |
2554 | |
2555 | SourceRange getLocalSourceRange() const { |
2556 | return SourceRange(getEllipsisLoc(), getEllipsisLoc()); |
2557 | } |
2558 | |
2559 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2560 | setEllipsisLoc(Loc); |
2561 | } |
2562 | |
2563 | TypeLoc getPatternLoc() const { |
2564 | return getInnerTypeLoc(); |
2565 | } |
2566 | |
2567 | QualType getInnerType() const { |
2568 | return this->getTypePtr()->getPattern(); |
2569 | } |
2570 | }; |
2571 | |
2572 | struct AtomicTypeLocInfo { |
2573 | SourceLocation KWLoc, LParenLoc, RParenLoc; |
2574 | }; |
2575 | |
2576 | class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc, |
2577 | AtomicType, AtomicTypeLocInfo> { |
2578 | public: |
2579 | TypeLoc getValueLoc() const { |
2580 | return this->getInnerTypeLoc(); |
2581 | } |
2582 | |
2583 | SourceRange getLocalSourceRange() const { |
2584 | return SourceRange(getKWLoc(), getRParenLoc()); |
2585 | } |
2586 | |
2587 | SourceLocation getKWLoc() const { |
2588 | return this->getLocalData()->KWLoc; |
2589 | } |
2590 | |
2591 | void setKWLoc(SourceLocation Loc) { |
2592 | this->getLocalData()->KWLoc = Loc; |
2593 | } |
2594 | |
2595 | SourceLocation getLParenLoc() const { |
2596 | return this->getLocalData()->LParenLoc; |
2597 | } |
2598 | |
2599 | void setLParenLoc(SourceLocation Loc) { |
2600 | this->getLocalData()->LParenLoc = Loc; |
2601 | } |
2602 | |
2603 | SourceLocation getRParenLoc() const { |
2604 | return this->getLocalData()->RParenLoc; |
2605 | } |
2606 | |
2607 | void setRParenLoc(SourceLocation Loc) { |
2608 | this->getLocalData()->RParenLoc = Loc; |
2609 | } |
2610 | |
2611 | SourceRange getParensRange() const { |
2612 | return SourceRange(getLParenLoc(), getRParenLoc()); |
2613 | } |
2614 | |
2615 | void setParensRange(SourceRange Range) { |
2616 | setLParenLoc(Range.getBegin()); |
2617 | setRParenLoc(Range.getEnd()); |
2618 | } |
2619 | |
2620 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2621 | setKWLoc(Loc); |
2622 | setLParenLoc(Loc); |
2623 | setRParenLoc(Loc); |
2624 | } |
2625 | |
2626 | QualType getInnerType() const { |
2627 | return this->getTypePtr()->getValueType(); |
2628 | } |
2629 | }; |
2630 | |
2631 | struct PipeTypeLocInfo { |
2632 | SourceLocation KWLoc; |
2633 | }; |
2634 | |
2635 | class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType, |
2636 | PipeTypeLocInfo> { |
2637 | public: |
2638 | TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } |
2639 | |
2640 | SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); } |
2641 | |
2642 | SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } |
2643 | void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } |
2644 | |
2645 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2646 | setKWLoc(Loc); |
2647 | } |
2648 | |
2649 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
2650 | }; |
2651 | |
2652 | template <typename T> |
2653 | inline T TypeLoc::getAsAdjusted() const { |
2654 | TypeLoc Cur = *this; |
2655 | while (!T::isKind(Cur)) { |
2656 | if (auto PTL = Cur.getAs<ParenTypeLoc>()) |
2657 | Cur = PTL.getInnerLoc(); |
2658 | else if (auto ATL = Cur.getAs<AttributedTypeLoc>()) |
2659 | Cur = ATL.getModifiedLoc(); |
2660 | else if (auto ATL = Cur.getAs<BTFTagAttributedTypeLoc>()) |
2661 | Cur = ATL.getWrappedLoc(); |
2662 | else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>()) |
2663 | Cur = ETL.getNamedTypeLoc(); |
2664 | else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) |
2665 | Cur = ATL.getOriginalLoc(); |
2666 | else if (auto MQL = Cur.getAs<MacroQualifiedTypeLoc>()) |
2667 | Cur = MQL.getInnerLoc(); |
2668 | else |
2669 | break; |
2670 | } |
2671 | return Cur.getAs<T>(); |
2672 | } |
2673 | class BitIntTypeLoc final |
2674 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, BitIntTypeLoc, |
2675 | BitIntType> {}; |
2676 | class DependentBitIntTypeLoc final |
2677 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc, |
2678 | DependentBitIntType> {}; |
2679 | |
2680 | class ObjCProtocolLoc { |
2681 | ObjCProtocolDecl *Protocol = nullptr; |
2682 | SourceLocation Loc = SourceLocation(); |
2683 | |
2684 | public: |
2685 | ObjCProtocolLoc(ObjCProtocolDecl *protocol, SourceLocation loc) |
2686 | : Protocol(protocol), Loc(loc) {} |
2687 | ObjCProtocolDecl *getProtocol() const { return Protocol; } |
2688 | SourceLocation getLocation() const { return Loc; } |
2689 | |
2690 | /// The source range is just the protocol name. |
2691 | SourceRange getSourceRange() const LLVM_READONLY { |
2692 | return SourceRange(Loc, Loc); |
2693 | } |
2694 | }; |
2695 | |
2696 | } // namespace clang |
2697 | |
2698 | #endif // LLVM_CLANG_AST_TYPELOC_H |
2699 | |