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 "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;
21 //===----------------------------------------------------------------------===//
22 // TypeLoc Implementation
23 //===----------------------------------------------------------------------===//
26 class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
28 #define ABSTRACT_TYPELOC(CLASS, PARENT)
29 #define TYPELOC(CLASS, PARENT) \
30 SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
31 return TyLoc.getLocalSourceRange(); \
33 #include "clang/AST/TypeLocNodes.def"
37 SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
38 if (TL.isNull()) return SourceRange();
39 return TypeLocRanger().Visit(TL);
43 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
45 #define ABSTRACT_TYPELOC(CLASS, PARENT)
46 #define TYPELOC(CLASS, PARENT) \
47 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
48 return TyLoc.getFullDataSize(); \
50 #include "clang/AST/TypeLocNodes.def"
54 /// \brief Returns the size of the type source info data block.
55 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
56 if (Ty.isNull()) return 0;
57 return TypeSizer().Visit(TypeLoc(Ty, 0));
61 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
63 #define ABSTRACT_TYPELOC(CLASS, PARENT)
64 #define TYPELOC(CLASS, PARENT) \
65 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
66 return TyLoc.getNextTypeLoc(); \
68 #include "clang/AST/TypeLocNodes.def"
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".
74 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
75 return NextLoc().Visit(TL);
78 /// \brief Initializes a type location, and all of its children
79 /// recursively, as if the entire tree had been written in the
81 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
84 switch (TL.getTypeLocClass()) {
85 #define ABSTRACT_TYPELOC(CLASS, PARENT)
86 #define TYPELOC(CLASS, PARENT) \
88 CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
89 TLCasted.initializeLocal(Context, Loc); \
90 TL = TLCasted.getNextTypeLoc(); \
94 #include "clang/AST/TypeLocNodes.def"
99 SourceLocation TypeLoc::getBeginLoc() const {
102 switch (Cur.getTypeLocClass()) {
103 // FIXME: Currently QualifiedTypeLoc does not have a source range
107 case DependentTemplateSpecialization:
110 TypeLoc Next = Cur.getNextTypeLoc();
111 if (Next.isNull()) break;
117 return Cur.getLocalSourceRange().getBegin();
120 SourceLocation TypeLoc::getEndLoc() const {
124 switch (Cur.getTypeLocClass()) {
128 return Last.getLocalSourceRange().getEnd();
131 case DependentSizedArray:
132 case IncompleteArray:
135 case FunctionNoProto:
141 case LValueReference:
142 case RValueReference:
151 Cur = Cur.getNextTypeLoc();
157 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
158 // Overload resolution does the real work for us.
159 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
160 static bool isTypeSpec(TypeLoc _) { return false; }
162 #define ABSTRACT_TYPELOC(CLASS, PARENT)
163 #define TYPELOC(CLASS, PARENT) \
164 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
165 return isTypeSpec(TyLoc); \
167 #include "clang/AST/TypeLocNodes.def"
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.
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
180 bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
181 if (TL->getType().hasLocalQualifiers()) return false;
182 return TSTChecker().Visit(*TL);
185 // Reimplemented to account for GNU/C++ extension
186 // typeof unary-expression
187 // where there are no parentheses.
188 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
189 if (getRParenLoc().isValid())
190 return SourceRange(getTypeofLoc(), getRParenLoc());
192 return SourceRange(getTypeofLoc(),
193 getUnderlyingExpr()->getSourceRange().getEnd());
197 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
198 if (needsExtraLocalData())
199 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
200 switch (getTypePtr()->getKind()) {
201 case BuiltinType::Void:
203 case BuiltinType::Bool:
205 case BuiltinType::Char_U:
206 case BuiltinType::Char_S:
208 case BuiltinType::Char16:
210 case BuiltinType::Char32:
212 case BuiltinType::WChar_S:
213 case BuiltinType::WChar_U:
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.
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;
248 llvm_unreachable("Invalid BuiltinType Kind!");
251 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
252 while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
253 TL = PTL->getInnerLoc();
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));
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));
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));
283 setQualifierLoc(NestedNameSpecifierLoc());
285 setTemplateKeywordLoc(Loc);
286 setTemplateNameLoc(Loc);
289 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
290 getTypePtr()->getArgs(),
294 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
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());
309 case TemplateArgument::Type:
310 ArgInfos[i] = TemplateArgumentLocInfo(
311 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
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);
324 ArgInfos[i] = TemplateArgumentLocInfo(
325 Builder.getWithLocInContext(Context),
327 Args[i].getKind() == TemplateArgument::Template