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