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