llvm-project

Форк
0
/
TypeLoc.cpp 
756 строк · 22.9 Кб
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(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(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(TyLoc.getType());
100
    MaxAlign = std::max(Align, MaxAlign);
101
    Total = llvm::alignTo(Total, Align);
102
    Total += TypeSizer().Visit(TyLoc);
103
    TyLoc = TyLoc.getNextTypeLoc();
104
  }
105
  Total = llvm::alignTo(Total, 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(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(reinterpret_cast<uintptr_t>(Data),
176
                        TypeLocMaxDataAlign) &&
177
      reinterpret_cast<uintptr_t>(other.Data) ==
178
          llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data),
179
                        TypeLocMaxDataAlign)) {
180
    memcpy(Data, other.Data, getFullDataSize());
181
    return;
182
  }
183

184
  // Copy each of the pieces.
185
  TypeLoc TL(getType(), Data);
186
  do {
187
    TypeLocCopier(other).Visit(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(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>(A) || isa<TypeNonNullAttr>(A) ||
454
              isa<TypeNullUnspecifiedAttr>(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
                   Context.getTrivialTypeSourceInfo(
501
                     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(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(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, getTypePtr()->getQualifier(), 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, getTypePtr()->getQualifier(), 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, getTypePtr()->getQualifier(), 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, getTypePtr()->template_arguments(), 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(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, DTN->getQualifier(), Loc);
616
      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
617
        Builder.MakeTrivial(Context, QTN->getQualifier(), 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, AT->getTypeConstraintArguments(), TALI, Loc);
645
  TemplateArgumentListInfo TAListI;
646
  for (unsigned i = 0; i < size; ++i) {
647
    TAListI.addArgument(
648
        TemplateArgumentLoc(AT->getTypeConstraintArguments()[i],
649
                            TALI[i])); // TemplateArgumentLocInfo()
650
  }
651

652
  auto *ConceptRef = ConceptReference::Create(
653
      Context, NestedNameSpecifierLoc{}, Loc, DNI, nullptr,
654
      AT->getTypeConstraintConcept(),
655
      ASTTemplateArgumentListInfo::Create(Context, 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, 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(T.getNamedTypeLoc());
685
    }
686

687
    TypeLoc VisitQualifiedTypeLoc(QualifiedTypeLoc T) {
688
      return Visit(T.getUnqualifiedLoc());
689
    }
690

691
    TypeLoc VisitPointerTypeLoc(PointerTypeLoc T) {
692
      return Visit(T.getPointeeLoc());
693
    }
694

695
    TypeLoc VisitBlockPointerTypeLoc(BlockPointerTypeLoc T) {
696
      return Visit(T.getPointeeLoc());
697
    }
698

699
    TypeLoc VisitReferenceTypeLoc(ReferenceTypeLoc T) {
700
      return Visit(T.getPointeeLoc());
701
    }
702

703
    TypeLoc VisitMemberPointerTypeLoc(MemberPointerTypeLoc T) {
704
      return Visit(T.getPointeeLoc());
705
    }
706

707
    TypeLoc VisitArrayTypeLoc(ArrayTypeLoc T) {
708
      return Visit(T.getElementLoc());
709
    }
710

711
    TypeLoc VisitFunctionTypeLoc(FunctionTypeLoc T) {
712
      return Visit(T.getReturnLoc());
713
    }
714

715
    TypeLoc VisitParenTypeLoc(ParenTypeLoc T) {
716
      return Visit(T.getInnerLoc());
717
    }
718

719
    TypeLoc VisitAttributedTypeLoc(AttributedTypeLoc T) {
720
      return Visit(T.getModifiedLoc());
721
    }
722

723
    TypeLoc VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc T) {
724
      return Visit(T.getWrappedLoc());
725
    }
726

727
    TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) {
728
      return Visit(T.getInnerLoc());
729
    }
730

731
    TypeLoc VisitAdjustedTypeLoc(AdjustedTypeLoc T) {
732
      return Visit(T.getOriginalLoc());
733
    }
734

735
    TypeLoc VisitPackExpansionTypeLoc(PackExpansionTypeLoc T) {
736
      return Visit(T.getPatternLoc());
737
    }
738
  };
739

740
} // namespace
741

742
AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
743
  TypeLoc Res = GetContainedAutoTypeLocVisitor().Visit(*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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.