clang API Documentation

TypeLoc.cpp
Go to the documentation of this file.
00001 //===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines the TypeLoc subclasses implementations.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/AST/TypeLoc.h"
00015 #include "clang/AST/ASTContext.h"
00016 #include "clang/AST/Expr.h"
00017 #include "clang/AST/TypeLocVisitor.h"
00018 #include "llvm/Support/ErrorHandling.h"
00019 #include "llvm/Support/raw_ostream.h"
00020 using namespace clang;
00021 
00022 //===----------------------------------------------------------------------===//
00023 // TypeLoc Implementation
00024 //===----------------------------------------------------------------------===//
00025 
00026 namespace {
00027   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
00028   public:
00029 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00030 #define TYPELOC(CLASS, PARENT) \
00031     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00032       return TyLoc.getLocalSourceRange(); \
00033     }
00034 #include "clang/AST/TypeLocNodes.def"
00035   };
00036 }
00037 
00038 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
00039   if (TL.isNull()) return SourceRange();
00040   return TypeLocRanger().Visit(TL);
00041 }
00042 
00043 namespace {
00044   class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
00045   public:
00046 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00047 #define TYPELOC(CLASS, PARENT) \
00048     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00049       return TyLoc.getLocalDataAlignment(); \
00050     }
00051 #include "clang/AST/TypeLocNodes.def"
00052   };
00053 }
00054 
00055 /// \brief Returns the alignment of the type source info data block.
00056 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
00057   if (Ty.isNull()) return 1;
00058   return TypeAligner().Visit(TypeLoc(Ty, nullptr));
00059 }
00060 
00061 namespace {
00062   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
00063   public:
00064 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00065 #define TYPELOC(CLASS, PARENT) \
00066     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00067       return TyLoc.getLocalDataSize(); \
00068     }
00069 #include "clang/AST/TypeLocNodes.def"
00070   };
00071 }
00072 
00073 /// \brief Returns the size of the type source info data block.
00074 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
00075   unsigned Total = 0;
00076   TypeLoc TyLoc(Ty, nullptr);
00077   unsigned MaxAlign = 1;
00078   while (!TyLoc.isNull()) {
00079     unsigned Align = getLocalAlignmentForType(TyLoc.getType());
00080     MaxAlign = std::max(Align, MaxAlign);
00081     Total = llvm::RoundUpToAlignment(Total, Align);
00082     Total += TypeSizer().Visit(TyLoc);
00083     TyLoc = TyLoc.getNextTypeLoc();
00084   }
00085   Total = llvm::RoundUpToAlignment(Total, MaxAlign);
00086   return Total;
00087 }
00088 
00089 namespace {
00090   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
00091   public:
00092 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00093 #define TYPELOC(CLASS, PARENT) \
00094     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00095       return TyLoc.getNextTypeLoc(); \
00096     }
00097 #include "clang/AST/TypeLocNodes.def"
00098   };
00099 }
00100 
00101 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
00102 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
00103 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
00104   return NextLoc().Visit(TL);
00105 }
00106 
00107 /// \brief Initializes a type location, and all of its children
00108 /// recursively, as if the entire tree had been written in the
00109 /// given location.
00110 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 
00111                              SourceLocation Loc) {
00112   while (true) {
00113     switch (TL.getTypeLocClass()) {
00114 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00115 #define TYPELOC(CLASS, PARENT)        \
00116     case CLASS: {                     \
00117       CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
00118       TLCasted.initializeLocal(Context, Loc);  \
00119       TL = TLCasted.getNextTypeLoc(); \
00120       if (!TL) return;                \
00121       continue;                       \
00122     }
00123 #include "clang/AST/TypeLocNodes.def"
00124     }
00125   }
00126 }
00127 
00128 SourceLocation TypeLoc::getBeginLoc() const {
00129   TypeLoc Cur = *this;
00130   TypeLoc LeftMost = Cur;
00131   while (true) {
00132     switch (Cur.getTypeLocClass()) {
00133     case Elaborated:
00134       LeftMost = Cur;
00135       break;
00136     case FunctionProto:
00137       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
00138               ->hasTrailingReturn()) {
00139         LeftMost = Cur;
00140         break;
00141       }
00142       /* Fall through */
00143     case FunctionNoProto:
00144     case ConstantArray:
00145     case DependentSizedArray:
00146     case IncompleteArray:
00147     case VariableArray:
00148       // FIXME: Currently QualifiedTypeLoc does not have a source range
00149     case Qualified:
00150       Cur = Cur.getNextTypeLoc();
00151       continue;
00152     default:
00153       if (!Cur.getLocalSourceRange().getBegin().isInvalid())
00154         LeftMost = Cur;
00155       Cur = Cur.getNextTypeLoc();
00156       if (Cur.isNull())
00157         break;
00158       continue;
00159     } // switch
00160     break;
00161   } // while
00162   return LeftMost.getLocalSourceRange().getBegin();
00163 }
00164 
00165 SourceLocation TypeLoc::getEndLoc() const {
00166   TypeLoc Cur = *this;
00167   TypeLoc Last;
00168   while (true) {
00169     switch (Cur.getTypeLocClass()) {
00170     default:
00171       if (!Last)
00172   Last = Cur;
00173       return Last.getLocalSourceRange().getEnd();
00174     case Paren:
00175     case ConstantArray:
00176     case DependentSizedArray:
00177     case IncompleteArray:
00178     case VariableArray:
00179     case FunctionNoProto:
00180       Last = Cur;
00181       break;
00182     case FunctionProto:
00183       if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
00184         Last = TypeLoc();
00185       else
00186         Last = Cur;
00187       break;
00188     case Pointer:
00189     case BlockPointer:
00190     case MemberPointer:
00191     case LValueReference:
00192     case RValueReference:
00193     case PackExpansion:
00194       if (!Last)
00195   Last = Cur;
00196       break;
00197     case Qualified:
00198     case Elaborated:
00199       break;
00200     }
00201     Cur = Cur.getNextTypeLoc();
00202   }
00203 }
00204 
00205 
00206 namespace {
00207   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
00208     // Overload resolution does the real work for us.
00209     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
00210     static bool isTypeSpec(TypeLoc _) { return false; }
00211 
00212 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00213 #define TYPELOC(CLASS, PARENT) \
00214     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00215       return isTypeSpec(TyLoc); \
00216     }
00217 #include "clang/AST/TypeLocNodes.def"
00218   };
00219 }
00220 
00221 
00222 /// \brief Determines if the given type loc corresponds to a
00223 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
00224 /// the type hierarchy, this is made somewhat complicated.
00225 ///
00226 /// There are a lot of types that currently use TypeSpecTypeLoc
00227 /// because it's a convenient base class.  Ideally we would not accept
00228 /// those here, but ideally we would have better implementations for
00229 /// them.
00230 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
00231   if (TL.getType().hasLocalQualifiers()) return false;
00232   return TSTChecker().Visit(TL);
00233 }
00234 
00235 // Reimplemented to account for GNU/C++ extension
00236 //     typeof unary-expression
00237 // where there are no parentheses.
00238 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
00239   if (getRParenLoc().isValid())
00240     return SourceRange(getTypeofLoc(), getRParenLoc());
00241   else
00242     return SourceRange(getTypeofLoc(),
00243                        getUnderlyingExpr()->getSourceRange().getEnd());
00244 }
00245 
00246 
00247 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
00248   if (needsExtraLocalData())
00249     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
00250   switch (getTypePtr()->getKind()) {
00251   case BuiltinType::Void:
00252     return TST_void;
00253   case BuiltinType::Bool:
00254     return TST_bool;
00255   case BuiltinType::Char_U:
00256   case BuiltinType::Char_S:
00257     return TST_char;
00258   case BuiltinType::Char16:
00259     return TST_char16;
00260   case BuiltinType::Char32:
00261     return TST_char32;
00262   case BuiltinType::WChar_S:
00263   case BuiltinType::WChar_U:
00264     return TST_wchar;
00265   case BuiltinType::UChar:
00266   case BuiltinType::UShort:
00267   case BuiltinType::UInt:
00268   case BuiltinType::ULong:
00269   case BuiltinType::ULongLong:
00270   case BuiltinType::UInt128:
00271   case BuiltinType::SChar:
00272   case BuiltinType::Short:
00273   case BuiltinType::Int:
00274   case BuiltinType::Long:
00275   case BuiltinType::LongLong:
00276   case BuiltinType::Int128:
00277   case BuiltinType::Half:
00278   case BuiltinType::Float:
00279   case BuiltinType::Double:
00280   case BuiltinType::LongDouble:
00281     llvm_unreachable("Builtin type needs extra local data!");
00282     // Fall through, if the impossible happens.
00283       
00284   case BuiltinType::NullPtr:
00285   case BuiltinType::Overload:
00286   case BuiltinType::Dependent:
00287   case BuiltinType::BoundMember:
00288   case BuiltinType::UnknownAny:
00289   case BuiltinType::ARCUnbridgedCast:
00290   case BuiltinType::PseudoObject:
00291   case BuiltinType::ObjCId:
00292   case BuiltinType::ObjCClass:
00293   case BuiltinType::ObjCSel:
00294   case BuiltinType::OCLImage1d:
00295   case BuiltinType::OCLImage1dArray:
00296   case BuiltinType::OCLImage1dBuffer:
00297   case BuiltinType::OCLImage2d:
00298   case BuiltinType::OCLImage2dArray:
00299   case BuiltinType::OCLImage3d:
00300   case BuiltinType::OCLSampler:
00301   case BuiltinType::OCLEvent:
00302   case BuiltinType::BuiltinFn:
00303     return TST_unspecified;
00304   }
00305 
00306   llvm_unreachable("Invalid BuiltinType Kind!");
00307 }
00308 
00309 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
00310   while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
00311     TL = PTL.getInnerLoc();
00312   return TL;
00313 }
00314 
00315 void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
00316                                        SourceLocation Loc) {
00317   TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
00318       ::initializeLocal(Context, Loc);
00319   this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
00320       getUnderlyingType(), Loc);
00321 }
00322 
00323 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
00324                                         SourceLocation Loc) {
00325   setElaboratedKeywordLoc(Loc);
00326   NestedNameSpecifierLocBuilder Builder;
00327   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00328   setQualifierLoc(Builder.getWithLocInContext(Context));
00329 }
00330 
00331 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
00332                                            SourceLocation Loc) {
00333   setElaboratedKeywordLoc(Loc);
00334   NestedNameSpecifierLocBuilder Builder;
00335   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00336   setQualifierLoc(Builder.getWithLocInContext(Context));
00337   setNameLoc(Loc);
00338 }
00339 
00340 void
00341 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
00342                                                         SourceLocation Loc) {
00343   setElaboratedKeywordLoc(Loc);
00344   if (getTypePtr()->getQualifier()) {
00345     NestedNameSpecifierLocBuilder Builder;
00346     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00347     setQualifierLoc(Builder.getWithLocInContext(Context));
00348   } else {
00349     setQualifierLoc(NestedNameSpecifierLoc());
00350   }
00351   setTemplateKeywordLoc(Loc);
00352   setTemplateNameLoc(Loc);
00353   setLAngleLoc(Loc);
00354   setRAngleLoc(Loc);
00355   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
00356                                                    getTypePtr()->getArgs(),
00357                                                    getArgInfos(), Loc);
00358 }
00359 
00360 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
00361                                                       unsigned NumArgs,
00362                                                   const TemplateArgument *Args,
00363                                               TemplateArgumentLocInfo *ArgInfos,
00364                                                       SourceLocation Loc) {
00365   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
00366     switch (Args[i].getKind()) {
00367     case TemplateArgument::Null: 
00368       llvm_unreachable("Impossible TemplateArgument");
00369 
00370     case TemplateArgument::Integral:
00371     case TemplateArgument::Declaration:
00372     case TemplateArgument::NullPtr:
00373       ArgInfos[i] = TemplateArgumentLocInfo();
00374       break;
00375 
00376     case TemplateArgument::Expression:
00377       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
00378       break;
00379       
00380     case TemplateArgument::Type:
00381       ArgInfos[i] = TemplateArgumentLocInfo(
00382                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
00383                                                            Loc));
00384       break;
00385 
00386     case TemplateArgument::Template:
00387     case TemplateArgument::TemplateExpansion: {
00388       NestedNameSpecifierLocBuilder Builder;
00389       TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
00390       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
00391         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
00392       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
00393         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
00394 
00395       ArgInfos[i] = TemplateArgumentLocInfo(
00396           Builder.getWithLocInContext(Context), Loc,
00397           Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
00398                                                           : Loc);
00399       break;
00400     }
00401 
00402     case TemplateArgument::Pack:
00403       ArgInfos[i] = TemplateArgumentLocInfo();
00404       break;
00405     }
00406   }
00407 }