]> granicus.if.org Git - clang/blob - lib/AST/TypeLoc.cpp
Improve source-location information for builtin TypeLocs, from Enea
[clang] / lib / AST / TypeLoc.cpp
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"
18 using namespace clang;
19
20 //===----------------------------------------------------------------------===//
21 // TypeLoc Implementation
22 //===----------------------------------------------------------------------===//
23
24 namespace {
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
36 SourceRange TypeLoc::getSourceRangeImpl(TypeLoc TL) {
37   if (TL.isNull()) return SourceRange();
38   return TypeLocRanger().Visit(TL);
39 }
40
41 namespace {
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.
54 unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
55   if (Ty.isNull()) return 0;
56   return TypeSizer().Visit(TypeLoc(Ty, 0));
57 }
58
59 namespace {
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".
73 TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
74   return NextLoc().Visit(TL);
75 }
76
77 namespace {
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.
94 void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
95   do {
96     TypeLocInitializer(Loc).Visit(TL);
97   } while ((TL = TL.getNextTypeLoc()));
98 }
99
100 namespace {
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.
124 bool 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.
132 SourceRange 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
141 TypeSpecifierType 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::Float:
160       return TST_float;
161     case BuiltinType::Double:
162     case BuiltinType::LongDouble:
163       return TST_double;
164     case BuiltinType::UndeducedAuto:
165       return TST_auto;
166         
167     case BuiltinType::UChar:
168     case BuiltinType::UShort:
169     case BuiltinType::UInt:
170     case BuiltinType::ULong:
171     case BuiltinType::ULongLong:
172     case BuiltinType::UInt128:
173     case BuiltinType::SChar:
174     case BuiltinType::Short:
175     case BuiltinType::Int:
176     case BuiltinType::Long:
177     case BuiltinType::LongLong:
178     case BuiltinType::Int128:
179       llvm_unreachable("Builtin type needs extra local data!");
180       // Fall through, if the impossible happens.
181         
182     case BuiltinType::NullPtr:
183     case BuiltinType::Overload:
184     case BuiltinType::Dependent:
185     case BuiltinType::ObjCId:
186     case BuiltinType::ObjCClass:
187     case BuiltinType::ObjCSel:
188       return TST_unspecified;
189     }
190   }
191   
192   return TST_unspecified;
193 }