aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/TypeLoc.cpp
blob: 04e708370af3dfb003f60a371a46e7427d88ab61 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the TypeLoc subclasses implementations.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/raw_ostream.h"
#include "clang/AST/TypeLocVisitor.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// TypeLoc Implementation
//===----------------------------------------------------------------------===//

namespace {

/// \brief Return the source range for the visited TypeSpecLoc.
class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
public:
#define ABSTRACT_TYPELOC(CLASS)
#define TYPELOC(CLASS, PARENT) \
    SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); }
#include "clang/AST/TypeLocNodes.def"

  SourceRange VisitTypeLoc(TypeLoc TyLoc) {
    assert(0 && "A typeloc wrapper was not handled!");
    return SourceRange();
  }
};

}

SourceRange TypeLoc::getSourceRange() const {
  if (isNull())
    return SourceRange();
  return TypeLocRanger().Visit(*this);
}

/// \brief Find the TypeSpecLoc that is part of this TypeLoc.
TypeSpecLoc TypeLoc::getTypeSpecLoc() const {
  if (isNull())
    return TypeSpecLoc();
  UnqualTypeLoc Cur = getUnqualifiedLoc();
  if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur))
    return DL->getTypeSpecLoc();
  return cast<TypeSpecLoc>(Cur);
}

namespace {

/// \brief Report the full source info data size for the visited TypeLoc.
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
public:
#define ABSTRACT_TYPELOC(CLASS)
#define TYPELOC(CLASS, PARENT) \
    unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); }
#include "clang/AST/TypeLocNodes.def"

  unsigned VisitTypeLoc(TypeLoc TyLoc) {
    assert(0 && "A type loc wrapper was not handled!");
    return 0;
  }
};

}

/// \brief Returns the size of the type source info data block.
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
  if (Ty.isNull()) return 0;
  return TypeSizer().Visit(TypeLoc(Ty, 0));
}

namespace {

/// \brief Return the "next" TypeLoc for the visited TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
public:
#define TYPELOC(CLASS, PARENT)
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
  TypeLoc Visit##CLASS(CLASS TyLoc);
#include "clang/AST/TypeLocNodes.def"

  TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); }
  TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
  TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
    return TyLoc.getUnqualifiedLoc();
  }

  TypeLoc VisitTypeLoc(TypeLoc TyLoc) {
    assert(0 && "A declarator loc wrapper was not handled!");
    return TypeLoc();
  }
};

}

TypeLoc NextLoc::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
  return TL.getBaseTypeLoc();
}

TypeLoc NextLoc::VisitPointerLoc(PointerLoc TL) {
  return TL.getPointeeLoc();
}
TypeLoc NextLoc::VisitMemberPointerLoc(MemberPointerLoc TL) {
  return TL.getPointeeLoc();
}
TypeLoc NextLoc::VisitBlockPointerLoc(BlockPointerLoc TL) {
  return TL.getPointeeLoc();
}
TypeLoc NextLoc::VisitReferenceLoc(ReferenceLoc TL) {
  return TL.getPointeeLoc();
}
TypeLoc NextLoc::VisitFunctionLoc(FunctionLoc TL) {
  return TL.getResultLoc();
}
TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) {
  return TL.getElementLoc();
}

/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
TypeLoc TypeLoc::getNextTypeLoc() const {
  //llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n";
  TypeLoc Tmp = NextLoc().Visit(*this);
  //llvm::errs() << "  result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n";
  return Tmp;
}

//===----------------------------------------------------------------------===//
// TypeSpecLoc Implementation
//===----------------------------------------------------------------------===//

namespace {
class TypeSpecChecker : public TypeLocVisitor<TypeSpecChecker, bool> {
public:
  bool VisitTypeSpecLoc(TypeSpecLoc TyLoc) { return true; }
};

}

bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) {
  return TypeSpecChecker().Visit(*TL);
}

//===----------------------------------------------------------------------===//
// DeclaratorLoc Implementation
//===----------------------------------------------------------------------===//

namespace {

/// \brief Return the TypeSpecLoc for the visited DeclaratorLoc.
class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> {
public:
#define TYPELOC(CLASS, PARENT)
#define DECLARATOR_TYPELOC(CLASS, TYPE) \
    TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); }
#include "clang/AST/TypeLocNodes.def"

  TypeSpecLoc VisitTypeLoc(TypeLoc TyLoc) {
    assert(0 && "A declarator loc wrapper was not handled!");
    return TypeSpecLoc();
  }

  TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
    return Visit(TyLoc.getUnqualifiedLoc());
  }
};

}

/// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc.
TypeSpecLoc DeclaratorLoc::getTypeSpecLoc() const {
  return TypeSpecGetter().Visit(*this);
}

namespace {

class DeclaratorLocChecker : public TypeLocVisitor<DeclaratorLocChecker, bool> {
public:
  bool VisitDeclaratorLoc(DeclaratorLoc TyLoc) { return true; }
};

}

bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) {
  return DeclaratorLocChecker().Visit(*TL);
}

//===----------------------------------------------------------------------===//
// DefaultTypeSpecLoc Implementation
//===----------------------------------------------------------------------===//

namespace {

class DefaultTypeSpecLocChecker :
                        public TypeLocVisitor<DefaultTypeSpecLocChecker, bool> {
public:
  bool VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { return true; }
};

}

bool DefaultTypeSpecLoc::classofType(const Type *Ty) {
  return
    DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0));
}