1 /**
2  * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Jan 29, 2012
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module clang.Type;
8 
9 import mambo.core._;
10 
11 import clang.c.Index;
12 import clang.Cursor;
13 import clang.Util;
14 
15 struct Type
16 {
17     mixin CX;
18 
19     @property string spelling ()
20     {
21         auto r = clang_getTypeDeclaration(cx);
22         return Cursor(r).spelling;
23     }
24 
25     @property bool isTypedef ()
26     {
27         return kind == CXTypeKind.CXType_Typedef;
28     }
29 
30     @property bool isEnum ()
31     {
32         return kind == CXTypeKind.CXType_Enum;
33     }
34 
35     @property Type canonicalType ()
36     {
37         auto r = clang_getCanonicalType(cx);
38         return Type(r);
39     }
40 
41     @property Type pointeeType ()
42     {
43         auto r = clang_getPointeeType(cx);
44         return Type(r);
45     }
46 
47     @property bool isValid ()
48     {
49         return kind != CXTypeKind.CXType_Invalid;
50     }
51 
52     @property bool isFunctionType ()
53     {
54         return canonicalType.kind == CXTypeKind.CXType_FunctionProto;
55     }
56 
57     @property bool isFunctionPointerType ()
58     {
59         with (CXTypeKind)
60             return kind == CXType_Pointer && pointeeType.isFunctionType;
61     }
62 
63     @property bool isObjCIdType ()
64     {
65         return isTypedef &&
66             canonicalType.kind ==  CXTypeKind.CXType_ObjCObjectPointer &&
67             spelling == "id";
68     }
69 
70     @property bool isObjCClassType ()
71     {
72         return isTypedef &&
73             canonicalType.kind ==  CXTypeKind.CXType_ObjCObjectPointer &&
74             spelling == "Class";
75     }
76 
77     @property bool isObjCSelType ()
78     {
79         with(CXTypeKind)
80             if (isTypedef)
81             {
82                 auto c = canonicalType;
83                 return c.kind == CXType_Pointer &&
84                     c.pointeeType.kind == CXType_ObjCSel;
85             }
86 
87             else
88                 return false;
89     }
90 
91     @property bool isObjCBuiltinType ()
92     {
93         return isObjCIdType || isObjCClassType || isObjCSelType;
94     }
95 
96     @property bool isWideCharType ()
97     {
98         with (CXTypeKind)
99             return kind == CXType_WChar;
100     }
101 
102     @property bool isConst ()
103     {
104         return clang_isConstQualifiedType(cx) == 1;
105     }
106 
107     @property bool isExposed ()
108     {
109         return kind != CXTypeKind.CXType_Unexposed;
110     }
111 
112     @property bool isAnonymous ()
113     {
114         return spelling.isEmpty;
115     }
116 
117     @property Cursor declaration ()
118     {
119         auto r = clang_getTypeDeclaration(cx);
120         return Cursor(r);
121     }
122 
123     @property FuncType func ()
124     {
125         return FuncType(this);
126     }
127 
128     @property ArrayType array ()
129     {
130         return ArrayType(this);
131     }
132 }
133 
134 struct FuncType
135 {
136     Type type;
137     alias type this;
138 
139     @property Type resultType ()
140     {
141         auto r = clang_getResultType(type.cx);
142         return Type(r);
143     }
144 
145     @property Arguments arguments ()
146     {
147         return Arguments(this);
148     }
149 
150     @property bool isVariadic ()
151     {
152         return clang_isFunctionTypeVariadic(type.cx) == 1;
153     }
154 }
155 
156 struct ArrayType
157 {
158     Type type;
159     alias type this;
160 
161     @property Type elementType ()
162     {
163         auto r = clang_getArrayElementType(cx);
164         return Type(r);
165     }
166 
167     @property long size ()
168     {
169         return clang_getArraySize(cx);
170     }
171 }
172 
173 struct Arguments
174 {
175     FuncType type;
176 
177     @property uint length ()
178     {
179         return clang_getNumArgTypes(type.type.cx);
180     }
181 
182     Type opIndex (uint i)
183     {
184         auto r = clang_getArgType(type.type.cx, i);
185         return Type(r);
186     }
187 
188     int opApply (int delegate (ref Type) dg)
189     {
190         foreach (i ; 0 .. length)
191         {
192             auto type = this[i];
193 
194             if (auto result = dg(type))
195                 return result;
196         }
197 
198         return 0;
199     }
200 }
201 
202 @property bool isUnsigned (CXTypeKind kind)
203 {
204     with (CXTypeKind)
205         switch (kind)
206         {
207             case CXType_Char_U: return true;
208             case CXType_UChar: return true;
209             case CXType_UShort: return true;
210             case CXType_UInt: return true;
211             case CXType_ULong: return true;
212             case CXType_ULongLong: return true;
213             case CXType_UInt128: return true;
214 
215             default: return false;
216         }
217 }