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 TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
46 #define ABSTRACT_TYPELOC(CLASS, PARENT)
47 #define TYPELOC(CLASS, PARENT) \
48 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
49 return TyLoc.getLocalDataAlignment(); \
51 #include "clang/AST/TypeLocNodes.def"
55 /// \brief Returns the alignment of the type source info data block.
56 unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
57 if (Ty.isNull()) return 1;
58 return TypeAligner().Visit(TypeLoc(Ty, 0));
62 class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
64 #define ABSTRACT_TYPELOC(CLASS, PARENT)
65 #define TYPELOC(CLASS, PARENT) \
66 unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
67 return TyLoc.getLocalDataSize(); \
69 #include "clang/AST/TypeLocNodes.def"
73 /// \brief Returns the size of the type source info data block.
74 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
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();
85 Total = llvm::RoundUpToAlignment(Total, MaxAlign);
90 class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
92 #define ABSTRACT_TYPELOC(CLASS, PARENT)
93 #define TYPELOC(CLASS, PARENT) \
94 TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
95 return TyLoc.getNextTypeLoc(); \
97 #include "clang/AST/TypeLocNodes.def"
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".
103 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
104 return NextLoc().Visit(TL);
107 /// \brief Initializes a type location, and all of its children
108 /// recursively, as if the entire tree had been written in the
110 void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
111 SourceLocation Loc) {
113 switch (TL.getTypeLocClass()) {
114 #define ABSTRACT_TYPELOC(CLASS, PARENT)
115 #define TYPELOC(CLASS, PARENT) \
117 CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \
118 TLCasted.initializeLocal(Context, Loc); \
119 TL = TLCasted.getNextTypeLoc(); \
123 #include "clang/AST/TypeLocNodes.def"
128 SourceLocation TypeLoc::getBeginLoc() const {
130 TypeLoc LeftMost = Cur;
132 switch (Cur.getTypeLocClass()) {
137 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()
138 ->hasTrailingReturn()) {
143 case FunctionNoProto:
145 case DependentSizedArray:
146 case IncompleteArray:
148 // FIXME: Currently QualifiedTypeLoc does not have a source range
150 Cur = Cur.getNextTypeLoc();
153 if (!Cur.getLocalSourceRange().getBegin().isInvalid())
155 Cur = Cur.getNextTypeLoc();
162 return LeftMost.getLocalSourceRange().getBegin();
165 SourceLocation TypeLoc::getEndLoc() const {
169 switch (Cur.getTypeLocClass()) {
173 return Last.getLocalSourceRange().getEnd();
176 case DependentSizedArray:
177 case IncompleteArray:
179 case FunctionNoProto:
183 if (Cur.castAs<FunctionProtoTypeLoc>().getTypePtr()->hasTrailingReturn())
191 case LValueReference:
192 case RValueReference:
201 Cur = Cur.getNextTypeLoc();
207 struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
208 // Overload resolution does the real work for us.
209 static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
210 static bool isTypeSpec(TypeLoc _) { return false; }
212 #define ABSTRACT_TYPELOC(CLASS, PARENT)
213 #define TYPELOC(CLASS, PARENT) \
214 bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
215 return isTypeSpec(TyLoc); \
217 #include "clang/AST/TypeLocNodes.def"
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.
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
230 bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) {
231 if (TL.getType().hasLocalQualifiers()) return false;
232 return TSTChecker().Visit(TL);
235 // Reimplemented to account for GNU/C++ extension
236 // typeof unary-expression
237 // where there are no parentheses.
238 SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
239 if (getRParenLoc().isValid())
240 return SourceRange(getTypeofLoc(), getRParenLoc());
242 return SourceRange(getTypeofLoc(),
243 getUnderlyingExpr()->getSourceRange().getEnd());
247 TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
248 if (needsExtraLocalData())
249 return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
250 switch (getTypePtr()->getKind()) {
251 case BuiltinType::Void:
253 case BuiltinType::Bool:
255 case BuiltinType::Char_U:
256 case BuiltinType::Char_S:
258 case BuiltinType::Char16:
260 case BuiltinType::Char32:
262 case BuiltinType::WChar_S:
263 case BuiltinType::WChar_U:
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.
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;
306 llvm_unreachable("Invalid BuiltinType Kind!");
309 TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
310 while (ParenTypeLoc PTL = TL.getAs<ParenTypeLoc>())
311 TL = PTL.getInnerLoc();
315 void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
316 SourceLocation Loc) {
317 setElaboratedKeywordLoc(Loc);
318 NestedNameSpecifierLocBuilder Builder;
319 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
320 setQualifierLoc(Builder.getWithLocInContext(Context));
323 void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
324 SourceLocation Loc) {
325 setElaboratedKeywordLoc(Loc);
326 NestedNameSpecifierLocBuilder Builder;
327 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
328 setQualifierLoc(Builder.getWithLocInContext(Context));
333 DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
334 SourceLocation Loc) {
335 setElaboratedKeywordLoc(Loc);
336 if (getTypePtr()->getQualifier()) {
337 NestedNameSpecifierLocBuilder Builder;
338 Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
339 setQualifierLoc(Builder.getWithLocInContext(Context));
341 setQualifierLoc(NestedNameSpecifierLoc());
343 setTemplateKeywordLoc(Loc);
344 setTemplateNameLoc(Loc);
347 TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
348 getTypePtr()->getArgs(),
352 void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
354 const TemplateArgument *Args,
355 TemplateArgumentLocInfo *ArgInfos,
356 SourceLocation Loc) {
357 for (unsigned i = 0, e = NumArgs; i != e; ++i) {
358 switch (Args[i].getKind()) {
359 case TemplateArgument::Null:
360 llvm_unreachable("Impossible TemplateArgument");
362 case TemplateArgument::Integral:
363 case TemplateArgument::Declaration:
364 case TemplateArgument::NullPtr:
365 ArgInfos[i] = TemplateArgumentLocInfo();
368 case TemplateArgument::Expression:
369 ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
372 case TemplateArgument::Type:
373 ArgInfos[i] = TemplateArgumentLocInfo(
374 Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
378 case TemplateArgument::Template:
379 case TemplateArgument::TemplateExpansion: {
380 NestedNameSpecifierLocBuilder Builder;
381 TemplateName Template = Args[i].getAsTemplateOrTemplatePattern();
382 if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
383 Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
384 else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
385 Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
387 ArgInfos[i] = TemplateArgumentLocInfo(
388 Builder.getWithLocInContext(Context), Loc,
389 Args[i].getKind() == TemplateArgument::Template ? SourceLocation()
394 case TemplateArgument::Pack:
395 ArgInfos[i] = TemplateArgumentLocInfo();