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