1 | //===- TypeLoc.cpp - Type Source Info Wrapper -----------------------------===// |
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 | // This file defines the TypeLoc subclasses implementations. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/AST/TypeLoc.h" |
14 | #include "clang/AST/ASTConcept.h" |
15 | #include "clang/AST/ASTContext.h" |
16 | #include "clang/AST/Attr.h" |
17 | #include "clang/AST/DeclTemplate.h" |
18 | #include "clang/AST/Expr.h" |
19 | #include "clang/AST/NestedNameSpecifier.h" |
20 | #include "clang/AST/TemplateBase.h" |
21 | #include "clang/AST/TemplateName.h" |
22 | #include "clang/AST/TypeLocVisitor.h" |
23 | #include "clang/Basic/SourceLocation.h" |
24 | #include "clang/Basic/Specifiers.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/MathExtras.h" |
27 | #include <algorithm> |
28 | #include <cassert> |
29 | #include <cstdint> |
30 | #include <cstring> |
31 | |
32 | using namespace clang; |
33 | |
34 | static const unsigned TypeLocMaxDataAlign = alignof(void *); |
35 | |
36 | //===----------------------------------------------------------------------===// |
37 | // TypeLoc Implementation |
38 | //===----------------------------------------------------------------------===// |
39 | |
40 | namespace { |
41 | |
42 | class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { |
43 | public: |
44 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
45 | #define TYPELOC(CLASS, PARENT) \ |
46 | SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ |
47 | return TyLoc.getLocalSourceRange(); \ |
48 | } |
49 | #include "clang/AST/TypeLocNodes.def" |
50 | }; |
51 | |
52 | } // namespace |
53 | |
54 | SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { |
55 | if (TL.isNull()) return SourceRange(); |
56 | return TypeLocRanger().Visit(TyLoc: TL); |
57 | } |
58 | |
59 | namespace { |
60 | |
61 | class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> { |
62 | public: |
63 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
64 | #define TYPELOC(CLASS, PARENT) \ |
65 | unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ |
66 | return TyLoc.getLocalDataAlignment(); \ |
67 | } |
68 | #include "clang/AST/TypeLocNodes.def" |
69 | }; |
70 | |
71 | } // namespace |
72 | |
73 | /// Returns the alignment of the type source info data block. |
74 | unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { |
75 | if (Ty.isNull()) return 1; |
76 | return TypeAligner().Visit(TyLoc: TypeLoc(Ty, nullptr)); |
77 | } |
78 | |
79 | namespace { |
80 | |
81 | class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { |
82 | public: |
83 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
84 | #define TYPELOC(CLASS, PARENT) \ |
85 | unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ |
86 | return TyLoc.getLocalDataSize(); \ |
87 | } |
88 | #include "clang/AST/TypeLocNodes.def" |
89 | }; |
90 | |
91 | } // namespace |
92 | |
93 | /// Returns the size of the type source info data block. |
94 | unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { |
95 | unsigned Total = 0; |
96 | TypeLoc TyLoc(Ty, nullptr); |
97 | unsigned MaxAlign = 1; |
98 | while (!TyLoc.isNull()) { |
99 | unsigned Align = getLocalAlignmentForType(Ty: TyLoc.getType()); |
100 | MaxAlign = std::max(Align, MaxAlign); |
101 | Total = llvm::alignTo(Value: Total, Align); |
102 | Total += TypeSizer().Visit(TyLoc); |
103 | TyLoc = TyLoc.getNextTypeLoc(); |
104 | } |
105 | Total = llvm::alignTo(Value: Total, Align: MaxAlign); |
106 | return Total; |
107 | } |
108 | |
109 | namespace { |
110 | |
111 | class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { |
112 | public: |
113 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
114 | #define TYPELOC(CLASS, PARENT) \ |
115 | TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ |
116 | return TyLoc.getNextTypeLoc(); \ |
117 | } |
118 | #include "clang/AST/TypeLocNodes.def" |
119 | }; |
120 | |
121 | } // namespace |
122 | |
123 | /// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the |
124 | /// TypeLoc is a PointerLoc and next TypeLoc is for "int". |
125 | TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { |
126 | return NextLoc().Visit(TyLoc: TL); |
127 | } |
128 | |
129 | /// Initializes a type location, and all of its children |
130 | /// recursively, as if the entire tree had been written in the |
131 | /// given location. |
132 | void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, |
133 | SourceLocation Loc) { |
134 | while (true) { |
135 | switch (TL.getTypeLocClass()) { |
136 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
137 | #define TYPELOC(CLASS, PARENT) \ |
138 | case CLASS: { \ |
139 | CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \ |
140 | TLCasted.initializeLocal(Context, Loc); \ |
141 | TL = TLCasted.getNextTypeLoc(); \ |
142 | if (!TL) return; \ |
143 | continue; \ |
144 | } |
145 | #include "clang/AST/TypeLocNodes.def" |
146 | } |
147 | } |
148 | } |
149 | |
150 | namespace { |
151 | |
152 | class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> { |
153 | TypeLoc Source; |
154 | |
155 | public: |
156 | TypeLocCopier(TypeLoc source) : Source(source) {} |
157 | |
158 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
159 | #define TYPELOC(CLASS, PARENT) \ |
160 | void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) { \ |
161 | dest.copyLocal(Source.castAs<CLASS##TypeLoc>()); \ |
162 | } |
163 | #include "clang/AST/TypeLocNodes.def" |
164 | }; |
165 | |
166 | } // namespace |
167 | |
168 | void TypeLoc::copy(TypeLoc other) { |
169 | assert(getFullDataSize() == other.getFullDataSize()); |
170 | |
171 | // If both data pointers are aligned to the maximum alignment, we |
172 | // can memcpy because getFullDataSize() accurately reflects the |
173 | // layout of the data. |
174 | if (reinterpret_cast<uintptr_t>(Data) == |
175 | llvm::alignTo(Value: reinterpret_cast<uintptr_t>(Data), |
176 | Align: TypeLocMaxDataAlign) && |
177 | reinterpret_cast<uintptr_t>(other.Data) == |
178 | llvm::alignTo(Value: reinterpret_cast<uintptr_t>(other.Data), |
179 | Align: TypeLocMaxDataAlign)) { |
180 | memcpy(dest: Data, src: other.Data, n: getFullDataSize()); |
181 | return; |
182 | } |
183 | |
184 | // Copy each of the pieces. |
185 | TypeLoc TL(getType(), Data); |
186 | do { |
187 | TypeLocCopier(other).Visit(TyLoc: TL); |
188 | other = other.getNextTypeLoc(); |
189 | } while ((TL = TL.getNextTypeLoc())); |
190 | } |
191 | |
192 | SourceLocation TypeLoc::getBeginLoc() const { |
193 | TypeLoc Cur = *this; |
194 | TypeLoc LeftMost = Cur; |
195 | while (true) { |
196 | switch (Cur.getTypeLocClass()) { |
197 | case Elaborated: |
198 | if (Cur.getLocalSourceRange().getBegin().isValid()) { |
199 | LeftMost = Cur; |
200 | break; |
201 | } |
202 | Cur = Cur.getNextTypeLoc(); |
203 | if (Cur.isNull()) |
204 | break; |
205 | continue; |
206 | case FunctionProto: |
207 | if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr() |
208 | ->hasTrailingReturn()) { |
209 | LeftMost = Cur; |
210 | break; |
211 | } |
212 | [[fallthrough]]; |
213 | case FunctionNoProto: |
214 | case ConstantArray: |
215 | case DependentSizedArray: |
216 | case IncompleteArray: |
217 | case VariableArray: |
218 | // FIXME: Currently QualifiedTypeLoc does not have a source range |
219 | case Qualified: |
220 | Cur = Cur.getNextTypeLoc(); |
221 | continue; |
222 | default: |
223 | if (Cur.getLocalSourceRange().getBegin().isValid()) |
224 | LeftMost = Cur; |
225 | Cur = Cur.getNextTypeLoc(); |
226 | if (Cur.isNull()) |
227 | break; |
228 | continue; |
229 | } // switch |
230 | break; |
231 | } // while |
232 | return LeftMost.getLocalSourceRange().getBegin(); |
233 | } |
234 | |
235 | SourceLocation TypeLoc::getEndLoc() const { |
236 | TypeLoc Cur = *this; |
237 | TypeLoc Last; |
238 | while (true) { |
239 | switch (Cur.getTypeLocClass()) { |
240 | default: |
241 | if (!Last) |
242 | Last = Cur; |
243 | return Last.getLocalSourceRange().getEnd(); |
244 | case Paren: |
245 | case ConstantArray: |
246 | case DependentSizedArray: |
247 | case IncompleteArray: |
248 | case VariableArray: |
249 | case FunctionNoProto: |
250 | // The innermost type with suffix syntax always determines the end of the |
251 | // type. |
252 | Last = Cur; |
253 | break; |
254 | case FunctionProto: |
255 | if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn()) |
256 | Last = TypeLoc(); |
257 | else |
258 | Last = Cur; |
259 | break; |
260 | case ObjCObjectPointer: |
261 | // `id` and `id<...>` have no star location. |
262 | if (Cur.castAs<ObjCObjectPointerTypeLoc>().getStarLoc().isInvalid()) |
263 | break; |
264 | [[fallthrough]]; |
265 | case Pointer: |
266 | case BlockPointer: |
267 | case MemberPointer: |
268 | case LValueReference: |
269 | case RValueReference: |
270 | case PackExpansion: |
271 | // Types with prefix syntax only determine the end of the type if there |
272 | // is no suffix type. |
273 | if (!Last) |
274 | Last = Cur; |
275 | break; |
276 | case Qualified: |
277 | case Elaborated: |
278 | break; |
279 | } |
280 | Cur = Cur.getNextTypeLoc(); |
281 | } |
282 | } |
283 | |
284 | namespace { |
285 | |
286 | struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { |
287 | // Overload resolution does the real work for us. |
288 | static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } |
289 | static bool isTypeSpec(TypeLoc _) { return false; } |
290 | |
291 | #define ABSTRACT_TYPELOC(CLASS, PARENT) |
292 | #define TYPELOC(CLASS, PARENT) \ |
293 | bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ |
294 | return isTypeSpec(TyLoc); \ |
295 | } |
296 | #include "clang/AST/TypeLocNodes.def" |
297 | }; |
298 | |
299 | } // namespace |
300 | |
301 | /// Determines if the given type loc corresponds to a |
302 | /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in |
303 | /// the type hierarchy, this is made somewhat complicated. |
304 | /// |
305 | /// There are a lot of types that currently use TypeSpecTypeLoc |
306 | /// because it's a convenient base class. Ideally we would not accept |
307 | /// those here, but ideally we would have better implementations for |
308 | /// them. |
309 | bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { |
310 | if (TL.getType().hasLocalQualifiers()) return false; |
311 | return TSTChecker().Visit(TyLoc: TL); |
312 | } |
313 | |
314 | bool TagTypeLoc::isDefinition() const { |
315 | TagDecl *D = getDecl(); |
316 | return D->isCompleteDefinition() && |
317 | (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); |
318 | } |
319 | |
320 | // Reimplemented to account for GNU/C++ extension |
321 | // typeof unary-expression |
322 | // where there are no parentheses. |
323 | SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { |
324 | if (getRParenLoc().isValid()) |
325 | return SourceRange(getTypeofLoc(), getRParenLoc()); |
326 | else |
327 | return SourceRange(getTypeofLoc(), |
328 | getUnderlyingExpr()->getSourceRange().getEnd()); |
329 | } |
330 | |
331 | |
332 | TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { |
333 | if (needsExtraLocalData()) |
334 | return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); |
335 | switch (getTypePtr()->getKind()) { |
336 | case BuiltinType::Void: |
337 | return TST_void; |
338 | case BuiltinType::Bool: |
339 | return TST_bool; |
340 | case BuiltinType::Char_U: |
341 | case BuiltinType::Char_S: |
342 | return TST_char; |
343 | case BuiltinType::Char8: |
344 | return TST_char8; |
345 | case BuiltinType::Char16: |
346 | return TST_char16; |
347 | case BuiltinType::Char32: |
348 | return TST_char32; |
349 | case BuiltinType::WChar_S: |
350 | case BuiltinType::WChar_U: |
351 | return TST_wchar; |
352 | case BuiltinType::UChar: |
353 | case BuiltinType::UShort: |
354 | case BuiltinType::UInt: |
355 | case BuiltinType::ULong: |
356 | case BuiltinType::ULongLong: |
357 | case BuiltinType::UInt128: |
358 | case BuiltinType::SChar: |
359 | case BuiltinType::Short: |
360 | case BuiltinType::Int: |
361 | case BuiltinType::Long: |
362 | case BuiltinType::LongLong: |
363 | case BuiltinType::Int128: |
364 | case BuiltinType::Half: |
365 | case BuiltinType::Float: |
366 | case BuiltinType::Double: |
367 | case BuiltinType::LongDouble: |
368 | case BuiltinType::Float16: |
369 | case BuiltinType::Float128: |
370 | case BuiltinType::Ibm128: |
371 | case BuiltinType::ShortAccum: |
372 | case BuiltinType::Accum: |
373 | case BuiltinType::LongAccum: |
374 | case BuiltinType::UShortAccum: |
375 | case BuiltinType::UAccum: |
376 | case BuiltinType::ULongAccum: |
377 | case BuiltinType::ShortFract: |
378 | case BuiltinType::Fract: |
379 | case BuiltinType::LongFract: |
380 | case BuiltinType::UShortFract: |
381 | case BuiltinType::UFract: |
382 | case BuiltinType::ULongFract: |
383 | case BuiltinType::SatShortAccum: |
384 | case BuiltinType::SatAccum: |
385 | case BuiltinType::SatLongAccum: |
386 | case BuiltinType::SatUShortAccum: |
387 | case BuiltinType::SatUAccum: |
388 | case BuiltinType::SatULongAccum: |
389 | case BuiltinType::SatShortFract: |
390 | case BuiltinType::SatFract: |
391 | case BuiltinType::SatLongFract: |
392 | case BuiltinType::SatUShortFract: |
393 | case BuiltinType::SatUFract: |
394 | case BuiltinType::SatULongFract: |
395 | case BuiltinType::BFloat16: |
396 | llvm_unreachable("Builtin type needs extra local data!" ); |
397 | // Fall through, if the impossible happens. |
398 | |
399 | case BuiltinType::NullPtr: |
400 | case BuiltinType::Overload: |
401 | case BuiltinType::Dependent: |
402 | case BuiltinType::BoundMember: |
403 | case BuiltinType::UnknownAny: |
404 | case BuiltinType::ARCUnbridgedCast: |
405 | case BuiltinType::PseudoObject: |
406 | case BuiltinType::ObjCId: |
407 | case BuiltinType::ObjCClass: |
408 | case BuiltinType::ObjCSel: |
409 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
410 | case BuiltinType::Id: |
411 | #include "clang/Basic/OpenCLImageTypes.def" |
412 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
413 | case BuiltinType::Id: |
414 | #include "clang/Basic/OpenCLExtensionTypes.def" |
415 | case BuiltinType::OCLSampler: |
416 | case BuiltinType::OCLEvent: |
417 | case BuiltinType::OCLClkEvent: |
418 | case BuiltinType::OCLQueue: |
419 | case BuiltinType::OCLReserveID: |
420 | #define SVE_TYPE(Name, Id, SingletonId) \ |
421 | case BuiltinType::Id: |
422 | #include "clang/Basic/AArch64SVEACLETypes.def" |
423 | #define PPC_VECTOR_TYPE(Name, Id, Size) \ |
424 | case BuiltinType::Id: |
425 | #include "clang/Basic/PPCTypes.def" |
426 | #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
427 | #include "clang/Basic/RISCVVTypes.def" |
428 | #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
429 | #include "clang/Basic/WebAssemblyReferenceTypes.def" |
430 | case BuiltinType::BuiltinFn: |
431 | case BuiltinType::IncompleteMatrixIdx: |
432 | case BuiltinType::OMPArraySection: |
433 | case BuiltinType::OMPArrayShaping: |
434 | case BuiltinType::OMPIterator: |
435 | return TST_unspecified; |
436 | } |
437 | |
438 | llvm_unreachable("Invalid BuiltinType Kind!" ); |
439 | } |
440 | |
441 | TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { |
442 | while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) |
443 | TL = PTL.getInnerLoc(); |
444 | return TL; |
445 | } |
446 | |
447 | SourceLocation TypeLoc::findNullabilityLoc() const { |
448 | if (auto ATL = getAs<AttributedTypeLoc>()) { |
449 | const Attr *A = ATL.getAttr(); |
450 | if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) || |
451 | isa<TypeNullUnspecifiedAttr>(A))) |
452 | return A->getLocation(); |
453 | } |
454 | |
455 | return {}; |
456 | } |
457 | |
458 | TypeLoc TypeLoc::findExplicitQualifierLoc() const { |
459 | // Qualified types. |
460 | if (auto qual = getAs<QualifiedTypeLoc>()) |
461 | return qual; |
462 | |
463 | TypeLoc loc = IgnoreParens(); |
464 | |
465 | // Attributed types. |
466 | if (auto attr = loc.getAs<AttributedTypeLoc>()) { |
467 | if (attr.isQualifier()) return attr; |
468 | return attr.getModifiedLoc().findExplicitQualifierLoc(); |
469 | } |
470 | |
471 | // C11 _Atomic types. |
472 | if (auto atomic = loc.getAs<AtomicTypeLoc>()) { |
473 | return atomic; |
474 | } |
475 | |
476 | return {}; |
477 | } |
478 | |
479 | void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, |
480 | SourceLocation Loc) { |
481 | setNameLoc(Loc); |
482 | if (!getNumProtocols()) return; |
483 | |
484 | setProtocolLAngleLoc(Loc); |
485 | setProtocolRAngleLoc(Loc); |
486 | for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) |
487 | setProtocolLoc(i, Loc); |
488 | } |
489 | |
490 | void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, |
491 | SourceLocation Loc) { |
492 | setHasBaseTypeAsWritten(true); |
493 | setTypeArgsLAngleLoc(Loc); |
494 | setTypeArgsRAngleLoc(Loc); |
495 | for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) { |
496 | setTypeArgTInfo(i, |
497 | TInfo: Context.getTrivialTypeSourceInfo( |
498 | T: getTypePtr()->getTypeArgsAsWritten()[i], Loc)); |
499 | } |
500 | setProtocolLAngleLoc(Loc); |
501 | setProtocolRAngleLoc(Loc); |
502 | for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) |
503 | setProtocolLoc(i, Loc); |
504 | } |
505 | |
506 | SourceRange AttributedTypeLoc::getLocalSourceRange() const { |
507 | // Note that this does *not* include the range of the attribute |
508 | // enclosure, e.g.: |
509 | // __attribute__((foo(bar))) |
510 | // ^~~~~~~~~~~~~~~ ~~ |
511 | // or |
512 | // [[foo(bar)]] |
513 | // ^~ ~~ |
514 | // That enclosure doesn't necessarily belong to a single attribute |
515 | // anyway. |
516 | return getAttr() ? getAttr()->getRange() : SourceRange(); |
517 | } |
518 | |
519 | SourceRange CountAttributedTypeLoc::getLocalSourceRange() const { |
520 | return getCountExpr() ? getCountExpr()->getSourceRange() : SourceRange(); |
521 | } |
522 | |
523 | SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const { |
524 | return getAttr() ? getAttr()->getRange() : SourceRange(); |
525 | } |
526 | |
527 | void TypeOfTypeLoc::initializeLocal(ASTContext &Context, |
528 | SourceLocation Loc) { |
529 | TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> |
530 | ::initializeLocal(Context, Loc); |
531 | this->getLocalData()->UnmodifiedTInfo = |
532 | Context.getTrivialTypeSourceInfo(T: getUnmodifiedType(), Loc); |
533 | } |
534 | |
535 | void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context, |
536 | SourceLocation Loc) { |
537 | setKWLoc(Loc); |
538 | setRParenLoc(Loc); |
539 | setLParenLoc(Loc); |
540 | this->setUnderlyingTInfo( |
541 | Context.getTrivialTypeSourceInfo(T: getTypePtr()->getBaseType(), Loc)); |
542 | } |
543 | |
544 | void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, |
545 | SourceLocation Loc) { |
546 | if (isEmpty()) |
547 | return; |
548 | setElaboratedKeywordLoc(Loc); |
549 | NestedNameSpecifierLocBuilder Builder; |
550 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
551 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
552 | } |
553 | |
554 | void DependentNameTypeLoc::initializeLocal(ASTContext &Context, |
555 | SourceLocation Loc) { |
556 | setElaboratedKeywordLoc(Loc); |
557 | NestedNameSpecifierLocBuilder Builder; |
558 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
559 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
560 | setNameLoc(Loc); |
561 | } |
562 | |
563 | void |
564 | DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, |
565 | SourceLocation Loc) { |
566 | setElaboratedKeywordLoc(Loc); |
567 | if (getTypePtr()->getQualifier()) { |
568 | NestedNameSpecifierLocBuilder Builder; |
569 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
570 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
571 | } else { |
572 | setQualifierLoc(NestedNameSpecifierLoc()); |
573 | } |
574 | setTemplateKeywordLoc(Loc); |
575 | setTemplateNameLoc(Loc); |
576 | setLAngleLoc(Loc); |
577 | setRAngleLoc(Loc); |
578 | TemplateSpecializationTypeLoc::initializeArgLocs( |
579 | Context, Args: getTypePtr()->template_arguments(), ArgInfos: getArgInfos(), Loc); |
580 | } |
581 | |
582 | void TemplateSpecializationTypeLoc::initializeArgLocs( |
583 | ASTContext &Context, ArrayRef<TemplateArgument> Args, |
584 | TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc) { |
585 | for (unsigned i = 0, e = Args.size(); i != e; ++i) { |
586 | switch (Args[i].getKind()) { |
587 | case TemplateArgument::Null: |
588 | llvm_unreachable("Impossible TemplateArgument" ); |
589 | |
590 | case TemplateArgument::Integral: |
591 | case TemplateArgument::Declaration: |
592 | case TemplateArgument::NullPtr: |
593 | case TemplateArgument::StructuralValue: |
594 | ArgInfos[i] = TemplateArgumentLocInfo(); |
595 | break; |
596 | |
597 | case TemplateArgument::Expression: |
598 | ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); |
599 | break; |
600 | |
601 | case TemplateArgument::Type: |
602 | ArgInfos[i] = TemplateArgumentLocInfo( |
603 | Context.getTrivialTypeSourceInfo(T: Args[i].getAsType(), |
604 | Loc)); |
605 | break; |
606 | |
607 | case TemplateArgument::Template: |
608 | case TemplateArgument::TemplateExpansion: { |
609 | NestedNameSpecifierLocBuilder Builder; |
610 | TemplateName Template = Args[i].getAsTemplateOrTemplatePattern(); |
611 | if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) |
612 | Builder.MakeTrivial(Context, Qualifier: DTN->getQualifier(), R: Loc); |
613 | else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) |
614 | Builder.MakeTrivial(Context, Qualifier: QTN->getQualifier(), R: Loc); |
615 | |
616 | ArgInfos[i] = TemplateArgumentLocInfo( |
617 | Context, Builder.getWithLocInContext(Context), Loc, |
618 | Args[i].getKind() == TemplateArgument::Template ? SourceLocation() |
619 | : Loc); |
620 | break; |
621 | } |
622 | |
623 | case TemplateArgument::Pack: |
624 | ArgInfos[i] = TemplateArgumentLocInfo(); |
625 | break; |
626 | } |
627 | } |
628 | } |
629 | |
630 | // Builds a ConceptReference where all locations point at the same token, |
631 | // for use in trivial TypeSourceInfo for constrained AutoType |
632 | static ConceptReference *createTrivialConceptReference(ASTContext &Context, |
633 | SourceLocation Loc, |
634 | const AutoType *AT) { |
635 | DeclarationNameInfo DNI = |
636 | DeclarationNameInfo(AT->getTypeConstraintConcept()->getDeclName(), Loc, |
637 | AT->getTypeConstraintConcept()->getDeclName()); |
638 | unsigned size = AT->getTypeConstraintArguments().size(); |
639 | TemplateArgumentLocInfo *TALI = new TemplateArgumentLocInfo[size]; |
640 | TemplateSpecializationTypeLoc::initializeArgLocs( |
641 | Context, Args: AT->getTypeConstraintArguments(), ArgInfos: TALI, Loc); |
642 | TemplateArgumentListInfo TAListI; |
643 | for (unsigned i = 0; i < size; ++i) { |
644 | TAListI.addArgument( |
645 | Loc: TemplateArgumentLoc(AT->getTypeConstraintArguments()[i], |
646 | TALI[i])); // TemplateArgumentLocInfo() |
647 | } |
648 | |
649 | auto *ConceptRef = ConceptReference::Create( |
650 | C: Context, NNS: NestedNameSpecifierLoc{}, TemplateKWLoc: Loc, ConceptNameInfo: DNI, FoundDecl: nullptr, |
651 | NamedConcept: AT->getTypeConstraintConcept(), |
652 | ArgsAsWritten: ASTTemplateArgumentListInfo::Create(C: Context, List: TAListI)); |
653 | delete[] TALI; |
654 | return ConceptRef; |
655 | } |
656 | |
657 | void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { |
658 | setRParenLoc(Loc); |
659 | setNameLoc(Loc); |
660 | setConceptReference(nullptr); |
661 | if (getTypePtr()->isConstrained()) { |
662 | setConceptReference( |
663 | createTrivialConceptReference(Context, Loc, getTypePtr())); |
664 | } |
665 | } |
666 | |
667 | namespace { |
668 | |
669 | class GetContainedAutoTypeLocVisitor : |
670 | public TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc> { |
671 | public: |
672 | using TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc>::Visit; |
673 | |
674 | TypeLoc VisitAutoTypeLoc(AutoTypeLoc TL) { |
675 | return TL; |
676 | } |
677 | |
678 | // Only these types can contain the desired 'auto' type. |
679 | |
680 | TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) { |
681 | return Visit(TyLoc: T.getNamedTypeLoc()); |
682 | } |
683 | |
684 | TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) { |
685 | return Visit(TyLoc: T.getUnqualifiedLoc()); |
686 | } |
687 | |
688 | TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) { |
689 | return Visit(T.getPointeeLoc()); |
690 | } |
691 | |
692 | TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) { |
693 | return Visit(T.getPointeeLoc()); |
694 | } |
695 | |
696 | TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) { |
697 | return Visit(T.getPointeeLoc()); |
698 | } |
699 | |
700 | TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) { |
701 | return Visit(T.getPointeeLoc()); |
702 | } |
703 | |
704 | TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) { |
705 | return Visit(TyLoc: T.getElementLoc()); |
706 | } |
707 | |
708 | TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) { |
709 | return Visit(TyLoc: T.getReturnLoc()); |
710 | } |
711 | |
712 | TypeLoc VisitParenTypeLoc(ParenTypeLoc T) { |
713 | return Visit(TyLoc: T.getInnerLoc()); |
714 | } |
715 | |
716 | TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) { |
717 | return Visit(TyLoc: T.getModifiedLoc()); |
718 | } |
719 | |
720 | TypeLoc VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc T) { |
721 | return Visit(TyLoc: T.getWrappedLoc()); |
722 | } |
723 | |
724 | TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) { |
725 | return Visit(TyLoc: T.getInnerLoc()); |
726 | } |
727 | |
728 | TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) { |
729 | return Visit(TyLoc: T.getOriginalLoc()); |
730 | } |
731 | |
732 | TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) { |
733 | return Visit(TyLoc: T.getPatternLoc()); |
734 | } |
735 | }; |
736 | |
737 | } // namespace |
738 | |
739 | AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const { |
740 | TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(TyLoc: *this); |
741 | if (Res.isNull()) |
742 | return AutoTypeLoc(); |
743 | return Res.getAs<AutoTypeLoc>(); |
744 | } |
745 | |
746 | SourceLocation TypeLoc::getTemplateKeywordLoc() const { |
747 | if (const auto TSTL = getAsAdjusted<TemplateSpecializationTypeLoc>()) |
748 | return TSTL.getTemplateKeywordLoc(); |
749 | if (const auto DTSTL = |
750 | getAsAdjusted<DependentTemplateSpecializationTypeLoc>()) |
751 | return DTSTL.getTemplateKeywordLoc(); |
752 | return SourceLocation(); |
753 | } |
754 | |