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 BoundsAttributedLocInfo {}; |
1124 | class BoundsAttributedTypeLoc |
1125 | : public ConcreteTypeLoc<UnqualTypeLoc, BoundsAttributedTypeLoc, |
1126 | BoundsAttributedType, BoundsAttributedLocInfo> { |
1127 | public: |
1128 | TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } |
1129 | QualType getInnerType() const { return getTypePtr()->desugar(); } |
1130 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1131 | // nothing to do |
1132 | } |
1133 | // LocalData is empty and TypeLocBuilder doesn't handle DataSize 1. |
1134 | unsigned getLocalDataSize() const { return 0; } |
1135 | }; |
1136 | |
1137 | class CountAttributedTypeLoc final |
1138 | : public InheritingConcreteTypeLoc<BoundsAttributedTypeLoc, |
1139 | CountAttributedTypeLoc, |
1140 | CountAttributedType> { |
1141 | public: |
1142 | Expr *getCountExpr() const { return getTypePtr()->getCountExpr(); } |
1143 | bool isCountInBytes() const { return getTypePtr()->isCountInBytes(); } |
1144 | bool isOrNull() const { return getTypePtr()->isOrNull(); } |
1145 | |
1146 | SourceRange getLocalSourceRange() const; |
1147 | }; |
1148 | |
1149 | struct MacroQualifiedLocInfo { |
1150 | SourceLocation ExpansionLoc; |
1151 | }; |
1152 | |
1153 | class MacroQualifiedTypeLoc |
1154 | : public ConcreteTypeLoc<UnqualTypeLoc, MacroQualifiedTypeLoc, |
1155 | MacroQualifiedType, MacroQualifiedLocInfo> { |
1156 | public: |
1157 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1158 | setExpansionLoc(Loc); |
1159 | } |
1160 | |
1161 | TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } |
1162 | |
1163 | const IdentifierInfo *getMacroIdentifier() const { |
1164 | return getTypePtr()->getMacroIdentifier(); |
1165 | } |
1166 | |
1167 | SourceLocation getExpansionLoc() const { |
1168 | return this->getLocalData()->ExpansionLoc; |
1169 | } |
1170 | |
1171 | void setExpansionLoc(SourceLocation Loc) { |
1172 | this->getLocalData()->ExpansionLoc = Loc; |
1173 | } |
1174 | |
1175 | QualType getInnerType() const { return getTypePtr()->getUnderlyingType(); } |
1176 | |
1177 | SourceRange getLocalSourceRange() const { |
1178 | return getInnerLoc().getLocalSourceRange(); |
1179 | } |
1180 | }; |
1181 | |
1182 | struct ParenLocInfo { |
1183 | SourceLocation LParenLoc; |
1184 | SourceLocation RParenLoc; |
1185 | }; |
1186 | |
1187 | class ParenTypeLoc |
1188 | : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType, |
1189 | ParenLocInfo> { |
1190 | public: |
1191 | SourceLocation getLParenLoc() const { |
1192 | return this->getLocalData()->LParenLoc; |
1193 | } |
1194 | |
1195 | SourceLocation getRParenLoc() const { |
1196 | return this->getLocalData()->RParenLoc; |
1197 | } |
1198 | |
1199 | void setLParenLoc(SourceLocation Loc) { |
1200 | this->getLocalData()->LParenLoc = Loc; |
1201 | } |
1202 | |
1203 | void setRParenLoc(SourceLocation Loc) { |
1204 | this->getLocalData()->RParenLoc = Loc; |
1205 | } |
1206 | |
1207 | SourceRange getLocalSourceRange() const { |
1208 | return SourceRange(getLParenLoc(), getRParenLoc()); |
1209 | } |
1210 | |
1211 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1212 | setLParenLoc(Loc); |
1213 | setRParenLoc(Loc); |
1214 | } |
1215 | |
1216 | TypeLoc getInnerLoc() const { |
1217 | return getInnerTypeLoc(); |
1218 | } |
1219 | |
1220 | QualType getInnerType() const { |
1221 | return this->getTypePtr()->getInnerType(); |
1222 | } |
1223 | }; |
1224 | |
1225 | inline TypeLoc TypeLoc::IgnoreParens() const { |
1226 | if (ParenTypeLoc::isKind(*this)) |
1227 | return IgnoreParensImpl(TL: *this); |
1228 | return *this; |
1229 | } |
1230 | |
1231 | struct AdjustedLocInfo {}; // Nothing. |
1232 | |
1233 | class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, |
1234 | AdjustedType, AdjustedLocInfo> { |
1235 | public: |
1236 | TypeLoc getOriginalLoc() const { |
1237 | return getInnerTypeLoc(); |
1238 | } |
1239 | |
1240 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1241 | // do nothing |
1242 | } |
1243 | |
1244 | QualType getInnerType() const { |
1245 | // The inner type is the undecayed type, since that's what we have source |
1246 | // location information for. |
1247 | return getTypePtr()->getOriginalType(); |
1248 | } |
1249 | |
1250 | SourceRange getLocalSourceRange() const { return {}; } |
1251 | |
1252 | unsigned getLocalDataSize() const { |
1253 | // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique |
1254 | // anyway. TypeLocBuilder can't handle data sizes of 1. |
1255 | return 0; // No data. |
1256 | } |
1257 | }; |
1258 | |
1259 | /// Wrapper for source info for pointers decayed from arrays and |
1260 | /// functions. |
1261 | class DecayedTypeLoc : public InheritingConcreteTypeLoc< |
1262 | AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { |
1263 | }; |
1264 | |
1265 | struct PointerLikeLocInfo { |
1266 | SourceLocation StarLoc; |
1267 | }; |
1268 | |
1269 | /// A base class for |
1270 | template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> |
1271 | class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, |
1272 | TypeClass, LocalData> { |
1273 | public: |
1274 | SourceLocation getSigilLoc() const { |
1275 | return this->getLocalData()->StarLoc; |
1276 | } |
1277 | |
1278 | void setSigilLoc(SourceLocation Loc) { |
1279 | this->getLocalData()->StarLoc = Loc; |
1280 | } |
1281 | |
1282 | TypeLoc getPointeeLoc() const { |
1283 | return this->getInnerTypeLoc(); |
1284 | } |
1285 | |
1286 | SourceRange getLocalSourceRange() const { |
1287 | return SourceRange(getSigilLoc(), getSigilLoc()); |
1288 | } |
1289 | |
1290 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1291 | setSigilLoc(Loc); |
1292 | } |
1293 | |
1294 | QualType getInnerType() const { |
1295 | return this->getTypePtr()->getPointeeType(); |
1296 | } |
1297 | }; |
1298 | |
1299 | /// Wrapper for source info for pointers. |
1300 | class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, |
1301 | PointerType> { |
1302 | public: |
1303 | SourceLocation getStarLoc() const { |
1304 | return getSigilLoc(); |
1305 | } |
1306 | |
1307 | void setStarLoc(SourceLocation Loc) { |
1308 | setSigilLoc(Loc); |
1309 | } |
1310 | }; |
1311 | |
1312 | /// Wrapper for source info for block pointers. |
1313 | class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, |
1314 | BlockPointerType> { |
1315 | public: |
1316 | SourceLocation getCaretLoc() const { |
1317 | return getSigilLoc(); |
1318 | } |
1319 | |
1320 | void setCaretLoc(SourceLocation Loc) { |
1321 | setSigilLoc(Loc); |
1322 | } |
1323 | }; |
1324 | |
1325 | struct MemberPointerLocInfo : public PointerLikeLocInfo { |
1326 | TypeSourceInfo *ClassTInfo; |
1327 | }; |
1328 | |
1329 | /// Wrapper for source info for member pointers. |
1330 | class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, |
1331 | MemberPointerType, |
1332 | MemberPointerLocInfo> { |
1333 | public: |
1334 | SourceLocation getStarLoc() const { |
1335 | return getSigilLoc(); |
1336 | } |
1337 | |
1338 | void setStarLoc(SourceLocation Loc) { |
1339 | setSigilLoc(Loc); |
1340 | } |
1341 | |
1342 | const Type *getClass() const { |
1343 | return getTypePtr()->getClass(); |
1344 | } |
1345 | |
1346 | TypeSourceInfo *getClassTInfo() const { |
1347 | return getLocalData()->ClassTInfo; |
1348 | } |
1349 | |
1350 | void setClassTInfo(TypeSourceInfo* TI) { |
1351 | getLocalData()->ClassTInfo = TI; |
1352 | } |
1353 | |
1354 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1355 | setSigilLoc(Loc); |
1356 | setClassTInfo(nullptr); |
1357 | } |
1358 | |
1359 | SourceRange getLocalSourceRange() const { |
1360 | if (TypeSourceInfo *TI = getClassTInfo()) |
1361 | return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); |
1362 | else |
1363 | return SourceRange(getStarLoc()); |
1364 | } |
1365 | }; |
1366 | |
1367 | /// Wraps an ObjCPointerType with source location information. |
1368 | class ObjCObjectPointerTypeLoc : |
1369 | public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, |
1370 | ObjCObjectPointerType> { |
1371 | public: |
1372 | SourceLocation getStarLoc() const { |
1373 | return getSigilLoc(); |
1374 | } |
1375 | |
1376 | void setStarLoc(SourceLocation Loc) { |
1377 | setSigilLoc(Loc); |
1378 | } |
1379 | }; |
1380 | |
1381 | class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, |
1382 | ReferenceType> { |
1383 | public: |
1384 | QualType getInnerType() const { |
1385 | return getTypePtr()->getPointeeTypeAsWritten(); |
1386 | } |
1387 | }; |
1388 | |
1389 | class LValueReferenceTypeLoc : |
1390 | public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
1391 | LValueReferenceTypeLoc, |
1392 | LValueReferenceType> { |
1393 | public: |
1394 | SourceLocation getAmpLoc() const { |
1395 | return getSigilLoc(); |
1396 | } |
1397 | |
1398 | void setAmpLoc(SourceLocation Loc) { |
1399 | setSigilLoc(Loc); |
1400 | } |
1401 | }; |
1402 | |
1403 | class RValueReferenceTypeLoc : |
1404 | public InheritingConcreteTypeLoc<ReferenceTypeLoc, |
1405 | RValueReferenceTypeLoc, |
1406 | RValueReferenceType> { |
1407 | public: |
1408 | SourceLocation getAmpAmpLoc() const { |
1409 | return getSigilLoc(); |
1410 | } |
1411 | |
1412 | void setAmpAmpLoc(SourceLocation Loc) { |
1413 | setSigilLoc(Loc); |
1414 | } |
1415 | }; |
1416 | |
1417 | struct FunctionLocInfo { |
1418 | SourceLocation LocalRangeBegin; |
1419 | SourceLocation LParenLoc; |
1420 | SourceLocation RParenLoc; |
1421 | SourceLocation LocalRangeEnd; |
1422 | }; |
1423 | |
1424 | /// Wrapper for source info for functions. |
1425 | class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
1426 | FunctionTypeLoc, |
1427 | FunctionType, |
1428 | FunctionLocInfo> { |
1429 | bool hasExceptionSpec() const { |
1430 | if (auto *FPT = dyn_cast<FunctionProtoType>(getTypePtr())) { |
1431 | return FPT->hasExceptionSpec(); |
1432 | } |
1433 | return false; |
1434 | } |
1435 | |
1436 | SourceRange *getExceptionSpecRangePtr() const { |
1437 | assert(hasExceptionSpec() && "No exception spec range" ); |
1438 | // After the Info comes the ParmVarDecl array, and after that comes the |
1439 | // exception specification information. |
1440 | return (SourceRange *)(getParmArray() + getNumParams()); |
1441 | } |
1442 | |
1443 | public: |
1444 | SourceLocation getLocalRangeBegin() const { |
1445 | return getLocalData()->LocalRangeBegin; |
1446 | } |
1447 | |
1448 | void setLocalRangeBegin(SourceLocation L) { |
1449 | getLocalData()->LocalRangeBegin = L; |
1450 | } |
1451 | |
1452 | SourceLocation getLocalRangeEnd() const { |
1453 | return getLocalData()->LocalRangeEnd; |
1454 | } |
1455 | |
1456 | void setLocalRangeEnd(SourceLocation L) { |
1457 | getLocalData()->LocalRangeEnd = L; |
1458 | } |
1459 | |
1460 | SourceLocation getLParenLoc() const { |
1461 | return this->getLocalData()->LParenLoc; |
1462 | } |
1463 | |
1464 | void setLParenLoc(SourceLocation Loc) { |
1465 | this->getLocalData()->LParenLoc = Loc; |
1466 | } |
1467 | |
1468 | SourceLocation getRParenLoc() const { |
1469 | return this->getLocalData()->RParenLoc; |
1470 | } |
1471 | |
1472 | void setRParenLoc(SourceLocation Loc) { |
1473 | this->getLocalData()->RParenLoc = Loc; |
1474 | } |
1475 | |
1476 | SourceRange getParensRange() const { |
1477 | return SourceRange(getLParenLoc(), getRParenLoc()); |
1478 | } |
1479 | |
1480 | SourceRange getExceptionSpecRange() const { |
1481 | if (hasExceptionSpec()) |
1482 | return *getExceptionSpecRangePtr(); |
1483 | return {}; |
1484 | } |
1485 | |
1486 | void setExceptionSpecRange(SourceRange R) { |
1487 | if (hasExceptionSpec()) |
1488 | *getExceptionSpecRangePtr() = R; |
1489 | } |
1490 | |
1491 | ArrayRef<ParmVarDecl *> getParams() const { |
1492 | return llvm::ArrayRef(getParmArray(), getNumParams()); |
1493 | } |
1494 | |
1495 | // ParmVarDecls* are stored after Info, one for each parameter. |
1496 | ParmVarDecl **getParmArray() const { |
1497 | return (ParmVarDecl**) getExtraLocalData(); |
1498 | } |
1499 | |
1500 | unsigned getNumParams() const { |
1501 | if (isa<FunctionNoProtoType>(getTypePtr())) |
1502 | return 0; |
1503 | return cast<FunctionProtoType>(getTypePtr())->getNumParams(); |
1504 | } |
1505 | |
1506 | ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } |
1507 | void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } |
1508 | |
1509 | TypeLoc getReturnLoc() const { |
1510 | return getInnerTypeLoc(); |
1511 | } |
1512 | |
1513 | SourceRange getLocalSourceRange() const { |
1514 | return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); |
1515 | } |
1516 | |
1517 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1518 | setLocalRangeBegin(Loc); |
1519 | setLParenLoc(Loc); |
1520 | setRParenLoc(Loc); |
1521 | setLocalRangeEnd(Loc); |
1522 | for (unsigned i = 0, e = getNumParams(); i != e; ++i) |
1523 | setParam(i, VD: nullptr); |
1524 | if (hasExceptionSpec()) |
1525 | setExceptionSpecRange(Loc); |
1526 | } |
1527 | |
1528 | /// Returns the size of the type source info data block that is |
1529 | /// specific to this type. |
1530 | unsigned () const { |
1531 | unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0; |
1532 | return (getNumParams() * sizeof(ParmVarDecl *)) + ExceptSpecSize; |
1533 | } |
1534 | |
1535 | unsigned () const { return alignof(ParmVarDecl *); } |
1536 | |
1537 | QualType getInnerType() const { return getTypePtr()->getReturnType(); } |
1538 | }; |
1539 | |
1540 | class FunctionProtoTypeLoc : |
1541 | public InheritingConcreteTypeLoc<FunctionTypeLoc, |
1542 | FunctionProtoTypeLoc, |
1543 | FunctionProtoType> { |
1544 | }; |
1545 | |
1546 | class FunctionNoProtoTypeLoc : |
1547 | public InheritingConcreteTypeLoc<FunctionTypeLoc, |
1548 | FunctionNoProtoTypeLoc, |
1549 | FunctionNoProtoType> { |
1550 | }; |
1551 | |
1552 | struct ArrayLocInfo { |
1553 | SourceLocation LBracketLoc, RBracketLoc; |
1554 | Expr *Size; |
1555 | }; |
1556 | |
1557 | /// Wrapper for source info for arrays. |
1558 | class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
1559 | ArrayTypeLoc, |
1560 | ArrayType, |
1561 | ArrayLocInfo> { |
1562 | public: |
1563 | SourceLocation getLBracketLoc() const { |
1564 | return getLocalData()->LBracketLoc; |
1565 | } |
1566 | |
1567 | void setLBracketLoc(SourceLocation Loc) { |
1568 | getLocalData()->LBracketLoc = Loc; |
1569 | } |
1570 | |
1571 | SourceLocation getRBracketLoc() const { |
1572 | return getLocalData()->RBracketLoc; |
1573 | } |
1574 | |
1575 | void setRBracketLoc(SourceLocation Loc) { |
1576 | getLocalData()->RBracketLoc = Loc; |
1577 | } |
1578 | |
1579 | SourceRange getBracketsRange() const { |
1580 | return SourceRange(getLBracketLoc(), getRBracketLoc()); |
1581 | } |
1582 | |
1583 | Expr *getSizeExpr() const { |
1584 | return getLocalData()->Size; |
1585 | } |
1586 | |
1587 | void setSizeExpr(Expr *Size) { |
1588 | getLocalData()->Size = Size; |
1589 | } |
1590 | |
1591 | TypeLoc getElementLoc() const { |
1592 | return getInnerTypeLoc(); |
1593 | } |
1594 | |
1595 | SourceRange getLocalSourceRange() const { |
1596 | return SourceRange(getLBracketLoc(), getRBracketLoc()); |
1597 | } |
1598 | |
1599 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1600 | setLBracketLoc(Loc); |
1601 | setRBracketLoc(Loc); |
1602 | setSizeExpr(nullptr); |
1603 | } |
1604 | |
1605 | QualType getInnerType() const { return getTypePtr()->getElementType(); } |
1606 | }; |
1607 | |
1608 | class ConstantArrayTypeLoc : |
1609 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1610 | ConstantArrayTypeLoc, |
1611 | ConstantArrayType> { |
1612 | }; |
1613 | |
1614 | /// Wrapper for source info for array parameter types. |
1615 | class ArrayParameterTypeLoc |
1616 | : public InheritingConcreteTypeLoc< |
1617 | ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {}; |
1618 | |
1619 | class IncompleteArrayTypeLoc : |
1620 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1621 | IncompleteArrayTypeLoc, |
1622 | IncompleteArrayType> { |
1623 | }; |
1624 | |
1625 | class DependentSizedArrayTypeLoc : |
1626 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1627 | DependentSizedArrayTypeLoc, |
1628 | DependentSizedArrayType> { |
1629 | public: |
1630 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1631 | ArrayTypeLoc::initializeLocal(Context, Loc); |
1632 | setSizeExpr(getTypePtr()->getSizeExpr()); |
1633 | } |
1634 | }; |
1635 | |
1636 | class VariableArrayTypeLoc : |
1637 | public InheritingConcreteTypeLoc<ArrayTypeLoc, |
1638 | VariableArrayTypeLoc, |
1639 | VariableArrayType> { |
1640 | }; |
1641 | |
1642 | // Location information for a TemplateName. Rudimentary for now. |
1643 | struct TemplateNameLocInfo { |
1644 | SourceLocation NameLoc; |
1645 | }; |
1646 | |
1647 | struct TemplateSpecializationLocInfo : TemplateNameLocInfo { |
1648 | SourceLocation TemplateKWLoc; |
1649 | SourceLocation LAngleLoc; |
1650 | SourceLocation RAngleLoc; |
1651 | }; |
1652 | |
1653 | class TemplateSpecializationTypeLoc : |
1654 | public ConcreteTypeLoc<UnqualTypeLoc, |
1655 | TemplateSpecializationTypeLoc, |
1656 | TemplateSpecializationType, |
1657 | TemplateSpecializationLocInfo> { |
1658 | public: |
1659 | SourceLocation getTemplateKeywordLoc() const { |
1660 | return getLocalData()->TemplateKWLoc; |
1661 | } |
1662 | |
1663 | void setTemplateKeywordLoc(SourceLocation Loc) { |
1664 | getLocalData()->TemplateKWLoc = Loc; |
1665 | } |
1666 | |
1667 | SourceLocation getLAngleLoc() const { |
1668 | return getLocalData()->LAngleLoc; |
1669 | } |
1670 | |
1671 | void setLAngleLoc(SourceLocation Loc) { |
1672 | getLocalData()->LAngleLoc = Loc; |
1673 | } |
1674 | |
1675 | SourceLocation getRAngleLoc() const { |
1676 | return getLocalData()->RAngleLoc; |
1677 | } |
1678 | |
1679 | void setRAngleLoc(SourceLocation Loc) { |
1680 | getLocalData()->RAngleLoc = Loc; |
1681 | } |
1682 | |
1683 | unsigned getNumArgs() const { |
1684 | return getTypePtr()->template_arguments().size(); |
1685 | } |
1686 | |
1687 | void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { |
1688 | getArgInfos()[i] = AI; |
1689 | } |
1690 | |
1691 | TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { |
1692 | return getArgInfos()[i]; |
1693 | } |
1694 | |
1695 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
1696 | return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], |
1697 | getArgLocInfo(i)); |
1698 | } |
1699 | |
1700 | SourceLocation getTemplateNameLoc() const { |
1701 | return getLocalData()->NameLoc; |
1702 | } |
1703 | |
1704 | void setTemplateNameLoc(SourceLocation Loc) { |
1705 | getLocalData()->NameLoc = Loc; |
1706 | } |
1707 | |
1708 | /// - Copy the location information from the given info. |
1709 | void copy(TemplateSpecializationTypeLoc Loc) { |
1710 | unsigned size = getFullDataSize(); |
1711 | assert(size == Loc.getFullDataSize()); |
1712 | |
1713 | // We're potentially copying Expr references here. We don't |
1714 | // bother retaining them because TypeSourceInfos live forever, so |
1715 | // as long as the Expr was retained when originally written into |
1716 | // the TypeLoc, we're okay. |
1717 | memcpy(Data, Loc.Data, size); |
1718 | } |
1719 | |
1720 | SourceRange getLocalSourceRange() const { |
1721 | if (getTemplateKeywordLoc().isValid()) |
1722 | return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); |
1723 | else |
1724 | return SourceRange(getTemplateNameLoc(), getRAngleLoc()); |
1725 | } |
1726 | |
1727 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1728 | setTemplateKeywordLoc(SourceLocation()); |
1729 | setTemplateNameLoc(Loc); |
1730 | setLAngleLoc(Loc); |
1731 | setRAngleLoc(Loc); |
1732 | initializeArgLocs(Context, Args: getTypePtr()->template_arguments(), |
1733 | ArgInfos: getArgInfos(), Loc); |
1734 | } |
1735 | |
1736 | static void initializeArgLocs(ASTContext &Context, |
1737 | ArrayRef<TemplateArgument> Args, |
1738 | TemplateArgumentLocInfo *ArgInfos, |
1739 | SourceLocation Loc); |
1740 | |
1741 | unsigned () const { |
1742 | return getNumArgs() * sizeof(TemplateArgumentLocInfo); |
1743 | } |
1744 | |
1745 | unsigned () const { |
1746 | return alignof(TemplateArgumentLocInfo); |
1747 | } |
1748 | |
1749 | private: |
1750 | TemplateArgumentLocInfo *getArgInfos() const { |
1751 | return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
1752 | } |
1753 | }; |
1754 | |
1755 | struct DependentAddressSpaceLocInfo { |
1756 | Expr *ExprOperand; |
1757 | SourceRange OperandParens; |
1758 | SourceLocation AttrLoc; |
1759 | }; |
1760 | |
1761 | class DependentAddressSpaceTypeLoc |
1762 | : public ConcreteTypeLoc<UnqualTypeLoc, |
1763 | DependentAddressSpaceTypeLoc, |
1764 | DependentAddressSpaceType, |
1765 | DependentAddressSpaceLocInfo> { |
1766 | public: |
1767 | /// The location of the attribute name, i.e. |
1768 | /// int * __attribute__((address_space(11))) |
1769 | /// ^~~~~~~~~~~~~ |
1770 | SourceLocation getAttrNameLoc() const { |
1771 | return getLocalData()->AttrLoc; |
1772 | } |
1773 | void setAttrNameLoc(SourceLocation loc) { |
1774 | getLocalData()->AttrLoc = loc; |
1775 | } |
1776 | |
1777 | /// The attribute's expression operand, if it has one. |
1778 | /// int * __attribute__((address_space(11))) |
1779 | /// ^~ |
1780 | Expr *getAttrExprOperand() const { |
1781 | return getLocalData()->ExprOperand; |
1782 | } |
1783 | void setAttrExprOperand(Expr *e) { |
1784 | getLocalData()->ExprOperand = e; |
1785 | } |
1786 | |
1787 | /// The location of the parentheses around the operand, if there is |
1788 | /// an operand. |
1789 | /// int * __attribute__((address_space(11))) |
1790 | /// ^ ^ |
1791 | SourceRange getAttrOperandParensRange() const { |
1792 | return getLocalData()->OperandParens; |
1793 | } |
1794 | void setAttrOperandParensRange(SourceRange range) { |
1795 | getLocalData()->OperandParens = range; |
1796 | } |
1797 | |
1798 | SourceRange getLocalSourceRange() const { |
1799 | SourceRange range(getAttrNameLoc()); |
1800 | range.setEnd(getAttrOperandParensRange().getEnd()); |
1801 | return range; |
1802 | } |
1803 | |
1804 | /// Returns the type before the address space attribute application |
1805 | /// area. |
1806 | /// int * __attribute__((address_space(11))) * |
1807 | /// ^ ^ |
1808 | QualType getInnerType() const { |
1809 | return this->getTypePtr()->getPointeeType(); |
1810 | } |
1811 | |
1812 | TypeLoc getPointeeTypeLoc() const { |
1813 | return this->getInnerTypeLoc(); |
1814 | } |
1815 | |
1816 | void initializeLocal(ASTContext &Context, SourceLocation loc) { |
1817 | setAttrNameLoc(loc); |
1818 | setAttrOperandParensRange(loc); |
1819 | setAttrOperandParensRange(SourceRange(loc)); |
1820 | setAttrExprOperand(getTypePtr()->getAddrSpaceExpr()); |
1821 | } |
1822 | }; |
1823 | |
1824 | //===----------------------------------------------------------------------===// |
1825 | // |
1826 | // All of these need proper implementations. |
1827 | // |
1828 | //===----------------------------------------------------------------------===// |
1829 | |
1830 | // FIXME: size expression and attribute locations (or keyword if we |
1831 | // ever fully support altivec syntax). |
1832 | struct VectorTypeLocInfo { |
1833 | SourceLocation NameLoc; |
1834 | }; |
1835 | |
1836 | class VectorTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, VectorTypeLoc, |
1837 | VectorType, VectorTypeLocInfo> { |
1838 | public: |
1839 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1840 | |
1841 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1842 | |
1843 | SourceRange getLocalSourceRange() const { |
1844 | return SourceRange(getNameLoc(), getNameLoc()); |
1845 | } |
1846 | |
1847 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1848 | setNameLoc(Loc); |
1849 | } |
1850 | |
1851 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1852 | |
1853 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1854 | }; |
1855 | |
1856 | // FIXME: size expression and attribute locations (or keyword if we |
1857 | // ever fully support altivec syntax). |
1858 | class DependentVectorTypeLoc |
1859 | : public ConcreteTypeLoc<UnqualTypeLoc, DependentVectorTypeLoc, |
1860 | DependentVectorType, VectorTypeLocInfo> { |
1861 | public: |
1862 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1863 | |
1864 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1865 | |
1866 | SourceRange getLocalSourceRange() const { |
1867 | return SourceRange(getNameLoc(), getNameLoc()); |
1868 | } |
1869 | |
1870 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1871 | setNameLoc(Loc); |
1872 | } |
1873 | |
1874 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1875 | |
1876 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1877 | }; |
1878 | |
1879 | // FIXME: size expression and attribute locations. |
1880 | class ExtVectorTypeLoc |
1881 | : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc, |
1882 | ExtVectorType> {}; |
1883 | |
1884 | // FIXME: attribute locations. |
1885 | // For some reason, this isn't a subtype of VectorType. |
1886 | class DependentSizedExtVectorTypeLoc |
1887 | : public ConcreteTypeLoc<UnqualTypeLoc, DependentSizedExtVectorTypeLoc, |
1888 | DependentSizedExtVectorType, VectorTypeLocInfo> { |
1889 | public: |
1890 | SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } |
1891 | |
1892 | void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } |
1893 | |
1894 | SourceRange getLocalSourceRange() const { |
1895 | return SourceRange(getNameLoc(), getNameLoc()); |
1896 | } |
1897 | |
1898 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
1899 | setNameLoc(Loc); |
1900 | } |
1901 | |
1902 | TypeLoc getElementLoc() const { return getInnerTypeLoc(); } |
1903 | |
1904 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
1905 | }; |
1906 | |
1907 | struct MatrixTypeLocInfo { |
1908 | SourceLocation AttrLoc; |
1909 | SourceRange OperandParens; |
1910 | Expr *RowOperand; |
1911 | Expr *ColumnOperand; |
1912 | }; |
1913 | |
1914 | class MatrixTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, MatrixTypeLoc, |
1915 | MatrixType, MatrixTypeLocInfo> { |
1916 | public: |
1917 | /// The location of the attribute name, i.e. |
1918 | /// float __attribute__((matrix_type(4, 2))) |
1919 | /// ^~~~~~~~~~~~~~~~~ |
1920 | SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; } |
1921 | void setAttrNameLoc(SourceLocation loc) { getLocalData()->AttrLoc = loc; } |
1922 | |
1923 | /// The attribute's row operand, if it has one. |
1924 | /// float __attribute__((matrix_type(4, 2))) |
1925 | /// ^ |
1926 | Expr *getAttrRowOperand() const { return getLocalData()->RowOperand; } |
1927 | void setAttrRowOperand(Expr *e) { getLocalData()->RowOperand = e; } |
1928 | |
1929 | /// The attribute's column operand, if it has one. |
1930 | /// float __attribute__((matrix_type(4, 2))) |
1931 | /// ^ |
1932 | Expr *getAttrColumnOperand() const { return getLocalData()->ColumnOperand; } |
1933 | void setAttrColumnOperand(Expr *e) { getLocalData()->ColumnOperand = e; } |
1934 | |
1935 | /// The location of the parentheses around the operand, if there is |
1936 | /// an operand. |
1937 | /// float __attribute__((matrix_type(4, 2))) |
1938 | /// ^ ^ |
1939 | SourceRange getAttrOperandParensRange() const { |
1940 | return getLocalData()->OperandParens; |
1941 | } |
1942 | void setAttrOperandParensRange(SourceRange range) { |
1943 | getLocalData()->OperandParens = range; |
1944 | } |
1945 | |
1946 | SourceRange getLocalSourceRange() const { |
1947 | SourceRange range(getAttrNameLoc()); |
1948 | range.setEnd(getAttrOperandParensRange().getEnd()); |
1949 | return range; |
1950 | } |
1951 | |
1952 | void initializeLocal(ASTContext &Context, SourceLocation loc) { |
1953 | setAttrNameLoc(loc); |
1954 | setAttrOperandParensRange(loc); |
1955 | setAttrRowOperand(nullptr); |
1956 | setAttrColumnOperand(nullptr); |
1957 | } |
1958 | }; |
1959 | |
1960 | class ConstantMatrixTypeLoc |
1961 | : public InheritingConcreteTypeLoc<MatrixTypeLoc, ConstantMatrixTypeLoc, |
1962 | ConstantMatrixType> {}; |
1963 | |
1964 | class DependentSizedMatrixTypeLoc |
1965 | : public InheritingConcreteTypeLoc<MatrixTypeLoc, |
1966 | DependentSizedMatrixTypeLoc, |
1967 | DependentSizedMatrixType> {}; |
1968 | |
1969 | // FIXME: location of the '_Complex' keyword. |
1970 | class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, |
1971 | ComplexTypeLoc, |
1972 | ComplexType> { |
1973 | }; |
1974 | |
1975 | struct TypeofLocInfo { |
1976 | SourceLocation TypeofLoc; |
1977 | SourceLocation LParenLoc; |
1978 | SourceLocation RParenLoc; |
1979 | }; |
1980 | |
1981 | struct TypeOfExprTypeLocInfo : public TypeofLocInfo { |
1982 | }; |
1983 | |
1984 | struct TypeOfTypeLocInfo : public TypeofLocInfo { |
1985 | TypeSourceInfo *UnmodifiedTInfo; |
1986 | }; |
1987 | |
1988 | template <class Derived, class TypeClass, class LocalData = TypeofLocInfo> |
1989 | class TypeofLikeTypeLoc |
1990 | : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { |
1991 | public: |
1992 | SourceLocation getTypeofLoc() const { |
1993 | return this->getLocalData()->TypeofLoc; |
1994 | } |
1995 | |
1996 | void setTypeofLoc(SourceLocation Loc) { |
1997 | this->getLocalData()->TypeofLoc = Loc; |
1998 | } |
1999 | |
2000 | SourceLocation getLParenLoc() const { |
2001 | return this->getLocalData()->LParenLoc; |
2002 | } |
2003 | |
2004 | void setLParenLoc(SourceLocation Loc) { |
2005 | this->getLocalData()->LParenLoc = Loc; |
2006 | } |
2007 | |
2008 | SourceLocation getRParenLoc() const { |
2009 | return this->getLocalData()->RParenLoc; |
2010 | } |
2011 | |
2012 | void setRParenLoc(SourceLocation Loc) { |
2013 | this->getLocalData()->RParenLoc = Loc; |
2014 | } |
2015 | |
2016 | SourceRange getParensRange() const { |
2017 | return SourceRange(getLParenLoc(), getRParenLoc()); |
2018 | } |
2019 | |
2020 | void setParensRange(SourceRange range) { |
2021 | setLParenLoc(range.getBegin()); |
2022 | setRParenLoc(range.getEnd()); |
2023 | } |
2024 | |
2025 | SourceRange getLocalSourceRange() const { |
2026 | return SourceRange(getTypeofLoc(), getRParenLoc()); |
2027 | } |
2028 | |
2029 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2030 | setTypeofLoc(Loc); |
2031 | setLParenLoc(Loc); |
2032 | setRParenLoc(Loc); |
2033 | } |
2034 | }; |
2035 | |
2036 | class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc, |
2037 | TypeOfExprType, |
2038 | TypeOfExprTypeLocInfo> { |
2039 | public: |
2040 | Expr* getUnderlyingExpr() const { |
2041 | return getTypePtr()->getUnderlyingExpr(); |
2042 | } |
2043 | |
2044 | // Reimplemented to account for GNU/C++ extension |
2045 | // typeof unary-expression |
2046 | // where there are no parentheses. |
2047 | SourceRange getLocalSourceRange() const; |
2048 | }; |
2049 | |
2050 | class TypeOfTypeLoc |
2051 | : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> { |
2052 | public: |
2053 | QualType getUnmodifiedType() const { |
2054 | return this->getTypePtr()->getUnmodifiedType(); |
2055 | } |
2056 | |
2057 | TypeSourceInfo *getUnmodifiedTInfo() const { |
2058 | return this->getLocalData()->UnmodifiedTInfo; |
2059 | } |
2060 | |
2061 | void setUnmodifiedTInfo(TypeSourceInfo *TI) const { |
2062 | this->getLocalData()->UnmodifiedTInfo = TI; |
2063 | } |
2064 | |
2065 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2066 | }; |
2067 | |
2068 | // decltype(expression) abc; |
2069 | // ~~~~~~~~ DecltypeLoc |
2070 | // ~ RParenLoc |
2071 | // FIXME: add LParenLoc, it is tricky to support due to the limitation of |
2072 | // annotated-decltype token. |
2073 | struct DecltypeTypeLocInfo { |
2074 | SourceLocation DecltypeLoc; |
2075 | SourceLocation RParenLoc; |
2076 | }; |
2077 | class DecltypeTypeLoc |
2078 | : public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType, |
2079 | DecltypeTypeLocInfo> { |
2080 | public: |
2081 | Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } |
2082 | |
2083 | SourceLocation getDecltypeLoc() const { return getLocalData()->DecltypeLoc; } |
2084 | void setDecltypeLoc(SourceLocation Loc) { getLocalData()->DecltypeLoc = Loc; } |
2085 | |
2086 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2087 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2088 | |
2089 | SourceRange getLocalSourceRange() const { |
2090 | return SourceRange(getDecltypeLoc(), getRParenLoc()); |
2091 | } |
2092 | |
2093 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2094 | setDecltypeLoc(Loc); |
2095 | setRParenLoc(Loc); |
2096 | } |
2097 | }; |
2098 | |
2099 | struct PackIndexingTypeLocInfo { |
2100 | SourceLocation EllipsisLoc; |
2101 | }; |
2102 | |
2103 | class PackIndexingTypeLoc |
2104 | : public ConcreteTypeLoc<UnqualTypeLoc, PackIndexingTypeLoc, |
2105 | PackIndexingType, PackIndexingTypeLocInfo> { |
2106 | |
2107 | public: |
2108 | Expr *getIndexExpr() const { return getTypePtr()->getIndexExpr(); } |
2109 | QualType getPattern() const { return getTypePtr()->getPattern(); } |
2110 | |
2111 | SourceLocation getEllipsisLoc() const { return getLocalData()->EllipsisLoc; } |
2112 | void setEllipsisLoc(SourceLocation Loc) { getLocalData()->EllipsisLoc = Loc; } |
2113 | |
2114 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2115 | setEllipsisLoc(Loc); |
2116 | } |
2117 | |
2118 | TypeLoc getPatternLoc() const { return getInnerTypeLoc(); } |
2119 | |
2120 | QualType getInnerType() const { return this->getTypePtr()->getPattern(); } |
2121 | |
2122 | SourceRange getLocalSourceRange() const { |
2123 | return SourceRange(getEllipsisLoc(), getEllipsisLoc()); |
2124 | } |
2125 | }; |
2126 | |
2127 | struct UnaryTransformTypeLocInfo { |
2128 | // FIXME: While there's only one unary transform right now, future ones may |
2129 | // need different representations |
2130 | SourceLocation KWLoc, LParenLoc, RParenLoc; |
2131 | TypeSourceInfo *UnderlyingTInfo; |
2132 | }; |
2133 | |
2134 | class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2135 | UnaryTransformTypeLoc, |
2136 | UnaryTransformType, |
2137 | UnaryTransformTypeLocInfo> { |
2138 | public: |
2139 | SourceLocation getKWLoc() const { return getLocalData()->KWLoc; } |
2140 | void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; } |
2141 | |
2142 | SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; } |
2143 | void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; } |
2144 | |
2145 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2146 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2147 | |
2148 | TypeSourceInfo* getUnderlyingTInfo() const { |
2149 | return getLocalData()->UnderlyingTInfo; |
2150 | } |
2151 | |
2152 | void setUnderlyingTInfo(TypeSourceInfo *TInfo) { |
2153 | getLocalData()->UnderlyingTInfo = TInfo; |
2154 | } |
2155 | |
2156 | SourceRange getLocalSourceRange() const { |
2157 | return SourceRange(getKWLoc(), getRParenLoc()); |
2158 | } |
2159 | |
2160 | SourceRange getParensRange() const { |
2161 | return SourceRange(getLParenLoc(), getRParenLoc()); |
2162 | } |
2163 | |
2164 | void setParensRange(SourceRange Range) { |
2165 | setLParenLoc(Range.getBegin()); |
2166 | setRParenLoc(Range.getEnd()); |
2167 | } |
2168 | |
2169 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2170 | }; |
2171 | |
2172 | class DeducedTypeLoc |
2173 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc, |
2174 | DeducedType> {}; |
2175 | |
2176 | struct AutoTypeLocInfo : TypeSpecLocInfo { |
2177 | // For decltype(auto). |
2178 | SourceLocation RParenLoc; |
2179 | |
2180 | ConceptReference *CR = nullptr; |
2181 | }; |
2182 | |
2183 | class AutoTypeLoc |
2184 | : public ConcreteTypeLoc<DeducedTypeLoc, |
2185 | AutoTypeLoc, |
2186 | AutoType, |
2187 | AutoTypeLocInfo> { |
2188 | public: |
2189 | AutoTypeKeyword getAutoKeyword() const { |
2190 | return getTypePtr()->getKeyword(); |
2191 | } |
2192 | |
2193 | bool isDecltypeAuto() const { return getTypePtr()->isDecltypeAuto(); } |
2194 | SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } |
2195 | void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } |
2196 | |
2197 | bool isConstrained() const { |
2198 | return getTypePtr()->isConstrained(); |
2199 | } |
2200 | |
2201 | void setConceptReference(ConceptReference *CR) { getLocalData()->CR = CR; } |
2202 | |
2203 | ConceptReference *getConceptReference() const { return getLocalData()->CR; } |
2204 | |
2205 | // FIXME: Several of the following functions can be removed. Instead the |
2206 | // caller can directly work with the ConceptReference. |
2207 | const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const { |
2208 | if (const auto *CR = getConceptReference()) |
2209 | return CR->getNestedNameSpecifierLoc(); |
2210 | return NestedNameSpecifierLoc(); |
2211 | } |
2212 | |
2213 | SourceLocation getTemplateKWLoc() const { |
2214 | if (const auto *CR = getConceptReference()) |
2215 | return CR->getTemplateKWLoc(); |
2216 | return SourceLocation(); |
2217 | } |
2218 | |
2219 | SourceLocation getConceptNameLoc() const { |
2220 | if (const auto *CR = getConceptReference()) |
2221 | return CR->getConceptNameLoc(); |
2222 | return SourceLocation(); |
2223 | } |
2224 | |
2225 | NamedDecl *getFoundDecl() const { |
2226 | if (const auto *CR = getConceptReference()) |
2227 | return CR->getFoundDecl(); |
2228 | return nullptr; |
2229 | } |
2230 | |
2231 | ConceptDecl *getNamedConcept() const { |
2232 | if (const auto *CR = getConceptReference()) |
2233 | return CR->getNamedConcept(); |
2234 | return nullptr; |
2235 | } |
2236 | |
2237 | DeclarationNameInfo getConceptNameInfo() const { |
2238 | return getConceptReference()->getConceptNameInfo(); |
2239 | } |
2240 | |
2241 | bool hasExplicitTemplateArgs() const { |
2242 | return (getConceptReference() && |
2243 | getConceptReference()->getTemplateArgsAsWritten() && |
2244 | getConceptReference() |
2245 | ->getTemplateArgsAsWritten() |
2246 | ->getLAngleLoc() |
2247 | .isValid()); |
2248 | } |
2249 | |
2250 | SourceLocation getLAngleLoc() const { |
2251 | if (const auto *CR = getConceptReference()) |
2252 | if (const auto *TAAW = CR->getTemplateArgsAsWritten()) |
2253 | return TAAW->getLAngleLoc(); |
2254 | return SourceLocation(); |
2255 | } |
2256 | |
2257 | SourceLocation getRAngleLoc() const { |
2258 | if (const auto *CR = getConceptReference()) |
2259 | if (const auto *TAAW = CR->getTemplateArgsAsWritten()) |
2260 | return TAAW->getRAngleLoc(); |
2261 | return SourceLocation(); |
2262 | } |
2263 | |
2264 | unsigned getNumArgs() const { |
2265 | return getTypePtr()->getTypeConstraintArguments().size(); |
2266 | } |
2267 | |
2268 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
2269 | const auto *CR = getConceptReference(); |
2270 | assert(CR && "No ConceptReference" ); |
2271 | return CR->getTemplateArgsAsWritten()->getTemplateArgs()[i]; |
2272 | } |
2273 | |
2274 | SourceRange getLocalSourceRange() const { |
2275 | return {isConstrained() |
2276 | ? (getNestedNameSpecifierLoc() |
2277 | ? getNestedNameSpecifierLoc().getBeginLoc() |
2278 | : (getTemplateKWLoc().isValid() ? getTemplateKWLoc() |
2279 | : getConceptNameLoc())) |
2280 | : getNameLoc(), |
2281 | isDecltypeAuto() ? getRParenLoc() : getNameLoc()}; |
2282 | } |
2283 | |
2284 | void copy(AutoTypeLoc Loc) { |
2285 | unsigned size = getFullDataSize(); |
2286 | assert(size == Loc.getFullDataSize()); |
2287 | memcpy(Data, Loc.Data, size); |
2288 | } |
2289 | |
2290 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2291 | }; |
2292 | |
2293 | class DeducedTemplateSpecializationTypeLoc |
2294 | : public InheritingConcreteTypeLoc<DeducedTypeLoc, |
2295 | DeducedTemplateSpecializationTypeLoc, |
2296 | DeducedTemplateSpecializationType> { |
2297 | public: |
2298 | SourceLocation getTemplateNameLoc() const { |
2299 | return getNameLoc(); |
2300 | } |
2301 | |
2302 | void setTemplateNameLoc(SourceLocation Loc) { |
2303 | setNameLoc(Loc); |
2304 | } |
2305 | }; |
2306 | |
2307 | struct ElaboratedLocInfo { |
2308 | SourceLocation ElaboratedKWLoc; |
2309 | |
2310 | /// Data associated with the nested-name-specifier location. |
2311 | void *QualifierData; |
2312 | }; |
2313 | |
2314 | class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2315 | ElaboratedTypeLoc, |
2316 | ElaboratedType, |
2317 | ElaboratedLocInfo> { |
2318 | public: |
2319 | SourceLocation getElaboratedKeywordLoc() const { |
2320 | return !isEmpty() ? getLocalData()->ElaboratedKWLoc : SourceLocation(); |
2321 | } |
2322 | |
2323 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2324 | if (isEmpty()) { |
2325 | assert(Loc.isInvalid()); |
2326 | return; |
2327 | } |
2328 | getLocalData()->ElaboratedKWLoc = Loc; |
2329 | } |
2330 | |
2331 | NestedNameSpecifierLoc getQualifierLoc() const { |
2332 | return !isEmpty() ? NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2333 | getLocalData()->QualifierData) |
2334 | : NestedNameSpecifierLoc(); |
2335 | } |
2336 | |
2337 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2338 | assert(QualifierLoc.getNestedNameSpecifier() == |
2339 | getTypePtr()->getQualifier() && |
2340 | "Inconsistent nested-name-specifier pointer" ); |
2341 | if (isEmpty()) { |
2342 | assert(!QualifierLoc.hasQualifier()); |
2343 | return; |
2344 | } |
2345 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2346 | } |
2347 | |
2348 | SourceRange getLocalSourceRange() const { |
2349 | if (getElaboratedKeywordLoc().isValid()) |
2350 | if (getQualifierLoc()) |
2351 | return SourceRange(getElaboratedKeywordLoc(), |
2352 | getQualifierLoc().getEndLoc()); |
2353 | else |
2354 | return SourceRange(getElaboratedKeywordLoc()); |
2355 | else |
2356 | return getQualifierLoc().getSourceRange(); |
2357 | } |
2358 | |
2359 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2360 | |
2361 | TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); } |
2362 | |
2363 | QualType getInnerType() const { return getTypePtr()->getNamedType(); } |
2364 | |
2365 | bool isEmpty() const { |
2366 | return getTypePtr()->getKeyword() == ElaboratedTypeKeyword::None && |
2367 | !getTypePtr()->getQualifier(); |
2368 | } |
2369 | |
2370 | unsigned getLocalDataAlignment() const { |
2371 | // FIXME: We want to return 1 here in the empty case, but |
2372 | // there are bugs in how alignment is handled in TypeLocs |
2373 | // that prevent this from working. |
2374 | return ConcreteTypeLoc::getLocalDataAlignment(); |
2375 | } |
2376 | |
2377 | unsigned getLocalDataSize() const { |
2378 | return !isEmpty() ? ConcreteTypeLoc::getLocalDataSize() : 0; |
2379 | } |
2380 | |
2381 | void copy(ElaboratedTypeLoc Loc) { |
2382 | unsigned size = getFullDataSize(); |
2383 | assert(size == Loc.getFullDataSize()); |
2384 | memcpy(Data, Loc.Data, size); |
2385 | } |
2386 | }; |
2387 | |
2388 | // This is exactly the structure of an ElaboratedTypeLoc whose inner |
2389 | // type is some sort of TypeDeclTypeLoc. |
2390 | struct DependentNameLocInfo : ElaboratedLocInfo { |
2391 | SourceLocation NameLoc; |
2392 | }; |
2393 | |
2394 | class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, |
2395 | DependentNameTypeLoc, |
2396 | DependentNameType, |
2397 | DependentNameLocInfo> { |
2398 | public: |
2399 | SourceLocation getElaboratedKeywordLoc() const { |
2400 | return this->getLocalData()->ElaboratedKWLoc; |
2401 | } |
2402 | |
2403 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2404 | this->getLocalData()->ElaboratedKWLoc = Loc; |
2405 | } |
2406 | |
2407 | NestedNameSpecifierLoc getQualifierLoc() const { |
2408 | return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2409 | getLocalData()->QualifierData); |
2410 | } |
2411 | |
2412 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2413 | assert(QualifierLoc.getNestedNameSpecifier() |
2414 | == getTypePtr()->getQualifier() && |
2415 | "Inconsistent nested-name-specifier pointer" ); |
2416 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2417 | } |
2418 | |
2419 | SourceLocation getNameLoc() const { |
2420 | return this->getLocalData()->NameLoc; |
2421 | } |
2422 | |
2423 | void setNameLoc(SourceLocation Loc) { |
2424 | this->getLocalData()->NameLoc = Loc; |
2425 | } |
2426 | |
2427 | SourceRange getLocalSourceRange() const { |
2428 | if (getElaboratedKeywordLoc().isValid()) |
2429 | return SourceRange(getElaboratedKeywordLoc(), getNameLoc()); |
2430 | else |
2431 | return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); |
2432 | } |
2433 | |
2434 | void copy(DependentNameTypeLoc Loc) { |
2435 | unsigned size = getFullDataSize(); |
2436 | assert(size == Loc.getFullDataSize()); |
2437 | memcpy(Data, Loc.Data, size); |
2438 | } |
2439 | |
2440 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2441 | }; |
2442 | |
2443 | struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { |
2444 | SourceLocation TemplateKWLoc; |
2445 | SourceLocation LAngleLoc; |
2446 | SourceLocation RAngleLoc; |
2447 | // followed by a TemplateArgumentLocInfo[] |
2448 | }; |
2449 | |
2450 | class DependentTemplateSpecializationTypeLoc : |
2451 | public ConcreteTypeLoc<UnqualTypeLoc, |
2452 | DependentTemplateSpecializationTypeLoc, |
2453 | DependentTemplateSpecializationType, |
2454 | DependentTemplateSpecializationLocInfo> { |
2455 | public: |
2456 | SourceLocation getElaboratedKeywordLoc() const { |
2457 | return this->getLocalData()->ElaboratedKWLoc; |
2458 | } |
2459 | |
2460 | void setElaboratedKeywordLoc(SourceLocation Loc) { |
2461 | this->getLocalData()->ElaboratedKWLoc = Loc; |
2462 | } |
2463 | |
2464 | NestedNameSpecifierLoc getQualifierLoc() const { |
2465 | if (!getLocalData()->QualifierData) |
2466 | return NestedNameSpecifierLoc(); |
2467 | |
2468 | return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), |
2469 | getLocalData()->QualifierData); |
2470 | } |
2471 | |
2472 | void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { |
2473 | if (!QualifierLoc) { |
2474 | // Even if we have a nested-name-specifier in the dependent |
2475 | // template specialization type, we won't record the nested-name-specifier |
2476 | // location information when this type-source location information is |
2477 | // part of a nested-name-specifier. |
2478 | getLocalData()->QualifierData = nullptr; |
2479 | return; |
2480 | } |
2481 | |
2482 | assert(QualifierLoc.getNestedNameSpecifier() |
2483 | == getTypePtr()->getQualifier() && |
2484 | "Inconsistent nested-name-specifier pointer" ); |
2485 | getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); |
2486 | } |
2487 | |
2488 | SourceLocation getTemplateKeywordLoc() const { |
2489 | return getLocalData()->TemplateKWLoc; |
2490 | } |
2491 | |
2492 | void setTemplateKeywordLoc(SourceLocation Loc) { |
2493 | getLocalData()->TemplateKWLoc = Loc; |
2494 | } |
2495 | |
2496 | SourceLocation getTemplateNameLoc() const { |
2497 | return this->getLocalData()->NameLoc; |
2498 | } |
2499 | |
2500 | void setTemplateNameLoc(SourceLocation Loc) { |
2501 | this->getLocalData()->NameLoc = Loc; |
2502 | } |
2503 | |
2504 | SourceLocation getLAngleLoc() const { |
2505 | return this->getLocalData()->LAngleLoc; |
2506 | } |
2507 | |
2508 | void setLAngleLoc(SourceLocation Loc) { |
2509 | this->getLocalData()->LAngleLoc = Loc; |
2510 | } |
2511 | |
2512 | SourceLocation getRAngleLoc() const { |
2513 | return this->getLocalData()->RAngleLoc; |
2514 | } |
2515 | |
2516 | void setRAngleLoc(SourceLocation Loc) { |
2517 | this->getLocalData()->RAngleLoc = Loc; |
2518 | } |
2519 | |
2520 | unsigned getNumArgs() const { |
2521 | return getTypePtr()->template_arguments().size(); |
2522 | } |
2523 | |
2524 | void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { |
2525 | getArgInfos()[i] = AI; |
2526 | } |
2527 | |
2528 | TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { |
2529 | return getArgInfos()[i]; |
2530 | } |
2531 | |
2532 | TemplateArgumentLoc getArgLoc(unsigned i) const { |
2533 | return TemplateArgumentLoc(getTypePtr()->template_arguments()[i], |
2534 | getArgLocInfo(i)); |
2535 | } |
2536 | |
2537 | SourceRange getLocalSourceRange() const { |
2538 | if (getElaboratedKeywordLoc().isValid()) |
2539 | return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc()); |
2540 | else if (getQualifierLoc()) |
2541 | return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); |
2542 | else if (getTemplateKeywordLoc().isValid()) |
2543 | return SourceRange(getTemplateKeywordLoc(), getRAngleLoc()); |
2544 | else |
2545 | return SourceRange(getTemplateNameLoc(), getRAngleLoc()); |
2546 | } |
2547 | |
2548 | void copy(DependentTemplateSpecializationTypeLoc Loc) { |
2549 | unsigned size = getFullDataSize(); |
2550 | assert(size == Loc.getFullDataSize()); |
2551 | memcpy(Data, Loc.Data, size); |
2552 | } |
2553 | |
2554 | void initializeLocal(ASTContext &Context, SourceLocation Loc); |
2555 | |
2556 | unsigned () const { |
2557 | return getNumArgs() * sizeof(TemplateArgumentLocInfo); |
2558 | } |
2559 | |
2560 | unsigned () const { |
2561 | return alignof(TemplateArgumentLocInfo); |
2562 | } |
2563 | |
2564 | private: |
2565 | TemplateArgumentLocInfo *getArgInfos() const { |
2566 | return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); |
2567 | } |
2568 | }; |
2569 | |
2570 | struct PackExpansionTypeLocInfo { |
2571 | SourceLocation EllipsisLoc; |
2572 | }; |
2573 | |
2574 | class PackExpansionTypeLoc |
2575 | : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc, |
2576 | PackExpansionType, PackExpansionTypeLocInfo> { |
2577 | public: |
2578 | SourceLocation getEllipsisLoc() const { |
2579 | return this->getLocalData()->EllipsisLoc; |
2580 | } |
2581 | |
2582 | void setEllipsisLoc(SourceLocation Loc) { |
2583 | this->getLocalData()->EllipsisLoc = Loc; |
2584 | } |
2585 | |
2586 | SourceRange getLocalSourceRange() const { |
2587 | return SourceRange(getEllipsisLoc(), getEllipsisLoc()); |
2588 | } |
2589 | |
2590 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2591 | setEllipsisLoc(Loc); |
2592 | } |
2593 | |
2594 | TypeLoc getPatternLoc() const { |
2595 | return getInnerTypeLoc(); |
2596 | } |
2597 | |
2598 | QualType getInnerType() const { |
2599 | return this->getTypePtr()->getPattern(); |
2600 | } |
2601 | }; |
2602 | |
2603 | struct AtomicTypeLocInfo { |
2604 | SourceLocation KWLoc, LParenLoc, RParenLoc; |
2605 | }; |
2606 | |
2607 | class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc, |
2608 | AtomicType, AtomicTypeLocInfo> { |
2609 | public: |
2610 | TypeLoc getValueLoc() const { |
2611 | return this->getInnerTypeLoc(); |
2612 | } |
2613 | |
2614 | SourceRange getLocalSourceRange() const { |
2615 | return SourceRange(getKWLoc(), getRParenLoc()); |
2616 | } |
2617 | |
2618 | SourceLocation getKWLoc() const { |
2619 | return this->getLocalData()->KWLoc; |
2620 | } |
2621 | |
2622 | void setKWLoc(SourceLocation Loc) { |
2623 | this->getLocalData()->KWLoc = Loc; |
2624 | } |
2625 | |
2626 | SourceLocation getLParenLoc() const { |
2627 | return this->getLocalData()->LParenLoc; |
2628 | } |
2629 | |
2630 | void setLParenLoc(SourceLocation Loc) { |
2631 | this->getLocalData()->LParenLoc = Loc; |
2632 | } |
2633 | |
2634 | SourceLocation getRParenLoc() const { |
2635 | return this->getLocalData()->RParenLoc; |
2636 | } |
2637 | |
2638 | void setRParenLoc(SourceLocation Loc) { |
2639 | this->getLocalData()->RParenLoc = Loc; |
2640 | } |
2641 | |
2642 | SourceRange getParensRange() const { |
2643 | return SourceRange(getLParenLoc(), getRParenLoc()); |
2644 | } |
2645 | |
2646 | void setParensRange(SourceRange Range) { |
2647 | setLParenLoc(Range.getBegin()); |
2648 | setRParenLoc(Range.getEnd()); |
2649 | } |
2650 | |
2651 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2652 | setKWLoc(Loc); |
2653 | setLParenLoc(Loc); |
2654 | setRParenLoc(Loc); |
2655 | } |
2656 | |
2657 | QualType getInnerType() const { |
2658 | return this->getTypePtr()->getValueType(); |
2659 | } |
2660 | }; |
2661 | |
2662 | struct PipeTypeLocInfo { |
2663 | SourceLocation KWLoc; |
2664 | }; |
2665 | |
2666 | class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType, |
2667 | PipeTypeLocInfo> { |
2668 | public: |
2669 | TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); } |
2670 | |
2671 | SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); } |
2672 | |
2673 | SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } |
2674 | void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } |
2675 | |
2676 | void initializeLocal(ASTContext &Context, SourceLocation Loc) { |
2677 | setKWLoc(Loc); |
2678 | } |
2679 | |
2680 | QualType getInnerType() const { return this->getTypePtr()->getElementType(); } |
2681 | }; |
2682 | |
2683 | template <typename T> |
2684 | inline T TypeLoc::getAsAdjusted() const { |
2685 | TypeLoc Cur = *this; |
2686 | while (!T::isKind(Cur)) { |
2687 | if (auto PTL = Cur.getAs<ParenTypeLoc>()) |
2688 | Cur = PTL.getInnerLoc(); |
2689 | else if (auto ATL = Cur.getAs<AttributedTypeLoc>()) |
2690 | Cur = ATL.getModifiedLoc(); |
2691 | else if (auto ATL = Cur.getAs<BTFTagAttributedTypeLoc>()) |
2692 | Cur = ATL.getWrappedLoc(); |
2693 | else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>()) |
2694 | Cur = ETL.getNamedTypeLoc(); |
2695 | else if (auto ATL = Cur.getAs<AdjustedTypeLoc>()) |
2696 | Cur = ATL.getOriginalLoc(); |
2697 | else if (auto MQL = Cur.getAs<MacroQualifiedTypeLoc>()) |
2698 | Cur = MQL.getInnerLoc(); |
2699 | else |
2700 | break; |
2701 | } |
2702 | return Cur.getAs<T>(); |
2703 | } |
2704 | class BitIntTypeLoc final |
2705 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, BitIntTypeLoc, |
2706 | BitIntType> {}; |
2707 | class DependentBitIntTypeLoc final |
2708 | : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc, |
2709 | DependentBitIntType> {}; |
2710 | |
2711 | class ObjCProtocolLoc { |
2712 | ObjCProtocolDecl *Protocol = nullptr; |
2713 | SourceLocation Loc = SourceLocation(); |
2714 | |
2715 | public: |
2716 | ObjCProtocolLoc(ObjCProtocolDecl *protocol, SourceLocation loc) |
2717 | : Protocol(protocol), Loc(loc) {} |
2718 | ObjCProtocolDecl *getProtocol() const { return Protocol; } |
2719 | SourceLocation getLocation() const { return Loc; } |
2720 | |
2721 | /// The source range is just the protocol name. |
2722 | SourceRange getSourceRange() const LLVM_READONLY { |
2723 | return SourceRange(Loc, Loc); |
2724 | } |
2725 | }; |
2726 | |
2727 | } // namespace clang |
2728 | |
2729 | #endif // LLVM_CLANG_AST_TYPELOC_H |
2730 | |