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 "llvm/Support/raw_ostream.h"
00015 #include "clang/AST/TypeLocVisitor.h"
00016 #include "clang/AST/Expr.h"
00017 #include "llvm/Support/ErrorHandling.h"
00018 using namespace clang;
00019 
00020 //===----------------------------------------------------------------------===//
00021 // TypeLoc Implementation
00022 //===----------------------------------------------------------------------===//
00023 
00024 namespace {
00025   class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
00026   public:
00027 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00028 #define TYPELOC(CLASS, PARENT) \
00029     SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00030       return TyLoc.getLocalSourceRange(); \
00031     }
00032 #include "clang/AST/TypeLocNodes.def"
00033   };
00034 }
00035 
00036 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
00037   if (TL.isNull()) return SourceRange();
00038   return TypeLocRanger().Visit(TL);
00039 }
00040 
00041 namespace {
00042   class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
00043   public:
00044 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00045 #define TYPELOC(CLASS, PARENT) \
00046     unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00047       return TyLoc.getFullDataSize(); \
00048     }
00049 #include "clang/AST/TypeLocNodes.def"
00050   };
00051 }
00052 
00053 /// \brief Returns the size of the type source info data block.
00054 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
00055   if (Ty.isNull()) return 0;
00056   return TypeSizer().Visit(TypeLoc(Ty, 0));
00057 }
00058 
00059 namespace {
00060   class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
00061   public:
00062 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00063 #define TYPELOC(CLASS, PARENT) \
00064     TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00065       return TyLoc.getNextTypeLoc(); \
00066     }
00067 #include "clang/AST/TypeLocNodes.def"
00068   };
00069 }
00070 
00071 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
00072 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
00073 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
00074   return NextLoc().Visit(TL);
00075 }
00076 
00077 /// \brief Initializes a type location, and all of its children
00078 /// recursively, as if the entire tree had been written in the
00079 /// given location.
00080 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, 
00081                              SourceLocation Loc) {
00082   while (true) {
00083     switch (TL.getTypeLocClass()) {
00084 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00085 #define TYPELOC(CLASS, PARENT)        \
00086     case CLASS: {                     \
00087       CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
00088       TLCasted.initializeLocal(Context, Loc);  \
00089       TL = TLCasted.getNextTypeLoc(); \
00090       if (!TL) return;                \
00091       continue;                       \
00092     }
00093 #include "clang/AST/TypeLocNodes.def"
00094     }
00095   }
00096 }
00097 
00098 SourceLocation TypeLoc::getBeginLoc() const {
00099   TypeLoc Cur = *this;
00100   while (true) {
00101     switch (Cur.getTypeLocClass()) {
00102     // FIXME: Currently QualifiedTypeLoc does not have a source range
00103     // case Qualified:
00104     case Elaborated:
00105     case DependentName:
00106     case DependentTemplateSpecialization:
00107       break;
00108     default:
00109       TypeLoc Next = Cur.getNextTypeLoc();
00110       if (Next.isNull()) break;
00111       Cur = Next;
00112       continue;
00113     }
00114     break;
00115   }
00116   return Cur.getLocalSourceRange().getBegin();
00117 }
00118 
00119 SourceLocation TypeLoc::getEndLoc() const {
00120   TypeLoc Cur = *this;
00121   TypeLoc Last;
00122   while (true) {
00123     switch (Cur.getTypeLocClass()) {
00124     default:
00125       if (!Last)
00126   Last = Cur;
00127       return Last.getLocalSourceRange().getEnd();
00128     case Paren:
00129     case ConstantArray:
00130     case DependentSizedArray:
00131     case IncompleteArray:
00132     case VariableArray:
00133     case FunctionProto:
00134     case FunctionNoProto:
00135       Last = Cur;
00136       break;
00137     case Pointer:
00138     case BlockPointer:
00139     case MemberPointer:
00140     case LValueReference:
00141     case RValueReference:
00142     case PackExpansion:
00143       if (!Last)
00144   Last = Cur;
00145       break;
00146     case Qualified:
00147     case Elaborated:
00148       break;
00149     }
00150     Cur = Cur.getNextTypeLoc();
00151   }
00152 }
00153 
00154 
00155 namespace {
00156   struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
00157     // Overload resolution does the real work for us.
00158     static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
00159     static bool isTypeSpec(TypeLoc _) { return false; }
00160 
00161 #define ABSTRACT_TYPELOC(CLASS, PARENT)
00162 #define TYPELOC(CLASS, PARENT) \
00163     bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
00164       return isTypeSpec(TyLoc); \
00165     }
00166 #include "clang/AST/TypeLocNodes.def"
00167   };
00168 }
00169 
00170 
00171 /// \brief Determines if the given type loc corresponds to a
00172 /// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
00173 /// the type hierarchy, this is made somewhat complicated.
00174 ///
00175 /// There are a lot of types that currently use TypeSpecTypeLoc
00176 /// because it's a convenient base class.  Ideally we would not accept
00177 /// those here, but ideally we would have better implementations for
00178 /// them.
00179 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
00180   if (TL->getType().hasLocalQualifiers()) return false;
00181   return TSTChecker().Visit(*TL);
00182 }
00183 
00184 // Reimplemented to account for GNU/C++ extension
00185 //     typeof unary-expression
00186 // where there are no parentheses.
00187 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
00188   if (getRParenLoc().isValid())
00189     return SourceRange(getTypeofLoc(), getRParenLoc());
00190   else
00191     return SourceRange(getTypeofLoc(),
00192                        getUnderlyingExpr()->getSourceRange().getEnd());
00193 }
00194 
00195 
00196 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
00197   if (needsExtraLocalData())
00198     return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
00199   switch (getTypePtr()->getKind()) {
00200   case BuiltinType::Void:
00201     return TST_void;
00202   case BuiltinType::Bool:
00203     return TST_bool;
00204   case BuiltinType::Char_U:
00205   case BuiltinType::Char_S:
00206     return TST_char;
00207   case BuiltinType::Char16:
00208     return TST_char16;
00209   case BuiltinType::Char32:
00210     return TST_char32;
00211   case BuiltinType::WChar_S:
00212   case BuiltinType::WChar_U:
00213     return TST_wchar;
00214   case BuiltinType::UChar:
00215   case BuiltinType::UShort:
00216   case BuiltinType::UInt:
00217   case BuiltinType::ULong:
00218   case BuiltinType::ULongLong:
00219   case BuiltinType::UInt128:
00220   case BuiltinType::SChar:
00221   case BuiltinType::Short:
00222   case BuiltinType::Int:
00223   case BuiltinType::Long:
00224   case BuiltinType::LongLong:
00225   case BuiltinType::Int128:
00226   case BuiltinType::Half:
00227   case BuiltinType::Float:
00228   case BuiltinType::Double:
00229   case BuiltinType::LongDouble:
00230     llvm_unreachable("Builtin type needs extra local data!");
00231     // Fall through, if the impossible happens.
00232       
00233   case BuiltinType::NullPtr:
00234   case BuiltinType::Overload:
00235   case BuiltinType::Dependent:
00236   case BuiltinType::BoundMember:
00237   case BuiltinType::UnknownAny:
00238   case BuiltinType::ARCUnbridgedCast:
00239   case BuiltinType::PseudoObject:
00240   case BuiltinType::ObjCId:
00241   case BuiltinType::ObjCClass:
00242   case BuiltinType::ObjCSel:
00243     return TST_unspecified;
00244   }
00245 
00246   llvm_unreachable("Invalid BuiltinType Kind!");
00247 }
00248 
00249 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
00250   while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
00251     TL = PTL->getInnerLoc();
00252   return TL;
00253 }
00254 
00255 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, 
00256                                         SourceLocation Loc) {
00257   setElaboratedKeywordLoc(Loc);
00258   NestedNameSpecifierLocBuilder Builder;
00259   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00260   setQualifierLoc(Builder.getWithLocInContext(Context));
00261 }
00262 
00263 void DependentNameTypeLoc::initializeLocal(ASTContext &Context, 
00264                                            SourceLocation Loc) {
00265   setElaboratedKeywordLoc(Loc);
00266   NestedNameSpecifierLocBuilder Builder;
00267   Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00268   setQualifierLoc(Builder.getWithLocInContext(Context));
00269   setNameLoc(Loc);
00270 }
00271 
00272 void
00273 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
00274                                                         SourceLocation Loc) {
00275   setElaboratedKeywordLoc(Loc);
00276   if (getTypePtr()->getQualifier()) {
00277     NestedNameSpecifierLocBuilder Builder;
00278     Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
00279     setQualifierLoc(Builder.getWithLocInContext(Context));
00280   } else {
00281     setQualifierLoc(NestedNameSpecifierLoc());
00282   }
00283   setTemplateKeywordLoc(Loc);
00284   setTemplateNameLoc(Loc);
00285   setLAngleLoc(Loc);
00286   setRAngleLoc(Loc);
00287   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
00288                                                    getTypePtr()->getArgs(),
00289                                                    getArgInfos(), Loc);
00290 }
00291 
00292 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, 
00293                                                       unsigned NumArgs,
00294                                                   const TemplateArgument *Args,
00295                                               TemplateArgumentLocInfo *ArgInfos,
00296                                                       SourceLocation Loc) {
00297   for (unsigned i = 0, e = NumArgs; i != e; ++i) {
00298     switch (Args[i].getKind()) {
00299     case TemplateArgument::Null: 
00300     case TemplateArgument::Declaration:
00301     case TemplateArgument::Integral:
00302     case TemplateArgument::Pack:
00303     case TemplateArgument::Expression:
00304       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
00305       break;
00306       
00307     case TemplateArgument::Type:
00308       ArgInfos[i] = TemplateArgumentLocInfo(
00309                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
00310                                                            Loc));
00311       break;
00312         
00313     case TemplateArgument::Template:
00314     case TemplateArgument::TemplateExpansion: {
00315       NestedNameSpecifierLocBuilder Builder;
00316       TemplateName Template = Args[i].getAsTemplate();
00317       if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
00318         Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
00319       else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
00320         Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
00321       
00322       ArgInfos[i] = TemplateArgumentLocInfo(
00323                                            Builder.getWithLocInContext(Context),
00324                                             Loc, 
00325                                 Args[i].getKind() == TemplateArgument::Template
00326                                             ? SourceLocation()
00327                                             : Loc);
00328       break;
00329     }        
00330     }
00331   }
00332 }