TypeLoc.cpp revision ea285162342df160e7860e26528bc7110bc6c0cd
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"
18using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// TypeLoc Implementation
22//===----------------------------------------------------------------------===//
23
24namespace {
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.getSourceRange(); \
31    }
32#include "clang/AST/TypeLocNodes.def"
33  };
34}
35
36SourceRange TypeLoc::getSourceRangeImpl(TypeLoc TL) {
37  if (TL.isNull()) return SourceRange();
38  return TypeLocRanger().Visit(TL);
39}
40
41namespace {
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.
54unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55  if (Ty.isNull()) return 0;
56  return TypeSizer().Visit(TypeLoc(Ty, 0));
57}
58
59namespace {
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".
73TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74  return NextLoc().Visit(TL);
75}
76
77namespace {
78  struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
79    SourceLocation Loc;
80    TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
81
82#define ABSTRACT_TYPELOC(CLASS, PARENT)
83#define TYPELOC(CLASS, PARENT) \
84    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
85      TyLoc.initializeLocal(Loc); \
86    }
87#include "clang/AST/TypeLocNodes.def"
88  };
89}
90
91/// \brief Initializes a type location, and all of its children
92/// recursively, as if the entire tree had been written in the
93/// given location.
94void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
95  do {
96    TypeLocInitializer(Loc).Visit(TL);
97  } while ((TL = TL.getNextTypeLoc()));
98}
99
100namespace {
101  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
102    // Overload resolution does the real work for us.
103    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
104    static bool isTypeSpec(TypeLoc _) { return false; }
105
106#define ABSTRACT_TYPELOC(CLASS, PARENT)
107#define TYPELOC(CLASS, PARENT) \
108    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
109      return isTypeSpec(TyLoc); \
110    }
111#include "clang/AST/TypeLocNodes.def"
112  };
113}
114
115
116/// \brief Determines if the given type loc corresponds to a
117/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
118/// the type hierarchy, this is made somewhat complicated.
119///
120/// There are a lot of types that currently use TypeSpecTypeLoc
121/// because it's a convenient base class.  Ideally we would not accept
122/// those here, but ideally we would have better implementations for
123/// them.
124bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
125  if (TL->getType().hasLocalQualifiers()) return false;
126  return TSTChecker().Visit(*TL);
127}
128
129// Reimplemented to account for GNU/C++ extension
130//     typeof unary-expression
131// where there are no parentheses.
132SourceRange TypeOfExprTypeLoc::getSourceRange() const {
133  if (getRParenLoc().isValid())
134    return SourceRange(getTypeofLoc(), getRParenLoc());
135  else
136    return SourceRange(getTypeofLoc(),
137                       getUnderlyingExpr()->getSourceRange().getEnd());
138}
139
140
141TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
142  if (needsExtraLocalData())
143    return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
144  else {
145    switch (getTypePtr()->getKind()) {
146    case BuiltinType::Void:
147      return TST_void;
148    case BuiltinType::Bool:
149      return TST_bool;
150    case BuiltinType::Char_U:
151    case BuiltinType::Char_S:
152      return TST_char;
153    case BuiltinType::Char16:
154      return TST_char16;
155    case BuiltinType::Char32:
156      return TST_char32;
157    case BuiltinType::WChar:
158      return TST_wchar;
159    case BuiltinType::UndeducedAuto:
160      return TST_auto;
161
162    case BuiltinType::UChar:
163    case BuiltinType::UShort:
164    case BuiltinType::UInt:
165    case BuiltinType::ULong:
166    case BuiltinType::ULongLong:
167    case BuiltinType::UInt128:
168    case BuiltinType::SChar:
169    case BuiltinType::Short:
170    case BuiltinType::Int:
171    case BuiltinType::Long:
172    case BuiltinType::LongLong:
173    case BuiltinType::Int128:
174    case BuiltinType::Float:
175    case BuiltinType::Double:
176    case BuiltinType::LongDouble:
177      llvm_unreachable("Builtin type needs extra local data!");
178      // Fall through, if the impossible happens.
179
180    case BuiltinType::NullPtr:
181    case BuiltinType::Overload:
182    case BuiltinType::Dependent:
183    case BuiltinType::ObjCId:
184    case BuiltinType::ObjCClass:
185    case BuiltinType::ObjCSel:
186      return TST_unspecified;
187    }
188  }
189
190  return TST_unspecified;
191}
192