clang API Documentation
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 }