1 //===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the TypeLoc subclasses implementations.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/raw_ostream.h"
15 #include "clang/AST/TypeLocVisitor.h"
16 #include "clang/AST/Expr.h"
17 #include "llvm/Support/ErrorHandling.h"
18 using namespace clang;
19
20 //===----------------------------------------------------------------------===//
21 // TypeLoc Implementation
22 //===----------------------------------------------------------------------===//
23
24 namespace {
25 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
26 public:
27 #define ABSTRACT_TYPELOC(CLASS, PARENT)
28 #define TYPELOC(CLASS, PARENT) \
29 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
30 return TyLoc.getLocalSourceRange(); \
31 }
32 #include "clang/AST/TypeLocNodes.def"
33 };
34 }
35
getLocalSourceRangeImpl(TypeLoc TL)36 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
37 if (TL.isNull()) return SourceRange();
38 return TypeLocRanger().Visit(TL);
39 }
40
41 namespace {
42 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
43 public:
44 #define ABSTRACT_TYPELOC(CLASS, PARENT)
45 #define TYPELOC(CLASS, PARENT) \
46 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
47 return TyLoc.getFullDataSize(); \
48 }
49 #include "clang/AST/TypeLocNodes.def"
50 };
51 }
52
53 /// \brief Returns the size of the type source info data block.
getFullDataSizeForType(QualType Ty)54 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55 if (Ty.isNull()) return 0;
56 return TypeSizer().Visit(TypeLoc(Ty, 0));
57 }
58
59 namespace {
60 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
61 public:
62 #define ABSTRACT_TYPELOC(CLASS, PARENT)
63 #define TYPELOC(CLASS, PARENT) \
64 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
65 return TyLoc.getNextTypeLoc(); \
66 }
67 #include "clang/AST/TypeLocNodes.def"
68 };
69 }
70
71 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
72 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
getNextTypeLocImpl(TypeLoc TL)73 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74 return NextLoc().Visit(TL);
75 }
76
77 /// \brief Initializes a type location, and all of its children
78 /// recursively, as if the entire tree had been written in the
79 /// given location.
initializeImpl(ASTContext & Context,TypeLoc TL,SourceLocation Loc)80 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
81 SourceLocation Loc) {
82 while (true) {
83 switch (TL.getTypeLocClass()) {
84 #define ABSTRACT_TYPELOC(CLASS, PARENT)
85 #define TYPELOC(CLASS, PARENT) \
86 case CLASS: { \
87 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
88 TLCasted.initializeLocal(Context, Loc); \
89 TL = TLCasted.getNextTypeLoc(); \
90 if (!TL) return; \
91 continue; \
92 }
93 #include "clang/AST/TypeLocNodes.def"
94 }
95 }
96 }
97
getBeginLoc() const98 SourceLocation TypeLoc::getBeginLoc() const {
99 TypeLoc Cur = *this;
100 while (true) {
101 switch (Cur.getTypeLocClass()) {
102 // FIXME: Currently QualifiedTypeLoc does not have a source range
103 // case Qualified:
104 case Elaborated:
105 case DependentName:
106 case DependentTemplateSpecialization:
107 break;
108 default:
109 TypeLoc Next = Cur.getNextTypeLoc();
110 if (Next.isNull()) break;
111 Cur = Next;
112 continue;
113 }
114 break;
115 }
116 return Cur.getLocalSourceRange().getBegin();
117 }
118
getEndLoc() const119 SourceLocation TypeLoc::getEndLoc() const {
120 TypeLoc Cur = *this;
121 TypeLoc Last;
122 while (true) {
123 switch (Cur.getTypeLocClass()) {
124 default:
125 if (!Last)
126 Last = Cur;
127 return Last.getLocalSourceRange().getEnd();
128 case Paren:
129 case ConstantArray:
130 case DependentSizedArray:
131 case IncompleteArray:
132 case VariableArray:
133 case FunctionProto:
134 case FunctionNoProto:
135 Last = Cur;
136 break;
137 case Pointer:
138 case BlockPointer:
139 case MemberPointer:
140 case LValueReference:
141 case RValueReference:
142 case PackExpansion:
143 if (!Last)
144 Last = Cur;
145 break;
146 case Qualified:
147 case Elaborated:
148 break;
149 }
150 Cur = Cur.getNextTypeLoc();
151 }
152 }
153
154
155 namespace {
156 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
157 // Overload resolution does the real work for us.
isTypeSpec__anon488044570411::TSTChecker158 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
isTypeSpec__anon488044570411::TSTChecker159 static bool isTypeSpec(TypeLoc _) { return false; }
160
161 #define ABSTRACT_TYPELOC(CLASS, PARENT)
162 #define TYPELOC(CLASS, PARENT) \
163 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
164 return isTypeSpec(TyLoc); \
165 }
166 #include "clang/AST/TypeLocNodes.def"
167 };
168 }
169
170
171 /// \brief Determines if the given type loc corresponds to a
172 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
173 /// the type hierarchy, this is made somewhat complicated.
174 ///
175 /// There are a lot of types that currently use TypeSpecTypeLoc
176 /// because it's a convenient base class. Ideally we would not accept
177 /// those here, but ideally we would have better implementations for
178 /// them.
classof(const TypeLoc * TL)179 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
180 if (TL->getType().hasLocalQualifiers()) return false;
181 return TSTChecker().Visit(*TL);
182 }
183
184 // Reimplemented to account for GNU/C++ extension
185 // typeof unary-expression
186 // where there are no parentheses.
getLocalSourceRange() const187 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
188 if (getRParenLoc().isValid())
189 return SourceRange(getTypeofLoc(), getRParenLoc());
190 else
191 return SourceRange(getTypeofLoc(),
192 getUnderlyingExpr()->getSourceRange().getEnd());
193 }
194
195
getWrittenTypeSpec() const196 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
197 if (needsExtraLocalData())
198 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
199 switch (getTypePtr()->getKind()) {
200 case BuiltinType::Void:
201 return TST_void;
202 case BuiltinType::Bool:
203 return TST_bool;
204 case BuiltinType::Char_U:
205 case BuiltinType::Char_S:
206 return TST_char;
207 case BuiltinType::Char16:
208 return TST_char16;
209 case BuiltinType::Char32:
210 return TST_char32;
211 case BuiltinType::WChar_S:
212 case BuiltinType::WChar_U:
213 return TST_wchar;
214 case BuiltinType::UChar:
215 case BuiltinType::UShort:
216 case BuiltinType::UInt:
217 case BuiltinType::ULong:
218 case BuiltinType::ULongLong:
219 case BuiltinType::UInt128:
220 case BuiltinType::SChar:
221 case BuiltinType::Short:
222 case BuiltinType::Int:
223 case BuiltinType::Long:
224 case BuiltinType::LongLong:
225 case BuiltinType::Int128:
226 case BuiltinType::Half:
227 case BuiltinType::Float:
228 case BuiltinType::Double:
229 case BuiltinType::LongDouble:
230 llvm_unreachable("Builtin type needs extra local data!");
231 // Fall through, if the impossible happens.
232
233 case BuiltinType::NullPtr:
234 case BuiltinType::Overload:
235 case BuiltinType::Dependent:
236 case BuiltinType::BoundMember:
237 case BuiltinType::UnknownAny:
238 case BuiltinType::ARCUnbridgedCast:
239 case BuiltinType::PseudoObject:
240 case BuiltinType::ObjCId:
241 case BuiltinType::ObjCClass:
242 case BuiltinType::ObjCSel:
243 return TST_unspecified;
244 }
245
246 llvm_unreachable("Invalid BuiltinType Kind!");
247 }
248
IgnoreParensImpl(TypeLoc TL)249 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
250 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
251 TL = PTL->getInnerLoc();
252 return TL;
253 }
254
initializeLocal(ASTContext & Context,SourceLocation Loc)255 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
256 SourceLocation Loc) {
257 setElaboratedKeywordLoc(Loc);
258 NestedNameSpecifierLocBuilder Builder;
259 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
260 setQualifierLoc(Builder.getWithLocInContext(Context));
261 }
262
initializeLocal(ASTContext & Context,SourceLocation Loc)263 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
264 SourceLocation Loc) {
265 setElaboratedKeywordLoc(Loc);
266 NestedNameSpecifierLocBuilder Builder;
267 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
268 setQualifierLoc(Builder.getWithLocInContext(Context));
269 setNameLoc(Loc);
270 }
271
272 void
initializeLocal(ASTContext & Context,SourceLocation Loc)273 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
274 SourceLocation Loc) {
275 setElaboratedKeywordLoc(Loc);
276 if (getTypePtr()->getQualifier()) {
277 NestedNameSpecifierLocBuilder Builder;
278 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
279 setQualifierLoc(Builder.getWithLocInContext(Context));
280 } else {
281 setQualifierLoc(NestedNameSpecifierLoc());
282 }
283 setTemplateKeywordLoc(Loc);
284 setTemplateNameLoc(Loc);
285 setLAngleLoc(Loc);
286 setRAngleLoc(Loc);
287 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
288 getTypePtr()->getArgs(),
289 getArgInfos(), Loc);
290 }
291
initializeArgLocs(ASTContext & Context,unsigned NumArgs,const TemplateArgument * Args,TemplateArgumentLocInfo * ArgInfos,SourceLocation Loc)292 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
293 unsigned NumArgs,
294 const TemplateArgument *Args,
295 TemplateArgumentLocInfo *ArgInfos,
296 SourceLocation Loc) {
297 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
298 switch (Args[i].getKind()) {
299 case TemplateArgument::Null:
300 case TemplateArgument::Declaration:
301 case TemplateArgument::Integral:
302 case TemplateArgument::Pack:
303 case TemplateArgument::Expression:
304 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
305 break;
306
307 case TemplateArgument::Type:
308 ArgInfos[i] = TemplateArgumentLocInfo(
309 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
310 Loc));
311 break;
312
313 case TemplateArgument::Template:
314 case TemplateArgument::TemplateExpansion: {
315 NestedNameSpecifierLocBuilder Builder;
316 TemplateName Template = Args[i].getAsTemplate();
317 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
318 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
319 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
320 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
321
322 ArgInfos[i] = TemplateArgumentLocInfo(
323 Builder.getWithLocInContext(Context),
324 Loc,
325 Args[i].getKind() == TemplateArgument::Template
326 ? SourceLocation()
327 : Loc);
328 break;
329 }
330 }
331 }
332 }
333