Clang Project

clang_source_code/lib/AST/TypeLoc.cpp
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/ASTContext.h"
15#include "clang/AST/Expr.h"
16#include "clang/AST/NestedNameSpecifier.h"
17#include "clang/AST/TemplateBase.h"
18#include "clang/AST/TemplateName.h"
19#include "clang/AST/TypeLocVisitor.h"
20#include "clang/Basic/SourceLocation.h"
21#include "clang/Basic/Specifiers.h"
22#include "llvm/Support/ErrorHandling.h"
23#include "llvm/Support/MathExtras.h"
24#include <algorithm>
25#include <cassert>
26#include <cstdint>
27#include <cstring>
28
29using namespace clang;
30
31static const unsigned TypeLocMaxDataAlign = alignof(void *);
32
33//===----------------------------------------------------------------------===//
34// TypeLoc Implementation
35//===----------------------------------------------------------------------===//
36
37namespace {
38
39class TypeLocRanger : public TypeLocVisitor<TypeLocRangerSourceRange> {
40public:
41#define ABSTRACT_TYPELOC(CLASS, PARENT)
42#define TYPELOC(CLASS, PARENT) \
43  SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
44    return TyLoc.getLocalSourceRange(); \
45  }
46#include "clang/AST/TypeLocNodes.def"
47};
48
49// namespace
50
51SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
52  if (TL.isNull()) return SourceRange();
53  return TypeLocRanger().Visit(TL);
54}
55
56namespace {
57
58class TypeAligner : public TypeLocVisitor<TypeAlignerunsigned> {
59public:
60#define ABSTRACT_TYPELOC(CLASS, PARENT)
61#define TYPELOC(CLASS, PARENT) \
62  unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
63    return TyLoc.getLocalDataAlignment(); \
64  }
65#include "clang/AST/TypeLocNodes.def"
66};
67
68// namespace
69
70/// Returns the alignment of the type source info data block.
71unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
72  if (Ty.isNull()) return 1;
73  return TypeAligner().Visit(TypeLoc(Tynullptr));
74}
75
76namespace {
77
78class TypeSizer : public TypeLocVisitor<TypeSizerunsigned> {
79public:
80#define ABSTRACT_TYPELOC(CLASS, PARENT)
81#define TYPELOC(CLASS, PARENT) \
82  unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
83    return TyLoc.getLocalDataSize(); \
84  }
85#include "clang/AST/TypeLocNodes.def"
86};
87
88// namespace
89
90/// Returns the size of the type source info data block.
91unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
92  unsigned Total = 0;
93  TypeLoc TyLoc(Tynullptr);
94  unsigned MaxAlign = 1;
95  while (!TyLoc.isNull()) {
96    unsigned Align = getLocalAlignmentForType(TyLoc.getType());
97    MaxAlign = std::max(AlignMaxAlign);
98    Total = llvm::alignTo(Total, Align);
99    Total += TypeSizer().Visit(TyLoc);
100    TyLoc = TyLoc.getNextTypeLoc();
101  }
102  Total = llvm::alignTo(Total, MaxAlign);
103  return Total;
104}
105
106namespace {
107
108class NextLoc : public TypeLocVisitor<NextLocTypeLoc> {
109public:
110#define ABSTRACT_TYPELOC(CLASS, PARENT)
111#define TYPELOC(CLASS, PARENT) \
112  TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
113    return TyLoc.getNextTypeLoc(); \
114  }
115#include "clang/AST/TypeLocNodes.def"
116};
117
118// namespace
119
120/// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
121/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
122TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
123  return NextLoc().Visit(TL);
124}
125
126/// Initializes a type location, and all of its children
127/// recursively, as if the entire tree had been written in the
128/// given location.
129void TypeLoc::initializeImpl(ASTContext &ContextTypeLoc TL,
130                             SourceLocation Loc) {
131  while (true) {
132    switch (TL.getTypeLocClass()) {
133#define ABSTRACT_TYPELOC(CLASS, PARENT)
134#define TYPELOC(CLASS, PARENT)        \
135    case CLASS: {                     \
136      CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
137      TLCasted.initializeLocal(Context, Loc);  \
138      TL = TLCasted.getNextTypeLoc(); \
139      if (!TL) return;                \
140      continue;                       \
141    }
142#include "clang/AST/TypeLocNodes.def"
143    }
144  }
145}
146
147namespace {
148
149class TypeLocCopier : public TypeLocVisitor<TypeLocCopier> {
150  TypeLoc Source;
151
152public:
153  TypeLocCopier(TypeLoc source) : Source(source) {}
154
155#define ABSTRACT_TYPELOC(CLASS, PARENT)
156#define TYPELOC(CLASS, PARENT)                          \
157  void Visit##CLASS##TypeLoc(CLASS##TypeLoc dest) {   \
158    dest.copyLocal(Source.castAs<CLASS##TypeLoc>());  \
159  }
160#include "clang/AST/TypeLocNodes.def"
161};
162
163// namespace
164
165void TypeLoc::copy(TypeLoc other) {
166  assert(getFullDataSize() == other.getFullDataSize());
167
168  // If both data pointers are aligned to the maximum alignment, we
169  // can memcpy because getFullDataSize() accurately reflects the
170  // layout of the data.
171  if (reinterpret_cast<uintptr_t>(Data) ==
172          llvm::alignTo(reinterpret_cast<uintptr_t>(Data),
173                        TypeLocMaxDataAlign) &&
174      reinterpret_cast<uintptr_t>(other.Data) ==
175          llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data),
176                        TypeLocMaxDataAlign)) {
177    memcpy(Dataother.Data, getFullDataSize());
178    return;
179  }
180
181  // Copy each of the pieces.
182  TypeLoc TL(getType(), Data);
183  do {
184    TypeLocCopier(other).Visit(TL);
185    other = other.getNextTypeLoc();
186  } while ((TL = TL.getNextTypeLoc()));
187}
188
189SourceLocation TypeLoc::getBeginLoc() const {
190  TypeLoc Cur = *this;
191  TypeLoc LeftMost = Cur;
192  while (true) {
193    switch (Cur.getTypeLocClass()) {
194    case Elaborated:
195      LeftMost = Cur;
196      break;
197    case FunctionProto:
198      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
199              ->hasTrailingReturn()) {
200        LeftMost = Cur;
201        break;
202      }
203      LLVM_FALLTHROUGH;
204    case FunctionNoProto:
205    case ConstantArray:
206    case DependentSizedArray:
207    case IncompleteArray:
208    case VariableArray:
209      // FIXME: Currently QualifiedTypeLoc does not have a source range
210    case Qualified:
211      Cur = Cur.getNextTypeLoc();
212      continue;
213    default:
214      if (Cur.getLocalSourceRange().getBegin().isValid())
215        LeftMost = Cur;
216      Cur = Cur.getNextTypeLoc();
217      if (Cur.isNull())
218        break;
219      continue;
220    } // switch
221    break;
222  } // while
223  return LeftMost.getLocalSourceRange().getBegin();
224}
225
226SourceLocation TypeLoc::getEndLoc() const {
227  TypeLoc Cur = *this;
228  TypeLoc Last;
229  while (true) {
230    switch (Cur.getTypeLocClass()) {
231    default:
232      if (!Last)
233        Last = Cur;
234      return Last.getLocalSourceRange().getEnd();
235    case Paren:
236    case ConstantArray:
237    case DependentSizedArray:
238    case IncompleteArray:
239    case VariableArray:
240    case FunctionNoProto:
241      Last = Cur;
242      break;
243    case FunctionProto:
244      if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
245        Last = TypeLoc();
246      else
247        Last = Cur;
248      break;
249    case Pointer:
250    case BlockPointer:
251    case MemberPointer:
252    case LValueReference:
253    case RValueReference:
254    case PackExpansion:
255      if (!Last)
256        Last = Cur;
257      break;
258    case Qualified:
259    case Elaborated:
260      break;
261    }
262    Cur = Cur.getNextTypeLoc();
263  }
264}
265
266namespace {
267
268struct TSTChecker : public TypeLocVisitor<TSTCheckerbool> {
269  // Overload resolution does the real work for us.
270  static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
271  static bool isTypeSpec(TypeLoc _) { return false; }
272
273#define ABSTRACT_TYPELOC(CLASS, PARENT)
274#define TYPELOC(CLASS, PARENT) \
275  bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
276    return isTypeSpec(TyLoc); \
277  }
278#include "clang/AST/TypeLocNodes.def"
279};
280
281// namespace
282
283/// Determines if the given type loc corresponds to a
284/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
285/// the type hierarchy, this is made somewhat complicated.
286///
287/// There are a lot of types that currently use TypeSpecTypeLoc
288/// because it's a convenient base class.  Ideally we would not accept
289/// those here, but ideally we would have better implementations for
290/// them.
291bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
292  if (TL.getType().hasLocalQualifiers()) return false;
293  return TSTChecker().Visit(TL);
294}
295
296// Reimplemented to account for GNU/C++ extension
297//     typeof unary-expression
298// where there are no parentheses.
299SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
300  if (getRParenLoc().isValid())
301    return SourceRange(getTypeofLoc(), getRParenLoc());
302  else
303    return SourceRange(getTypeofLoc(),
304                       getUnderlyingExpr()->getSourceRange().getEnd());
305}
306
307
308TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
309  if (needsExtraLocalData())
310    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
311  switch (getTypePtr()->getKind()) {
312  case BuiltinType::Void:
313    return TST_void;
314  case BuiltinType::Bool:
315    return TST_bool;
316  case BuiltinType::Char_U:
317  case BuiltinType::Char_S:
318    return TST_char;
319  case BuiltinType::Char8:
320    return TST_char8;
321  case BuiltinType::Char16:
322    return TST_char16;
323  case BuiltinType::Char32:
324    return TST_char32;
325  case BuiltinType::WChar_S:
326  case BuiltinType::WChar_U:
327    return TST_wchar;
328  case BuiltinType::UChar:
329  case BuiltinType::UShort:
330  case BuiltinType::UInt:
331  case BuiltinType::ULong:
332  case BuiltinType::ULongLong:
333  case BuiltinType::UInt128:
334  case BuiltinType::SChar:
335  case BuiltinType::Short:
336  case BuiltinType::Int:
337  case BuiltinType::Long:
338  case BuiltinType::LongLong:
339  case BuiltinType::Int128:
340  case BuiltinType::Half:
341  case BuiltinType::Float:
342  case BuiltinType::Double:
343  case BuiltinType::LongDouble:
344  case BuiltinType::Float16:
345  case BuiltinType::Float128:
346  case BuiltinType::ShortAccum:
347  case BuiltinType::Accum:
348  case BuiltinType::LongAccum:
349  case BuiltinType::UShortAccum:
350  case BuiltinType::UAccum:
351  case BuiltinType::ULongAccum:
352  case BuiltinType::ShortFract:
353  case BuiltinType::Fract:
354  case BuiltinType::LongFract:
355  case BuiltinType::UShortFract:
356  case BuiltinType::UFract:
357  case BuiltinType::ULongFract:
358  case BuiltinType::SatShortAccum:
359  case BuiltinType::SatAccum:
360  case BuiltinType::SatLongAccum:
361  case BuiltinType::SatUShortAccum:
362  case BuiltinType::SatUAccum:
363  case BuiltinType::SatULongAccum:
364  case BuiltinType::SatShortFract:
365  case BuiltinType::SatFract:
366  case BuiltinType::SatLongFract:
367  case BuiltinType::SatUShortFract:
368  case BuiltinType::SatUFract:
369  case BuiltinType::SatULongFract:
370    llvm_unreachable("Builtin type needs extra local data!");
371    // Fall through, if the impossible happens.
372
373  case BuiltinType::NullPtr:
374  case BuiltinType::Overload:
375  case BuiltinType::Dependent:
376  case BuiltinType::BoundMember:
377  case BuiltinType::UnknownAny:
378  case BuiltinType::ARCUnbridgedCast:
379  case BuiltinType::PseudoObject:
380  case BuiltinType::ObjCId:
381  case BuiltinType::ObjCClass:
382  case BuiltinType::ObjCSel:
383#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
384  case BuiltinType::Id:
385#include "clang/Basic/OpenCLImageTypes.def"
386#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
387  case BuiltinType::Id:
388#include "clang/Basic/OpenCLExtensionTypes.def"
389  case BuiltinType::OCLSampler:
390  case BuiltinType::OCLEvent:
391  case BuiltinType::OCLClkEvent:
392  case BuiltinType::OCLQueue:
393  case BuiltinType::OCLReserveID:
394  case BuiltinType::BuiltinFn:
395  case BuiltinType::OMPArraySection:
396    return TST_unspecified;
397  }
398
399  llvm_unreachable("Invalid BuiltinType Kind!");
400}
401
402TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
403  while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
404    TL = PTL.getInnerLoc();
405  return TL;
406}
407
408SourceLocation TypeLoc::findNullabilityLoc() const {
409  if (auto ATL = getAs<AttributedTypeLoc>()) {
410    const Attr *A = ATL.getAttr();
411    if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
412              isa<TypeNullUnspecifiedAttr>(A)))
413      return A->getLocation();
414  }
415
416  return {};
417}
418
419TypeLoc TypeLoc::findExplicitQualifierLoc() const {
420  // Qualified types.
421  if (auto qual = getAs<QualifiedTypeLoc>())
422    return qual;
423
424  TypeLoc loc = IgnoreParens();
425
426  // Attributed types.
427  if (auto attr = loc.getAs<AttributedTypeLoc>()) {
428    if (attr.isQualifier()) return attr;
429    return attr.getModifiedLoc().findExplicitQualifierLoc();
430  }
431
432  // C11 _Atomic types.
433  if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
434    return atomic;
435  }
436
437  return {};
438}
439
440void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
441                                           SourceLocation Loc) {
442  setNameLoc(Loc);
443  if (!getNumProtocols()) return;
444
445  setProtocolLAngleLoc(Loc);
446  setProtocolRAngleLoc(Loc);
447  for (unsigned i = 0e = getNumProtocols(); i != e; ++i)
448    setProtocolLoc(iLoc);
449}
450
451void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
452                                        SourceLocation Loc) {
453  setHasBaseTypeAsWritten(true);
454  setTypeArgsLAngleLoc(Loc);
455  setTypeArgsRAngleLoc(Loc);
456  for (unsigned i = 0e = getNumTypeArgs(); i != e; ++i) {
457    setTypeArgTInfo(i,
458                   Context.getTrivialTypeSourceInfo(
459                     getTypePtr()->getTypeArgsAsWritten()[i], Loc));
460  }
461  setProtocolLAngleLoc(Loc);
462  setProtocolRAngleLoc(Loc);
463  for (unsigned i = 0e = getNumProtocols(); i != e; ++i)
464    setProtocolLoc(iLoc);
465}
466
467void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
468                                       SourceLocation Loc) {
469  TypeofLikeTypeLoc<TypeOfTypeLocTypeOfTypeTypeOfTypeLocInfo>
470      ::initializeLocal(ContextLoc);
471  this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
472      getUnderlyingType(), Loc);
473}
474
475void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
476                                       SourceLocation Loc) {
477    setKWLoc(Loc);
478    setRParenLoc(Loc);
479    setLParenLoc(Loc);
480    this->setUnderlyingTInfo(
481        Context.getTrivialTypeSourceInfo(getTypePtr()->getBaseType(), Loc));
482}
483
484void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
485                                        SourceLocation Loc) {
486  setElaboratedKeywordLoc(Loc);
487  NestedNameSpecifierLocBuilder Builder;
488  Builder.MakeTrivial(ContextgetTypePtr()->getQualifier(), Loc);
489  setQualifierLoc(Builder.getWithLocInContext(Context));
490}
491
492void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
493                                           SourceLocation Loc) {
494  setElaboratedKeywordLoc(Loc);
495  NestedNameSpecifierLocBuilder Builder;
496  Builder.MakeTrivial(ContextgetTypePtr()->getQualifier(), Loc);
497  setQualifierLoc(Builder.getWithLocInContext(Context));
498  setNameLoc(Loc);
499}
500
501void
502DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
503                                                        SourceLocation Loc) {
504  setElaboratedKeywordLoc(Loc);
505  if (getTypePtr()->getQualifier()) {
506    NestedNameSpecifierLocBuilder Builder;
507    Builder.MakeTrivial(ContextgetTypePtr()->getQualifier(), Loc);
508    setQualifierLoc(Builder.getWithLocInContext(Context));
509  } else {
510    setQualifierLoc(NestedNameSpecifierLoc());
511  }
512  setTemplateKeywordLoc(Loc);
513  setTemplateNameLoc(Loc);
514  setLAngleLoc(Loc);
515  setRAngleLoc(Loc);
516  TemplateSpecializationTypeLoc::initializeArgLocs(ContextgetNumArgs(),
517                                                   getTypePtr()->getArgs(),
518                                                   getArgInfos(), Loc);
519}
520
521void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
522                                                      unsigned NumArgs,
523                                                  const TemplateArgument *Args,
524                                              TemplateArgumentLocInfo *ArgInfos,
525                                                      SourceLocation Loc) {
526  for (unsigned i = 0e = NumArgsi != e; ++i) {
527    switch (Args[i].getKind()) {
528    case TemplateArgument::Null:
529      llvm_unreachable("Impossible TemplateArgument");
530
531    case TemplateArgument::Integral:
532    case TemplateArgument::Declaration:
533    case TemplateArgument::NullPtr:
534      ArgInfos[i] = TemplateArgumentLocInfo();
535      break;
536
537    case TemplateArgument::Expression:
538      ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
539      break;
540
541    case TemplateArgument::Type:
542      ArgInfos[i] = TemplateArgumentLocInfo(
543                          Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
544                                                           Loc));
545      break;
546
547    case TemplateArgument::Template:
548    case TemplateArgument::TemplateExpansion: {
549      NestedNameSpecifierLocBuilder Builder;
550      TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
551      if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
552        Builder.MakeTrivial(ContextDTN->getQualifier(), Loc);
553      else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
554        Builder.MakeTrivial(ContextQTN->getQualifier(), Loc);
555
556      ArgInfos[i] = TemplateArgumentLocInfo(
557          Builder.getWithLocInContext(Context), Loc,
558          Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
559                                                          : Loc);
560      break;
561    }
562
563    case TemplateArgument::Pack:
564      ArgInfos[i] = TemplateArgumentLocInfo();
565      break;
566    }
567  }
568}
569
clang::TypeLoc::getLocalSourceRangeImpl
clang::TypeLoc::getLocalAlignmentForType
clang::TypeLoc::getFullDataSizeForType
clang::TypeLoc::getNextTypeLocImpl
clang::TypeLoc::initializeImpl
clang::TypeLoc::copy
clang::TypeLoc::getBeginLoc
clang::TypeLoc::getEndLoc
clang::TypeSpecTypeLoc::isKind
clang::TypeOfExprTypeLoc::getLocalSourceRange
clang::BuiltinTypeLoc::getWrittenTypeSpec
clang::TypeLoc::IgnoreParensImpl
clang::TypeLoc::findNullabilityLoc
clang::TypeLoc::findExplicitQualifierLoc
clang::ObjCTypeParamTypeLoc::initializeLocal
clang::ObjCObjectTypeLoc::initializeLocal
clang::TypeOfTypeLoc::initializeLocal
clang::UnaryTransformTypeLoc::initializeLocal
clang::ElaboratedTypeLoc::initializeLocal
clang::DependentNameTypeLoc::initializeLocal
clang::DependentTemplateSpecializationTypeLoc::initializeLocal
clang::TemplateSpecializationTypeLoc::initializeArgLocs