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