1 //===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the TypeLoc subclasses implementations.
12 //===----------------------------------------------------------------------===//
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;
22 //===----------------------------------------------------------------------===//
23 // TypeLoc Implementation
24 //===----------------------------------------------------------------------===//
27 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
29 #define ABSTRACT_TYPELOC(CLASS, PARENT)
30 #define TYPELOC(CLASS, PARENT) \
31 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
32 return TyLoc.getLocalSourceRange(); \
34 #include "clang/AST/TypeLocNodes.def"
38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39 if (TL.isNull()) return SourceRange();
40 return TypeLocRanger().Visit(TL);
44 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
46 #define ABSTRACT_TYPELOC(CLASS, PARENT)
47 #define TYPELOC(CLASS, PARENT) \
48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
49 return TyLoc.getFullDataSize(); \
51 #include "clang/AST/TypeLocNodes.def"
55 /// \brief Returns the size of the type source info data block.
56 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
57 if (Ty.isNull()) return 0;
58 return TypeSizer().Visit(TypeLoc(Ty, 0));
62 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
65 #define TYPELOC(CLASS, PARENT) \
66 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67 return TyLoc.getNextTypeLoc(); \
69 #include "clang/AST/TypeLocNodes.def"
73 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
74 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
75 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
76 return NextLoc().Visit(TL);
79 /// \brief Initializes a type location, and all of its children
80 /// recursively, as if the entire tree had been written in the
82 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
85 switch (TL.getTypeLocClass()) {
86 #define ABSTRACT_TYPELOC(CLASS, PARENT)
87 #define TYPELOC(CLASS, PARENT) \
89 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
90 TLCasted.initializeLocal(Context, Loc); \
91 TL = TLCasted.getNextTypeLoc(); \
95 #include "clang/AST/TypeLocNodes.def"
100 SourceLocation TypeLoc::getBeginLoc() const {
102 TypeLoc LeftMost = Cur;
104 switch (Cur.getTypeLocClass()) {
109 if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
114 case FunctionNoProto:
116 case DependentSizedArray:
117 case IncompleteArray:
119 // FIXME: Currently QualifiedTypeLoc does not have a source range
121 Cur = Cur.getNextTypeLoc();
124 if (!Cur.getLocalSourceRange().getBegin().isInvalid())
126 Cur = Cur.getNextTypeLoc();
133 return LeftMost.getLocalSourceRange().getBegin();
136 SourceLocation TypeLoc::getEndLoc() const {
140 switch (Cur.getTypeLocClass()) {
144 return Last.getLocalSourceRange().getEnd();
147 case DependentSizedArray:
148 case IncompleteArray:
150 case FunctionNoProto:
154 if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
162 case LValueReference:
163 case RValueReference:
172 Cur = Cur.getNextTypeLoc();
178 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
179 // Overload resolution does the real work for us.
180 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
181 static bool isTypeSpec(TypeLoc _) { return false; }
183 #define ABSTRACT_TYPELOC(CLASS, PARENT)
184 #define TYPELOC(CLASS, PARENT) \
185 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
186 return isTypeSpec(TyLoc); \
188 #include "clang/AST/TypeLocNodes.def"
193 /// \brief Determines if the given type loc corresponds to a
194 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
195 /// the type hierarchy, this is made somewhat complicated.
197 /// There are a lot of types that currently use TypeSpecTypeLoc
198 /// because it's a convenient base class. Ideally we would not accept
199 /// those here, but ideally we would have better implementations for
201 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
202 if (TL->getType().hasLocalQualifiers()) return false;
203 return TSTChecker().Visit(*TL);
206 // Reimplemented to account for GNU/C++ extension
207 // typeof unary-expression
208 // where there are no parentheses.
209 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
210 if (getRParenLoc().isValid())
211 return SourceRange(getTypeofLoc(), getRParenLoc());
213 return SourceRange(getTypeofLoc(),
214 getUnderlyingExpr()->getSourceRange().getEnd());
218 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
219 if (needsExtraLocalData())
220 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
221 switch (getTypePtr()->getKind()) {
222 case BuiltinType::Void:
224 case BuiltinType::Bool:
226 case BuiltinType::Char_U:
227 case BuiltinType::Char_S:
229 case BuiltinType::Char16:
231 case BuiltinType::Char32:
233 case BuiltinType::WChar_S:
234 case BuiltinType::WChar_U:
236 case BuiltinType::UChar:
237 case BuiltinType::UShort:
238 case BuiltinType::UInt:
239 case BuiltinType::ULong:
240 case BuiltinType::ULongLong:
241 case BuiltinType::UInt128:
242 case BuiltinType::SChar:
243 case BuiltinType::Short:
244 case BuiltinType::Int:
245 case BuiltinType::Long:
246 case BuiltinType::LongLong:
247 case BuiltinType::Int128:
248 case BuiltinType::Half:
249 case BuiltinType::Float:
250 case BuiltinType::Double:
251 case BuiltinType::LongDouble:
252 llvm_unreachable("Builtin type needs extra local data!");
253 // Fall through, if the impossible happens.
255 case BuiltinType::NullPtr:
256 case BuiltinType::Overload:
257 case BuiltinType::Dependent:
258 case BuiltinType::BoundMember:
259 case BuiltinType::UnknownAny:
260 case BuiltinType::ARCUnbridgedCast:
261 case BuiltinType::PseudoObject:
262 case BuiltinType::ObjCId:
263 case BuiltinType::ObjCClass:
264 case BuiltinType::ObjCSel:
265 case BuiltinType::OCLImage1d:
266 case BuiltinType::OCLImage1dArray:
267 case BuiltinType::OCLImage1dBuffer:
268 case BuiltinType::OCLImage2d:
269 case BuiltinType::OCLImage2dArray:
270 case BuiltinType::OCLImage3d:
271 case BuiltinType::OCLSampler:
272 case BuiltinType::OCLEvent:
273 case BuiltinType::BuiltinFn:
274 return TST_unspecified;
277 llvm_unreachable("Invalid BuiltinType Kind!");
280 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
281 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
282 TL = PTL->getInnerLoc();
286 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
287 SourceLocation Loc) {
288 setElaboratedKeywordLoc(Loc);
289 NestedNameSpecifierLocBuilder Builder;
290 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
291 setQualifierLoc(Builder.getWithLocInContext(Context));
294 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
295 SourceLocation Loc) {
296 setElaboratedKeywordLoc(Loc);
297 NestedNameSpecifierLocBuilder Builder;
298 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
299 setQualifierLoc(Builder.getWithLocInContext(Context));
304 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
305 SourceLocation Loc) {
306 setElaboratedKeywordLoc(Loc);
307 if (getTypePtr()->getQualifier()) {
308 NestedNameSpecifierLocBuilder Builder;
309 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
310 setQualifierLoc(Builder.getWithLocInContext(Context));
312 setQualifierLoc(NestedNameSpecifierLoc());
314 setTemplateKeywordLoc(Loc);
315 setTemplateNameLoc(Loc);
318 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
319 getTypePtr()->getArgs(),
323 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
325 const TemplateArgument *Args,
326 TemplateArgumentLocInfo *ArgInfos,
327 SourceLocation Loc) {
328 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
329 switch (Args[i].getKind()) {
330 case TemplateArgument::Null:
331 case TemplateArgument::Declaration:
332 case TemplateArgument::Integral:
333 case TemplateArgument::NullPtr:
334 llvm_unreachable("Impossible TemplateArgument");
336 case TemplateArgument::Expression:
337 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
340 case TemplateArgument::Type:
341 ArgInfos[i] = TemplateArgumentLocInfo(
342 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
346 case TemplateArgument::Template:
347 case TemplateArgument::TemplateExpansion: {
348 NestedNameSpecifierLocBuilder Builder;
349 TemplateName Template = Args[i].getAsTemplate();
350 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
351 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
352 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
353 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
355 ArgInfos[i] = TemplateArgumentLocInfo(
356 Builder.getWithLocInContext(Context),
358 Args[i].getKind() == TemplateArgument::Template
364 case TemplateArgument::Pack:
365 ArgInfos[i] = TemplateArgumentLocInfo();