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 //===----------------------------------------------------------------------===//
     23 // TypeLoc Implementation
     24 //===----------------------------------------------------------------------===//
     25 
     26 namespace {
     27   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
     28   public:
     29 #define ABSTRACT_TYPELOC(CLASS, PARENT)
     30 #define TYPELOC(CLASS, PARENT) \
     31     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
     32       return TyLoc.getLocalSourceRange(); \
     33     }
     34 #include "clang/AST/TypeLocNodes.def"
     35   };
     36 }
     37 
     38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
     39   if (TL.isNull()) return SourceRange();
     40   return TypeLocRanger().Visit(TL);
     41 }
     42 
     43 namespace {
     44   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
     45   public:
     46 #define ABSTRACT_TYPELOC(CLASS, PARENT)
     47 #define TYPELOC(CLASS, PARENT) \
     48     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
     49       return TyLoc.getFullDataSize(); \
     50     }
     51 #include "clang/AST/TypeLocNodes.def"
     52   };
     53 }
     54 
     55 /// \brief Returns the size of the type source info data block.
     56 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
     57   if (Ty.isNull()) return 0;
     58   return TypeSizer().Visit(TypeLoc(Ty, 0));
     59 }
     60 
     61 namespace {
     62   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
     63   public:
     64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
     65 #define TYPELOC(CLASS, PARENT) \
     66     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
     67       return TyLoc.getNextTypeLoc(); \
     68     }
     69 #include "clang/AST/TypeLocNodes.def"
     70   };
     71 }
     72 
     73 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
     74 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
     75 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
     76   return NextLoc().Visit(TL);
     77 }
     78 
     79 /// \brief Initializes a type location, and all of its children
     80 /// recursively, as if the entire tree had been written in the
     81 /// given location.
     82 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
     83                              SourceLocation Loc) {
     84   while (true) {
     85     switch (TL.getTypeLocClass()) {
     86 #define ABSTRACT_TYPELOC(CLASS, PARENT)
     87 #define TYPELOC(CLASS, PARENT)        \
     88     case CLASS: {                     \
     89       CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
     90       TLCasted.initializeLocal(Context, Loc);  \
     91       TL = TLCasted.getNextTypeLoc(); \
     92       if (!TL) return;                \
     93       continue;                       \
     94     }
     95 #include "clang/AST/TypeLocNodes.def"
     96     }
     97   }
     98 }
     99 
    100 SourceLocation TypeLoc::getBeginLoc() const {
    101   TypeLoc Cur = *this;
    102   TypeLoc LeftMost = Cur;
    103   while (true) {
    104     switch (Cur.getTypeLocClass()) {
    105     case Elaborated:
    106       LeftMost = Cur;
    107       break;
    108     case FunctionProto:
    109       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
    110               ->hasTrailingReturn()) {
    111         LeftMost = Cur;
    112         break;
    113       }
    114       /* Fall through */
    115     case FunctionNoProto:
    116     case ConstantArray:
    117     case DependentSizedArray:
    118     case IncompleteArray:
    119     case VariableArray:
    120       // FIXME: Currently QualifiedTypeLoc does not have a source range
    121     case Qualified:
    122       Cur = Cur.getNextTypeLoc();
    123       continue;
    124     default:
    125       if (!Cur.getLocalSourceRange().getBegin().isInvalid())
    126         LeftMost = Cur;
    127       Cur = Cur.getNextTypeLoc();
    128       if (Cur.isNull())
    129         break;
    130       continue;
    131     } // switch
    132     break;
    133   } // while
    134   return LeftMost.getLocalSourceRange().getBegin();
    135 }
    136 
    137 SourceLocation TypeLoc::getEndLoc() const {
    138   TypeLoc Cur = *this;
    139   TypeLoc Last;
    140   while (true) {
    141     switch (Cur.getTypeLocClass()) {
    142     default:
    143       if (!Last)
    144 	Last = Cur;
    145       return Last.getLocalSourceRange().getEnd();
    146     case Paren:
    147     case ConstantArray:
    148     case DependentSizedArray:
    149     case IncompleteArray:
    150     case VariableArray:
    151     case FunctionNoProto:
    152       Last = Cur;
    153       break;
    154     case FunctionProto:
    155       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
    156         Last = TypeLoc();
    157       else
    158         Last = Cur;
    159       break;
    160     case Pointer:
    161     case BlockPointer:
    162     case MemberPointer:
    163     case LValueReference:
    164     case RValueReference:
    165     case PackExpansion:
    166       if (!Last)
    167 	Last = Cur;
    168       break;
    169     case Qualified:
    170     case Elaborated:
    171       break;
    172     }
    173     Cur = Cur.getNextTypeLoc();
    174   }
    175 }
    176 
    177 
    178 namespace {
    179   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
    180     // Overload resolution does the real work for us.
    181     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
    182     static bool isTypeSpec(TypeLoc _) { return false; }
    183 
    184 #define ABSTRACT_TYPELOC(CLASS, PARENT)
    185 #define TYPELOC(CLASS, PARENT) \
    186     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
    187       return isTypeSpec(TyLoc); \
    188     }
    189 #include "clang/AST/TypeLocNodes.def"
    190   };
    191 }
    192 
    193 
    194 /// \brief Determines if the given type loc corresponds to a
    195 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
    196 /// the type hierarchy, this is made somewhat complicated.
    197 ///
    198 /// There are a lot of types that currently use TypeSpecTypeLoc
    199 /// because it's a convenient base class.  Ideally we would not accept
    200 /// those here, but ideally we would have better implementations for
    201 /// them.
    202 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
    203   if (TL.getType().hasLocalQualifiers()) return false;
    204   return TSTChecker().Visit(TL);
    205 }
    206 
    207 // Reimplemented to account for GNU/C++ extension
    208 //     typeof unary-expression
    209 // where there are no parentheses.
    210 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
    211   if (getRParenLoc().isValid())
    212     return SourceRange(getTypeofLoc(), getRParenLoc());
    213   else
    214     return SourceRange(getTypeofLoc(),
    215                        getUnderlyingExpr()->getSourceRange().getEnd());
    216 }
    217 
    218 
    219 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
    220   if (needsExtraLocalData())
    221     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
    222   switch (getTypePtr()->getKind()) {
    223   case BuiltinType::Void:
    224     return TST_void;
    225   case BuiltinType::Bool:
    226     return TST_bool;
    227   case BuiltinType::Char_U:
    228   case BuiltinType::Char_S:
    229     return TST_char;
    230   case BuiltinType::Char16:
    231     return TST_char16;
    232   case BuiltinType::Char32:
    233     return TST_char32;
    234   case BuiltinType::WChar_S:
    235   case BuiltinType::WChar_U:
    236     return TST_wchar;
    237   case BuiltinType::UChar:
    238   case BuiltinType::UShort:
    239   case BuiltinType::UInt:
    240   case BuiltinType::ULong:
    241   case BuiltinType::ULongLong:
    242   case BuiltinType::UInt128:
    243   case BuiltinType::SChar:
    244   case BuiltinType::Short:
    245   case BuiltinType::Int:
    246   case BuiltinType::Long:
    247   case BuiltinType::LongLong:
    248   case BuiltinType::Int128:
    249   case BuiltinType::Half:
    250   case BuiltinType::Float:
    251   case BuiltinType::Double:
    252   case BuiltinType::LongDouble:
    253     llvm_unreachable("Builtin type needs extra local data!");
    254     // Fall through, if the impossible happens.
    255 
    256   case BuiltinType::NullPtr:
    257   case BuiltinType::Overload:
    258   case BuiltinType::Dependent:
    259   case BuiltinType::BoundMember:
    260   case BuiltinType::UnknownAny:
    261   case BuiltinType::ARCUnbridgedCast:
    262   case BuiltinType::PseudoObject:
    263   case BuiltinType::ObjCId:
    264   case BuiltinType::ObjCClass:
    265   case BuiltinType::ObjCSel:
    266   case BuiltinType::OCLImage1d:
    267   case BuiltinType::OCLImage1dArray:
    268   case BuiltinType::OCLImage1dBuffer:
    269   case BuiltinType::OCLImage2d:
    270   case BuiltinType::OCLImage2dArray:
    271   case BuiltinType::OCLImage3d:
    272   case BuiltinType::OCLSampler:
    273   case BuiltinType::OCLEvent:
    274   case BuiltinType::BuiltinFn:
    275     return TST_unspecified;
    276   }
    277 
    278   llvm_unreachable("Invalid BuiltinType Kind!");
    279 }
    280 
    281 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
    282   while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
    283     TL = PTL.getInnerLoc();
    284   return TL;
    285 }
    286 
    287 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
    288                                         SourceLocation Loc) {
    289   setElaboratedKeywordLoc(Loc);
    290   NestedNameSpecifierLocBuilder Builder;
    291   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
    292   setQualifierLoc(Builder.getWithLocInContext(Context));
    293 }
    294 
    295 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
    296                                            SourceLocation Loc) {
    297   setElaboratedKeywordLoc(Loc);
    298   NestedNameSpecifierLocBuilder Builder;
    299   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
    300   setQualifierLoc(Builder.getWithLocInContext(Context));
    301   setNameLoc(Loc);
    302 }
    303 
    304 void
    305 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
    306                                                         SourceLocation Loc) {
    307   setElaboratedKeywordLoc(Loc);
    308   if (getTypePtr()->getQualifier()) {
    309     NestedNameSpecifierLocBuilder Builder;
    310     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
    311     setQualifierLoc(Builder.getWithLocInContext(Context));
    312   } else {
    313     setQualifierLoc(NestedNameSpecifierLoc());
    314   }
    315   setTemplateKeywordLoc(Loc);
    316   setTemplateNameLoc(Loc);
    317   setLAngleLoc(Loc);
    318   setRAngleLoc(Loc);
    319   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
    320                                                    getTypePtr()->getArgs(),
    321                                                    getArgInfos(), Loc);
    322 }
    323 
    324 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
    325                                                       unsigned NumArgs,
    326                                                   const TemplateArgument *Args,
    327                                               TemplateArgumentLocInfo *ArgInfos,
    328                                                       SourceLocation Loc) {
    329   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
    330     switch (Args[i].getKind()) {
    331     case TemplateArgument::Null:
    332     case TemplateArgument::Declaration:
    333     case TemplateArgument::Integral:
    334     case TemplateArgument::NullPtr:
    335       llvm_unreachable("Impossible TemplateArgument");
    336 
    337     case TemplateArgument::Expression:
    338       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
    339       break;
    340 
    341     case TemplateArgument::Type:
    342       ArgInfos[i] = TemplateArgumentLocInfo(
    343                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
    344                                                            Loc));
    345       break;
    346 
    347     case TemplateArgument::Template:
    348     case TemplateArgument::TemplateExpansion: {
    349       NestedNameSpecifierLocBuilder Builder;
    350       TemplateName Template = Args[i].getAsTemplate();
    351       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
    352         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
    353       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
    354         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
    355 
    356       ArgInfos[i] = TemplateArgumentLocInfo(
    357                                            Builder.getWithLocInContext(Context),
    358                                             Loc,
    359                                 Args[i].getKind() == TemplateArgument::Template
    360                                             ? SourceLocation()
    361                                             : Loc);
    362       break;
    363     }
    364 
    365     case TemplateArgument::Pack:
    366       ArgInfos[i] = TemplateArgumentLocInfo();
    367       break;
    368     }
    369   }
    370 }
    371