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(a: Align, b: 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::UnresolvedTemplate: |
403 | case BuiltinType::BoundMember: |
404 | case BuiltinType::UnknownAny: |
405 | case BuiltinType::ARCUnbridgedCast: |
406 | case BuiltinType::PseudoObject: |
407 | case BuiltinType::ObjCId: |
408 | case BuiltinType::ObjCClass: |
409 | case BuiltinType::ObjCSel: |
410 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
411 | case BuiltinType::Id: |
412 | #include "clang/Basic/OpenCLImageTypes.def" |
413 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
414 | case BuiltinType::Id: |
415 | #include "clang/Basic/OpenCLExtensionTypes.def" |
416 | case BuiltinType::OCLSampler: |
417 | case BuiltinType::OCLEvent: |
418 | case BuiltinType::OCLClkEvent: |
419 | case BuiltinType::OCLQueue: |
420 | case BuiltinType::OCLReserveID: |
421 | #define SVE_TYPE(Name, Id, SingletonId) \ |
422 | case BuiltinType::Id: |
423 | #include "clang/Basic/AArch64SVEACLETypes.def" |
424 | #define PPC_VECTOR_TYPE(Name, Id, Size) \ |
425 | case BuiltinType::Id: |
426 | #include "clang/Basic/PPCTypes.def" |
427 | #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
428 | #include "clang/Basic/RISCVVTypes.def" |
429 | #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
430 | #include "clang/Basic/WebAssemblyReferenceTypes.def" |
431 | #define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id: |
432 | #include "clang/Basic/AMDGPUTypes.def" |
433 | case BuiltinType::BuiltinFn: |
434 | case BuiltinType::IncompleteMatrixIdx: |
435 | case BuiltinType::ArraySection: |
436 | case BuiltinType::OMPArrayShaping: |
437 | case BuiltinType::OMPIterator: |
438 | return TST_unspecified; |
439 | } |
440 | |
441 | llvm_unreachable("Invalid BuiltinType Kind!" ); |
442 | } |
443 | |
444 | TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { |
445 | while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>()) |
446 | TL = PTL.getInnerLoc(); |
447 | return TL; |
448 | } |
449 | |
450 | SourceLocation TypeLoc::findNullabilityLoc() const { |
451 | if (auto ATL = getAs<AttributedTypeLoc>()) { |
452 | const Attr *A = ATL.getAttr(); |
453 | if (A && (isa<TypeNullableAttr>(Val: A) || isa<TypeNonNullAttr>(Val: A) || |
454 | isa<TypeNullUnspecifiedAttr>(Val: A))) |
455 | return A->getLocation(); |
456 | } |
457 | |
458 | return {}; |
459 | } |
460 | |
461 | TypeLoc TypeLoc::findExplicitQualifierLoc() const { |
462 | // Qualified types. |
463 | if (auto qual = getAs<QualifiedTypeLoc>()) |
464 | return qual; |
465 | |
466 | TypeLoc loc = IgnoreParens(); |
467 | |
468 | // Attributed types. |
469 | if (auto attr = loc.getAs<AttributedTypeLoc>()) { |
470 | if (attr.isQualifier()) return attr; |
471 | return attr.getModifiedLoc().findExplicitQualifierLoc(); |
472 | } |
473 | |
474 | // C11 _Atomic types. |
475 | if (auto atomic = loc.getAs<AtomicTypeLoc>()) { |
476 | return atomic; |
477 | } |
478 | |
479 | return {}; |
480 | } |
481 | |
482 | void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, |
483 | SourceLocation Loc) { |
484 | setNameLoc(Loc); |
485 | if (!getNumProtocols()) return; |
486 | |
487 | setProtocolLAngleLoc(Loc); |
488 | setProtocolRAngleLoc(Loc); |
489 | for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) |
490 | setProtocolLoc(i, Loc); |
491 | } |
492 | |
493 | void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, |
494 | SourceLocation Loc) { |
495 | setHasBaseTypeAsWritten(true); |
496 | setTypeArgsLAngleLoc(Loc); |
497 | setTypeArgsRAngleLoc(Loc); |
498 | for (unsigned i = 0, e = getNumTypeArgs(); i != e; ++i) { |
499 | setTypeArgTInfo(i, |
500 | TInfo: Context.getTrivialTypeSourceInfo( |
501 | T: getTypePtr()->getTypeArgsAsWritten()[i], Loc)); |
502 | } |
503 | setProtocolLAngleLoc(Loc); |
504 | setProtocolRAngleLoc(Loc); |
505 | for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) |
506 | setProtocolLoc(i, Loc); |
507 | } |
508 | |
509 | SourceRange AttributedTypeLoc::getLocalSourceRange() const { |
510 | // Note that this does *not* include the range of the attribute |
511 | // enclosure, e.g.: |
512 | // __attribute__((foo(bar))) |
513 | // ^~~~~~~~~~~~~~~ ~~ |
514 | // or |
515 | // [[foo(bar)]] |
516 | // ^~ ~~ |
517 | // That enclosure doesn't necessarily belong to a single attribute |
518 | // anyway. |
519 | return getAttr() ? getAttr()->getRange() : SourceRange(); |
520 | } |
521 | |
522 | SourceRange CountAttributedTypeLoc::getLocalSourceRange() const { |
523 | return getCountExpr() ? getCountExpr()->getSourceRange() : SourceRange(); |
524 | } |
525 | |
526 | SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const { |
527 | return getAttr() ? getAttr()->getRange() : SourceRange(); |
528 | } |
529 | |
530 | void TypeOfTypeLoc::initializeLocal(ASTContext &Context, |
531 | SourceLocation Loc) { |
532 | TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> |
533 | ::initializeLocal(Context, Loc); |
534 | this->getLocalData()->UnmodifiedTInfo = |
535 | Context.getTrivialTypeSourceInfo(T: getUnmodifiedType(), Loc); |
536 | } |
537 | |
538 | void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context, |
539 | SourceLocation Loc) { |
540 | setKWLoc(Loc); |
541 | setRParenLoc(Loc); |
542 | setLParenLoc(Loc); |
543 | this->setUnderlyingTInfo( |
544 | Context.getTrivialTypeSourceInfo(T: getTypePtr()->getBaseType(), Loc)); |
545 | } |
546 | |
547 | void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, |
548 | SourceLocation Loc) { |
549 | if (isEmpty()) |
550 | return; |
551 | setElaboratedKeywordLoc(Loc); |
552 | NestedNameSpecifierLocBuilder Builder; |
553 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
554 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
555 | } |
556 | |
557 | void DependentNameTypeLoc::initializeLocal(ASTContext &Context, |
558 | SourceLocation Loc) { |
559 | setElaboratedKeywordLoc(Loc); |
560 | NestedNameSpecifierLocBuilder Builder; |
561 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
562 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
563 | setNameLoc(Loc); |
564 | } |
565 | |
566 | void |
567 | DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, |
568 | SourceLocation Loc) { |
569 | setElaboratedKeywordLoc(Loc); |
570 | if (getTypePtr()->getQualifier()) { |
571 | NestedNameSpecifierLocBuilder Builder; |
572 | Builder.MakeTrivial(Context, Qualifier: getTypePtr()->getQualifier(), R: Loc); |
573 | setQualifierLoc(Builder.getWithLocInContext(Context)); |
574 | } else { |
575 | setQualifierLoc(NestedNameSpecifierLoc()); |
576 | } |
577 | setTemplateKeywordLoc(Loc); |
578 | setTemplateNameLoc(Loc); |
579 | setLAngleLoc(Loc); |
580 | setRAngleLoc(Loc); |
581 | TemplateSpecializationTypeLoc::initializeArgLocs( |
582 | Context, Args: getTypePtr()->template_arguments(), ArgInfos: getArgInfos(), Loc); |
583 | } |
584 | |
585 | void TemplateSpecializationTypeLoc::initializeArgLocs( |
586 | ASTContext &Context, ArrayRef<TemplateArgument> Args, |
587 | TemplateArgumentLocInfo *ArgInfos, SourceLocation Loc) { |
588 | for (unsigned i = 0, e = Args.size(); i != e; ++i) { |
589 | switch (Args[i].getKind()) { |
590 | case TemplateArgument::Null: |
591 | llvm_unreachable("Impossible TemplateArgument" ); |
592 | |
593 | case TemplateArgument::Integral: |
594 | case TemplateArgument::Declaration: |
595 | case TemplateArgument::NullPtr: |
596 | case TemplateArgument::StructuralValue: |
597 | ArgInfos[i] = TemplateArgumentLocInfo(); |
598 | break; |
599 | |
600 | case TemplateArgument::Expression: |
601 | ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); |
602 | break; |
603 | |
604 | case TemplateArgument::Type: |
605 | ArgInfos[i] = TemplateArgumentLocInfo( |
606 | Context.getTrivialTypeSourceInfo(T: Args[i].getAsType(), |
607 | Loc)); |
608 | break; |
609 | |
610 | case TemplateArgument::Template: |
611 | case TemplateArgument::TemplateExpansion: { |
612 | NestedNameSpecifierLocBuilder Builder; |
613 | TemplateName Template = Args[i].getAsTemplateOrTemplatePattern(); |
614 | if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) |
615 | Builder.MakeTrivial(Context, Qualifier: DTN->getQualifier(), R: Loc); |
616 | else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) |
617 | Builder.MakeTrivial(Context, Qualifier: QTN->getQualifier(), R: Loc); |
618 | |
619 | ArgInfos[i] = TemplateArgumentLocInfo( |
620 | Context, Builder.getWithLocInContext(Context), Loc, |
621 | Args[i].getKind() == TemplateArgument::Template ? SourceLocation() |
622 | : Loc); |
623 | break; |
624 | } |
625 | |
626 | case TemplateArgument::Pack: |
627 | ArgInfos[i] = TemplateArgumentLocInfo(); |
628 | break; |
629 | } |
630 | } |
631 | } |
632 | |
633 | // Builds a ConceptReference where all locations point at the same token, |
634 | // for use in trivial TypeSourceInfo for constrained AutoType |
635 | static ConceptReference *createTrivialConceptReference(ASTContext &Context, |
636 | SourceLocation Loc, |
637 | const AutoType *AT) { |
638 | DeclarationNameInfo DNI = |
639 | DeclarationNameInfo(AT->getTypeConstraintConcept()->getDeclName(), Loc, |
640 | AT->getTypeConstraintConcept()->getDeclName()); |
641 | unsigned size = AT->getTypeConstraintArguments().size(); |
642 | TemplateArgumentLocInfo *TALI = new TemplateArgumentLocInfo[size]; |
643 | TemplateSpecializationTypeLoc::initializeArgLocs( |
644 | Context, Args: AT->getTypeConstraintArguments(), ArgInfos: TALI, Loc); |
645 | TemplateArgumentListInfo TAListI; |
646 | for (unsigned i = 0; i < size; ++i) { |
647 | TAListI.addArgument( |
648 | Loc: TemplateArgumentLoc(AT->getTypeConstraintArguments()[i], |
649 | TALI[i])); // TemplateArgumentLocInfo() |
650 | } |
651 | |
652 | auto *ConceptRef = ConceptReference::Create( |
653 | C: Context, NNS: NestedNameSpecifierLoc{}, TemplateKWLoc: Loc, ConceptNameInfo: DNI, FoundDecl: nullptr, |
654 | NamedConcept: AT->getTypeConstraintConcept(), |
655 | ArgsAsWritten: ASTTemplateArgumentListInfo::Create(C: Context, List: TAListI)); |
656 | delete[] TALI; |
657 | return ConceptRef; |
658 | } |
659 | |
660 | void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { |
661 | setRParenLoc(Loc); |
662 | setNameLoc(Loc); |
663 | setConceptReference(nullptr); |
664 | if (getTypePtr()->isConstrained()) { |
665 | setConceptReference( |
666 | createTrivialConceptReference(Context, Loc, AT: getTypePtr())); |
667 | } |
668 | } |
669 | |
670 | namespace { |
671 | |
672 | class GetContainedAutoTypeLocVisitor : |
673 | public TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc> { |
674 | public: |
675 | using TypeLocVisitor<GetContainedAutoTypeLocVisitor, TypeLoc>::Visit; |
676 | |
677 | TypeLoc VisitAutoTypeLoc(AutoTypeLoc TL) { |
678 | return TL; |
679 | } |
680 | |
681 | // Only these types can contain the desired 'auto' type. |
682 | |
683 | TypeLoc VisitElaboratedTypeLoc(ElaboratedTypeLoc T) { |
684 | return Visit(TyLoc: T.getNamedTypeLoc()); |
685 | } |
686 | |
687 | TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) { |
688 | return Visit(TyLoc: T.getUnqualifiedLoc()); |
689 | } |
690 | |
691 | TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) { |
692 | return Visit(TyLoc: T.getPointeeLoc()); |
693 | } |
694 | |
695 | TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) { |
696 | return Visit(TyLoc: T.getPointeeLoc()); |
697 | } |
698 | |
699 | TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) { |
700 | return Visit(TyLoc: T.getPointeeLoc()); |
701 | } |
702 | |
703 | TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) { |
704 | return Visit(TyLoc: T.getPointeeLoc()); |
705 | } |
706 | |
707 | TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) { |
708 | return Visit(TyLoc: T.getElementLoc()); |
709 | } |
710 | |
711 | TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) { |
712 | return Visit(TyLoc: T.getReturnLoc()); |
713 | } |
714 | |
715 | TypeLoc VisitParenTypeLoc(ParenTypeLoc T) { |
716 | return Visit(TyLoc: T.getInnerLoc()); |
717 | } |
718 | |
719 | TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) { |
720 | return Visit(TyLoc: T.getModifiedLoc()); |
721 | } |
722 | |
723 | TypeLoc VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc T) { |
724 | return Visit(TyLoc: T.getWrappedLoc()); |
725 | } |
726 | |
727 | TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) { |
728 | return Visit(TyLoc: T.getInnerLoc()); |
729 | } |
730 | |
731 | TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) { |
732 | return Visit(TyLoc: T.getOriginalLoc()); |
733 | } |
734 | |
735 | TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) { |
736 | return Visit(TyLoc: T.getPatternLoc()); |
737 | } |
738 | }; |
739 | |
740 | } // namespace |
741 | |
742 | AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const { |
743 | TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(TyLoc: *this); |
744 | if (Res.isNull()) |
745 | return AutoTypeLoc(); |
746 | return Res.getAs<AutoTypeLoc>(); |
747 | } |
748 | |
749 | SourceLocation TypeLoc::getTemplateKeywordLoc() const { |
750 | if (const auto TSTL = getAsAdjusted<TemplateSpecializationTypeLoc>()) |
751 | return TSTL.getTemplateKeywordLoc(); |
752 | if (const auto DTSTL = |
753 | getAsAdjusted<DependentTemplateSpecializationTypeLoc>()) |
754 | return DTSTL.getTemplateKeywordLoc(); |
755 | return SourceLocation(); |
756 | } |
757 | |