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 "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 }