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