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 "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;
21
22 //===----------------------------------------------------------------------===//
23 // TypeLoc Implementation
24 //===----------------------------------------------------------------------===//
25
26 namespace {
27 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
28 public:
29 #define ABSTRACT_TYPELOC(CLASS, PARENT)
30 #define TYPELOC(CLASS, PARENT) \
31 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
32 return TyLoc.getLocalSourceRange(); \
33 }
34 #include "clang/AST/TypeLocNodes.def"
35 };
36 }
37
getLocalSourceRangeImpl(TypeLoc TL)38 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
39 if (TL.isNull()) return SourceRange();
40 return TypeLocRanger().Visit(TL);
41 }
42
43 namespace {
44 class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
45 public:
46 #define ABSTRACT_TYPELOC(CLASS, PARENT)
47 #define TYPELOC(CLASS, PARENT) \
48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
49 return TyLoc.getLocalDataAlignment(); \
50 }
51 #include "clang/AST/TypeLocNodes.def"
52 };
53 }
54
55 /// \brief Returns the alignment of the type source info data block.
getLocalAlignmentForType(QualType Ty)56 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
57 if (Ty.isNull()) return 1;
58 return TypeAligner().Visit(TypeLoc(Ty, nullptr));
59 }
60
61 namespace {
62 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
63 public:
64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
65 #define TYPELOC(CLASS, PARENT) \
66 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67 return TyLoc.getLocalDataSize(); \
68 }
69 #include "clang/AST/TypeLocNodes.def"
70 };
71 }
72
73 /// \brief Returns the size of the type source info data block.
getFullDataSizeForType(QualType Ty)74 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
75 unsigned Total = 0;
76 TypeLoc TyLoc(Ty, nullptr);
77 unsigned MaxAlign = 1;
78 while (!TyLoc.isNull()) {
79 unsigned Align = getLocalAlignmentForType(TyLoc.getType());
80 MaxAlign = std::max(Align, MaxAlign);
81 Total = llvm::RoundUpToAlignment(Total, Align);
82 Total += TypeSizer().Visit(TyLoc);
83 TyLoc = TyLoc.getNextTypeLoc();
84 }
85 Total = llvm::RoundUpToAlignment(Total, MaxAlign);
86 return Total;
87 }
88
89 namespace {
90 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
91 public:
92 #define ABSTRACT_TYPELOC(CLASS, PARENT)
93 #define TYPELOC(CLASS, PARENT) \
94 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
95 return TyLoc.getNextTypeLoc(); \
96 }
97 #include "clang/AST/TypeLocNodes.def"
98 };
99 }
100
101 /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
102 /// TypeLoc is a PointerLoc and next TypeLoc is for "int".
getNextTypeLocImpl(TypeLoc TL)103 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
104 return NextLoc().Visit(TL);
105 }
106
107 /// \brief Initializes a type location, and all of its children
108 /// recursively, as if the entire tree had been written in the
109 /// given location.
initializeImpl(ASTContext & Context,TypeLoc TL,SourceLocation Loc)110 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
111 SourceLocation Loc) {
112 while (true) {
113 switch (TL.getTypeLocClass()) {
114 #define ABSTRACT_TYPELOC(CLASS, PARENT)
115 #define TYPELOC(CLASS, PARENT) \
116 case CLASS: { \
117 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
118 TLCasted.initializeLocal(Context, Loc); \
119 TL = TLCasted.getNextTypeLoc(); \
120 if (!TL) return; \
121 continue; \
122 }
123 #include "clang/AST/TypeLocNodes.def"
124 }
125 }
126 }
127
getBeginLoc() const128 SourceLocation TypeLoc::getBeginLoc() const {
129 TypeLoc Cur = *this;
130 TypeLoc LeftMost = Cur;
131 while (true) {
132 switch (Cur.getTypeLocClass()) {
133 case Elaborated:
134 LeftMost = Cur;
135 break;
136 case FunctionProto:
137 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
138 ->hasTrailingReturn()) {
139 LeftMost = Cur;
140 break;
141 }
142 /* Fall through */
143 case FunctionNoProto:
144 case ConstantArray:
145 case DependentSizedArray:
146 case IncompleteArray:
147 case VariableArray:
148 // FIXME: Currently QualifiedTypeLoc does not have a source range
149 case Qualified:
150 Cur = Cur.getNextTypeLoc();
151 continue;
152 default:
153 if (!Cur.getLocalSourceRange().getBegin().isInvalid())
154 LeftMost = Cur;
155 Cur = Cur.getNextTypeLoc();
156 if (Cur.isNull())
157 break;
158 continue;
159 } // switch
160 break;
161 } // while
162 return LeftMost.getLocalSourceRange().getBegin();
163 }
164
getEndLoc() const165 SourceLocation TypeLoc::getEndLoc() const {
166 TypeLoc Cur = *this;
167 TypeLoc Last;
168 while (true) {
169 switch (Cur.getTypeLocClass()) {
170 default:
171 if (!Last)
172 Last = Cur;
173 return Last.getLocalSourceRange().getEnd();
174 case Paren:
175 case ConstantArray:
176 case DependentSizedArray:
177 case IncompleteArray:
178 case VariableArray:
179 case FunctionNoProto:
180 Last = Cur;
181 break;
182 case FunctionProto:
183 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
184 Last = TypeLoc();
185 else
186 Last = Cur;
187 break;
188 case Pointer:
189 case BlockPointer:
190 case MemberPointer:
191 case LValueReference:
192 case RValueReference:
193 case PackExpansion:
194 if (!Last)
195 Last = Cur;
196 break;
197 case Qualified:
198 case Elaborated:
199 break;
200 }
201 Cur = Cur.getNextTypeLoc();
202 }
203 }
204
205
206 namespace {
207 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
208 // Overload resolution does the real work for us.
isTypeSpec__anone4cb4f9c0511::TSTChecker209 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
isTypeSpec__anone4cb4f9c0511::TSTChecker210 static bool isTypeSpec(TypeLoc _) { return false; }
211
212 #define ABSTRACT_TYPELOC(CLASS, PARENT)
213 #define TYPELOC(CLASS, PARENT) \
214 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
215 return isTypeSpec(TyLoc); \
216 }
217 #include "clang/AST/TypeLocNodes.def"
218 };
219 }
220
221
222 /// \brief Determines if the given type loc corresponds to a
223 /// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
224 /// the type hierarchy, this is made somewhat complicated.
225 ///
226 /// There are a lot of types that currently use TypeSpecTypeLoc
227 /// because it's a convenient base class. Ideally we would not accept
228 /// those here, but ideally we would have better implementations for
229 /// them.
isKind(const TypeLoc & TL)230 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
231 if (TL.getType().hasLocalQualifiers()) return false;
232 return TSTChecker().Visit(TL);
233 }
234
235 // Reimplemented to account for GNU/C++ extension
236 // typeof unary-expression
237 // where there are no parentheses.
getLocalSourceRange() const238 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
239 if (getRParenLoc().isValid())
240 return SourceRange(getTypeofLoc(), getRParenLoc());
241 else
242 return SourceRange(getTypeofLoc(),
243 getUnderlyingExpr()->getSourceRange().getEnd());
244 }
245
246
getWrittenTypeSpec() const247 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
248 if (needsExtraLocalData())
249 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
250 switch (getTypePtr()->getKind()) {
251 case BuiltinType::Void:
252 return TST_void;
253 case BuiltinType::Bool:
254 return TST_bool;
255 case BuiltinType::Char_U:
256 case BuiltinType::Char_S:
257 return TST_char;
258 case BuiltinType::Char16:
259 return TST_char16;
260 case BuiltinType::Char32:
261 return TST_char32;
262 case BuiltinType::WChar_S:
263 case BuiltinType::WChar_U:
264 return TST_wchar;
265 case BuiltinType::UChar:
266 case BuiltinType::UShort:
267 case BuiltinType::UInt:
268 case BuiltinType::ULong:
269 case BuiltinType::ULongLong:
270 case BuiltinType::UInt128:
271 case BuiltinType::SChar:
272 case BuiltinType::Short:
273 case BuiltinType::Int:
274 case BuiltinType::Long:
275 case BuiltinType::LongLong:
276 case BuiltinType::Int128:
277 case BuiltinType::Half:
278 case BuiltinType::Float:
279 case BuiltinType::Double:
280 case BuiltinType::LongDouble:
281 llvm_unreachable("Builtin type needs extra local data!");
282 // Fall through, if the impossible happens.
283
284 case BuiltinType::NullPtr:
285 case BuiltinType::Overload:
286 case BuiltinType::Dependent:
287 case BuiltinType::BoundMember:
288 case BuiltinType::UnknownAny:
289 case BuiltinType::ARCUnbridgedCast:
290 case BuiltinType::PseudoObject:
291 case BuiltinType::ObjCId:
292 case BuiltinType::ObjCClass:
293 case BuiltinType::ObjCSel:
294 case BuiltinType::OCLImage1d:
295 case BuiltinType::OCLImage1dArray:
296 case BuiltinType::OCLImage1dBuffer:
297 case BuiltinType::OCLImage2d:
298 case BuiltinType::OCLImage2dArray:
299 case BuiltinType::OCLImage3d:
300 case BuiltinType::OCLSampler:
301 case BuiltinType::OCLEvent:
302 case BuiltinType::BuiltinFn:
303 return TST_unspecified;
304 }
305
306 llvm_unreachable("Invalid BuiltinType Kind!");
307 }
308
IgnoreParensImpl(TypeLoc TL)309 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
310 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
311 TL = PTL.getInnerLoc();
312 return TL;
313 }
314
initializeLocal(ASTContext & Context,SourceLocation Loc)315 void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
316 SourceLocation Loc) {
317 TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
318 ::initializeLocal(Context, Loc);
319 this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
320 getUnderlyingType(), Loc);
321 }
322
initializeLocal(ASTContext & Context,SourceLocation Loc)323 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
324 SourceLocation Loc) {
325 setElaboratedKeywordLoc(Loc);
326 NestedNameSpecifierLocBuilder Builder;
327 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
328 setQualifierLoc(Builder.getWithLocInContext(Context));
329 }
330
initializeLocal(ASTContext & Context,SourceLocation Loc)331 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
332 SourceLocation Loc) {
333 setElaboratedKeywordLoc(Loc);
334 NestedNameSpecifierLocBuilder Builder;
335 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
336 setQualifierLoc(Builder.getWithLocInContext(Context));
337 setNameLoc(Loc);
338 }
339
340 void
initializeLocal(ASTContext & Context,SourceLocation Loc)341 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
342 SourceLocation Loc) {
343 setElaboratedKeywordLoc(Loc);
344 if (getTypePtr()->getQualifier()) {
345 NestedNameSpecifierLocBuilder Builder;
346 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
347 setQualifierLoc(Builder.getWithLocInContext(Context));
348 } else {
349 setQualifierLoc(NestedNameSpecifierLoc());
350 }
351 setTemplateKeywordLoc(Loc);
352 setTemplateNameLoc(Loc);
353 setLAngleLoc(Loc);
354 setRAngleLoc(Loc);
355 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
356 getTypePtr()->getArgs(),
357 getArgInfos(), Loc);
358 }
359
initializeArgLocs(ASTContext & Context,unsigned NumArgs,const TemplateArgument * Args,TemplateArgumentLocInfo * ArgInfos,SourceLocation Loc)360 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
361 unsigned NumArgs,
362 const TemplateArgument *Args,
363 TemplateArgumentLocInfo *ArgInfos,
364 SourceLocation Loc) {
365 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
366 switch (Args[i].getKind()) {
367 case TemplateArgument::Null:
368 llvm_unreachable("Impossible TemplateArgument");
369
370 case TemplateArgument::Integral:
371 case TemplateArgument::Declaration:
372 case TemplateArgument::NullPtr:
373 ArgInfos[i] = TemplateArgumentLocInfo();
374 break;
375
376 case TemplateArgument::Expression:
377 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
378 break;
379
380 case TemplateArgument::Type:
381 ArgInfos[i] = TemplateArgumentLocInfo(
382 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
383 Loc));
384 break;
385
386 case TemplateArgument::Template:
387 case TemplateArgument::TemplateExpansion: {
388 NestedNameSpecifierLocBuilder Builder;
389 TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
390 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
391 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
392 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
393 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
394
395 ArgInfos[i] = TemplateArgumentLocInfo(
396 Builder.getWithLocInContext(Context), Loc,
397 Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
398 : Loc);
399 break;
400 }
401
402 case TemplateArgument::Pack:
403 ArgInfos[i] = TemplateArgumentLocInfo();
404 break;
405 }
406 }
407 }
408