CXType.cpp revision 7717914639ed8a186fe8b781c9c220594e8dcf30
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===- CXTypes.cpp - Implements 'CXTypes' aspect of libclang ------------===//
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//===--------------------------------------------------------------------===//
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// This file implements the 'CXTypes' API hooks in the Clang-C library.
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//===--------------------------------------------------------------------===//
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "CIndexer.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "CXCursor.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "CXString.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "CXTranslationUnit.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "CXType.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/Decl.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/DeclObjC.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/DeclTemplate.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/Expr.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/AST/Type.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/Frontend/ASTUnit.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing namespace clang;
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#define BTCASE(K) case BuiltinType::K: return CXType_##K
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  switch (BT->getKind()) {
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Void);
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Bool);
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Char_U);
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(UChar);
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Char16);
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Char32);
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(UShort);
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(UInt);
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(ULong);
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(ULongLong);
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    BTCASE(UInt128);
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(Char_S);
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(SChar);
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BuiltinType::WChar_S: return CXType_WChar;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case BuiltinType::WChar_U: return CXType_WChar;
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(Short);
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(Int);
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(Long);
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(LongLong);
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(Int128);
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Float);
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Double);
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(LongDouble);
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(NullPtr);
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Overload);
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(Dependent);
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(ObjCId);
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BTCASE(ObjCClass);
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BTCASE(ObjCSel);
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  default:
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return CXType_Unexposed;
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#undef BTCASE
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static CXTypeKind GetTypeKind(QualType T) {
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Type *TP = T.getTypePtrOrNull();
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!TP)
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return CXType_Invalid;
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define TKCASE(K) case Type::K: return CXType_##K
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (TP->getTypeClass()) {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case Type::Builtin:
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return GetBuiltinTypeKind(cast<BuiltinType>(TP));
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(Complex);
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(Pointer);
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(BlockPointer);
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(LValueReference);
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(RValueReference);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TKCASE(Record);
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TKCASE(Enum);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TKCASE(Typedef);
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TKCASE(ObjCInterface);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TKCASE(ObjCObjectPointer);
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(FunctionNoProto);
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(FunctionProto);
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(ConstantArray);
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TKCASE(Vector);
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    default:
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return CXType_Unexposed;
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#undef TKCASE
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochCXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CXTypeKind TK = CXType_Invalid;
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (TU && !T.isNull()) {
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (Ctx.getLangOpts().ObjC1) {
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QualType UnqualT = T.getUnqualifiedType();
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (Ctx.isObjCIdType(UnqualT))
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        TK = CXType_ObjCId;
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      else if (Ctx.isObjCClassType(UnqualT))
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        TK = CXType_ObjCClass;
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      else if (Ctx.isObjCSelType(UnqualT))
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        TK = CXType_ObjCSel;
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (TK == CXType_Invalid)
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TK = GetTypeKind(T);
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return CT;
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing cxtype::MakeCXType;
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic inline QualType GetQualType(CXType CT) {
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return QualType::getFromOpaquePtr(CT.data[0]);
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic inline CXTranslationUnit GetTU(CXType CT) {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return static_cast<CXTranslationUnit>(CT.data[1]);
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochextern "C" {
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochCXType clang_getCursorType(CXCursor C) {
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  using namespace cxcursor;
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CXTranslationUnit TU = cxcursor::getCursorTU(C);
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!TU)
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return MakeCXType(QualType(), TU);
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (clang_isExpression(C.kind)) {
139    QualType T = cxcursor::getCursorExpr(C)->getType();
140    return MakeCXType(T, TU);
141  }
142
143  if (clang_isDeclaration(C.kind)) {
144    const Decl *D = cxcursor::getCursorDecl(C);
145    if (!D)
146      return MakeCXType(QualType(), TU);
147
148    if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
149      return MakeCXType(Context.getTypeDeclType(TD), TU);
150    if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
151      return MakeCXType(Context.getObjCInterfaceType(ID), TU);
152    if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
153      if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
154        return MakeCXType(TSInfo->getType(), TU);
155      return MakeCXType(DD->getType(), TU);
156    }
157    if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
158      return MakeCXType(VD->getType(), TU);
159    if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
160      return MakeCXType(PD->getType(), TU);
161    if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
162      if (TypeSourceInfo *TSInfo = FTD->getTemplatedDecl()->getTypeSourceInfo())
163        return MakeCXType(TSInfo->getType(), TU);
164      return MakeCXType(FTD->getTemplatedDecl()->getType(), TU);
165    }
166    return MakeCXType(QualType(), TU);
167  }
168
169  if (clang_isReference(C.kind)) {
170    switch (C.kind) {
171    case CXCursor_ObjCSuperClassRef: {
172      QualType T
173        = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
174      return MakeCXType(T, TU);
175    }
176
177    case CXCursor_ObjCClassRef: {
178      QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
179      return MakeCXType(T, TU);
180    }
181
182    case CXCursor_TypeRef: {
183      QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
184      return MakeCXType(T, TU);
185
186    }
187
188    case CXCursor_CXXBaseSpecifier:
189      return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
190
191    case CXCursor_MemberRef:
192      return cxtype::MakeCXType(getCursorMemberRef(C).first->getType(), TU);
193
194    case CXCursor_VariableRef:
195      return cxtype::MakeCXType(getCursorVariableRef(C).first->getType(), TU);
196
197    case CXCursor_ObjCProtocolRef:
198    case CXCursor_TemplateRef:
199    case CXCursor_NamespaceRef:
200    case CXCursor_OverloadedDeclRef:
201    default:
202      break;
203    }
204
205    return MakeCXType(QualType(), TU);
206  }
207
208  return MakeCXType(QualType(), TU);
209}
210
211CXString clang_getTypeSpelling(CXType CT) {
212  QualType T = GetQualType(CT);
213  if (T.isNull())
214    return cxstring::createEmpty();
215
216  CXTranslationUnit TU = GetTU(CT);
217  SmallString<64> Str;
218  llvm::raw_svector_ostream OS(Str);
219  PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
220
221  T.print(OS, PP);
222
223  return cxstring::createDup(OS.str());
224}
225
226CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
227  using namespace cxcursor;
228  CXTranslationUnit TU = cxcursor::getCursorTU(C);
229
230  if (clang_isDeclaration(C.kind)) {
231    const Decl *D = cxcursor::getCursorDecl(C);
232
233    if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
234      QualType T = TD->getUnderlyingType();
235      return MakeCXType(T, TU);
236    }
237
238    return MakeCXType(QualType(), TU);
239  }
240
241  return MakeCXType(QualType(), TU);
242}
243
244CXType clang_getEnumDeclIntegerType(CXCursor C) {
245  using namespace cxcursor;
246  CXTranslationUnit TU = cxcursor::getCursorTU(C);
247
248  if (clang_isDeclaration(C.kind)) {
249    const Decl *D = cxcursor::getCursorDecl(C);
250
251    if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
252      QualType T = TD->getIntegerType();
253      return MakeCXType(T, TU);
254    }
255
256    return MakeCXType(QualType(), TU);
257  }
258
259  return MakeCXType(QualType(), TU);
260}
261
262long long clang_getEnumConstantDeclValue(CXCursor C) {
263  using namespace cxcursor;
264
265  if (clang_isDeclaration(C.kind)) {
266    const Decl *D = cxcursor::getCursorDecl(C);
267
268    if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
269      return TD->getInitVal().getSExtValue();
270    }
271
272    return LLONG_MIN;
273  }
274
275  return LLONG_MIN;
276}
277
278unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
279  using namespace cxcursor;
280
281  if (clang_isDeclaration(C.kind)) {
282    const Decl *D = cxcursor::getCursorDecl(C);
283
284    if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
285      return TD->getInitVal().getZExtValue();
286    }
287
288    return ULLONG_MAX;
289  }
290
291  return ULLONG_MAX;
292}
293
294int clang_getFieldDeclBitWidth(CXCursor C) {
295  using namespace cxcursor;
296
297  if (clang_isDeclaration(C.kind)) {
298    const Decl *D = getCursorDecl(C);
299
300    if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
301      if (FD->isBitField())
302        return FD->getBitWidthValue(getCursorContext(C));
303    }
304  }
305
306  return -1;
307}
308
309CXType clang_getCanonicalType(CXType CT) {
310  if (CT.kind == CXType_Invalid)
311    return CT;
312
313  QualType T = GetQualType(CT);
314  CXTranslationUnit TU = GetTU(CT);
315
316  if (T.isNull())
317    return MakeCXType(QualType(), GetTU(CT));
318
319  return MakeCXType(cxtu::getASTUnit(TU)->getASTContext()
320                        .getCanonicalType(T),
321                    TU);
322}
323
324unsigned clang_isConstQualifiedType(CXType CT) {
325  QualType T = GetQualType(CT);
326  return T.isLocalConstQualified();
327}
328
329unsigned clang_isVolatileQualifiedType(CXType CT) {
330  QualType T = GetQualType(CT);
331  return T.isLocalVolatileQualified();
332}
333
334unsigned clang_isRestrictQualifiedType(CXType CT) {
335  QualType T = GetQualType(CT);
336  return T.isLocalRestrictQualified();
337}
338
339CXType clang_getPointeeType(CXType CT) {
340  QualType T = GetQualType(CT);
341  const Type *TP = T.getTypePtrOrNull();
342
343  if (!TP)
344    return MakeCXType(QualType(), GetTU(CT));
345
346  switch (TP->getTypeClass()) {
347    case Type::Pointer:
348      T = cast<PointerType>(TP)->getPointeeType();
349      break;
350    case Type::BlockPointer:
351      T = cast<BlockPointerType>(TP)->getPointeeType();
352      break;
353    case Type::LValueReference:
354    case Type::RValueReference:
355      T = cast<ReferenceType>(TP)->getPointeeType();
356      break;
357    case Type::ObjCObjectPointer:
358      T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
359      break;
360    default:
361      T = QualType();
362      break;
363  }
364  return MakeCXType(T, GetTU(CT));
365}
366
367CXCursor clang_getTypeDeclaration(CXType CT) {
368  if (CT.kind == CXType_Invalid)
369    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
370
371  QualType T = GetQualType(CT);
372  const Type *TP = T.getTypePtrOrNull();
373
374  if (!TP)
375    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
376
377  Decl *D = 0;
378
379try_again:
380  switch (TP->getTypeClass()) {
381  case Type::Typedef:
382    D = cast<TypedefType>(TP)->getDecl();
383    break;
384  case Type::ObjCObject:
385    D = cast<ObjCObjectType>(TP)->getInterface();
386    break;
387  case Type::ObjCInterface:
388    D = cast<ObjCInterfaceType>(TP)->getDecl();
389    break;
390  case Type::Record:
391  case Type::Enum:
392    D = cast<TagType>(TP)->getDecl();
393    break;
394  case Type::TemplateSpecialization:
395    if (const RecordType *Record = TP->getAs<RecordType>())
396      D = Record->getDecl();
397    else
398      D = cast<TemplateSpecializationType>(TP)->getTemplateName()
399                                                         .getAsTemplateDecl();
400    break;
401
402  case Type::InjectedClassName:
403    D = cast<InjectedClassNameType>(TP)->getDecl();
404    break;
405
406  // FIXME: Template type parameters!
407
408  case Type::Elaborated:
409    TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
410    goto try_again;
411
412  default:
413    break;
414  }
415
416  if (!D)
417    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
418
419  return cxcursor::MakeCXCursor(D, GetTU(CT));
420}
421
422CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
423  const char *s = 0;
424#define TKIND(X) case CXType_##X: s = ""  #X  ""; break
425  switch (K) {
426    TKIND(Invalid);
427    TKIND(Unexposed);
428    TKIND(Void);
429    TKIND(Bool);
430    TKIND(Char_U);
431    TKIND(UChar);
432    TKIND(Char16);
433    TKIND(Char32);
434    TKIND(UShort);
435    TKIND(UInt);
436    TKIND(ULong);
437    TKIND(ULongLong);
438    TKIND(UInt128);
439    TKIND(Char_S);
440    TKIND(SChar);
441    case CXType_WChar: s = "WChar"; break;
442    TKIND(Short);
443    TKIND(Int);
444    TKIND(Long);
445    TKIND(LongLong);
446    TKIND(Int128);
447    TKIND(Float);
448    TKIND(Double);
449    TKIND(LongDouble);
450    TKIND(NullPtr);
451    TKIND(Overload);
452    TKIND(Dependent);
453    TKIND(ObjCId);
454    TKIND(ObjCClass);
455    TKIND(ObjCSel);
456    TKIND(Complex);
457    TKIND(Pointer);
458    TKIND(BlockPointer);
459    TKIND(LValueReference);
460    TKIND(RValueReference);
461    TKIND(Record);
462    TKIND(Enum);
463    TKIND(Typedef);
464    TKIND(ObjCInterface);
465    TKIND(ObjCObjectPointer);
466    TKIND(FunctionNoProto);
467    TKIND(FunctionProto);
468    TKIND(ConstantArray);
469    TKIND(Vector);
470  }
471#undef TKIND
472  return cxstring::createRef(s);
473}
474
475unsigned clang_equalTypes(CXType A, CXType B) {
476  return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
477}
478
479unsigned clang_isFunctionTypeVariadic(CXType X) {
480  QualType T = GetQualType(X);
481  if (T.isNull())
482    return 0;
483
484  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
485    return (unsigned)FD->isVariadic();
486
487  if (T->getAs<FunctionNoProtoType>())
488    return 1;
489
490  return 0;
491}
492
493CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
494  QualType T = GetQualType(X);
495  if (T.isNull())
496    return CXCallingConv_Invalid;
497
498  if (const FunctionType *FD = T->getAs<FunctionType>()) {
499#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
500    switch (FD->getCallConv()) {
501      TCALLINGCONV(Default);
502      TCALLINGCONV(C);
503      TCALLINGCONV(X86StdCall);
504      TCALLINGCONV(X86FastCall);
505      TCALLINGCONV(X86ThisCall);
506      TCALLINGCONV(X86Pascal);
507      TCALLINGCONV(AAPCS);
508      TCALLINGCONV(AAPCS_VFP);
509      TCALLINGCONV(PnaclCall);
510      TCALLINGCONV(IntelOclBicc);
511    }
512#undef TCALLINGCONV
513  }
514
515  return CXCallingConv_Invalid;
516}
517
518int clang_getNumArgTypes(CXType X) {
519  QualType T = GetQualType(X);
520  if (T.isNull())
521    return -1;
522
523  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
524    return FD->getNumArgs();
525  }
526
527  if (T->getAs<FunctionNoProtoType>()) {
528    return 0;
529  }
530
531  return -1;
532}
533
534CXType clang_getArgType(CXType X, unsigned i) {
535  QualType T = GetQualType(X);
536  if (T.isNull())
537    return MakeCXType(QualType(), GetTU(X));
538
539  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
540    unsigned numArgs = FD->getNumArgs();
541    if (i >= numArgs)
542      return MakeCXType(QualType(), GetTU(X));
543
544    return MakeCXType(FD->getArgType(i), GetTU(X));
545  }
546
547  return MakeCXType(QualType(), GetTU(X));
548}
549
550CXType clang_getResultType(CXType X) {
551  QualType T = GetQualType(X);
552  if (T.isNull())
553    return MakeCXType(QualType(), GetTU(X));
554
555  if (const FunctionType *FD = T->getAs<FunctionType>())
556    return MakeCXType(FD->getResultType(), GetTU(X));
557
558  return MakeCXType(QualType(), GetTU(X));
559}
560
561CXType clang_getCursorResultType(CXCursor C) {
562  if (clang_isDeclaration(C.kind)) {
563    const Decl *D = cxcursor::getCursorDecl(C);
564    if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
565      return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
566
567    return clang_getResultType(clang_getCursorType(C));
568  }
569
570  return MakeCXType(QualType(), cxcursor::getCursorTU(C));
571}
572
573unsigned clang_isPODType(CXType X) {
574  QualType T = GetQualType(X);
575  if (T.isNull())
576    return 0;
577
578  CXTranslationUnit TU = GetTU(X);
579
580  return T.isPODType(cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
581}
582
583CXType clang_getElementType(CXType CT) {
584  QualType ET = QualType();
585  QualType T = GetQualType(CT);
586  const Type *TP = T.getTypePtrOrNull();
587
588  if (TP) {
589    switch (TP->getTypeClass()) {
590    case Type::ConstantArray:
591      ET = cast<ConstantArrayType> (TP)->getElementType();
592      break;
593    case Type::Vector:
594      ET = cast<VectorType> (TP)->getElementType();
595      break;
596    case Type::Complex:
597      ET = cast<ComplexType> (TP)->getElementType();
598      break;
599    default:
600      break;
601    }
602  }
603  return MakeCXType(ET, GetTU(CT));
604}
605
606long long clang_getNumElements(CXType CT) {
607  long long result = -1;
608  QualType T = GetQualType(CT);
609  const Type *TP = T.getTypePtrOrNull();
610
611  if (TP) {
612    switch (TP->getTypeClass()) {
613    case Type::ConstantArray:
614      result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
615      break;
616    case Type::Vector:
617      result = cast<VectorType> (TP)->getNumElements();
618      break;
619    default:
620      break;
621    }
622  }
623  return result;
624}
625
626CXType clang_getArrayElementType(CXType CT) {
627  QualType ET = QualType();
628  QualType T = GetQualType(CT);
629  const Type *TP = T.getTypePtrOrNull();
630
631  if (TP) {
632    switch (TP->getTypeClass()) {
633    case Type::ConstantArray:
634      ET = cast<ConstantArrayType> (TP)->getElementType();
635      break;
636    default:
637      break;
638    }
639  }
640  return MakeCXType(ET, GetTU(CT));
641}
642
643long long clang_getArraySize(CXType CT) {
644  long long result = -1;
645  QualType T = GetQualType(CT);
646  const Type *TP = T.getTypePtrOrNull();
647
648  if (TP) {
649    switch (TP->getTypeClass()) {
650    case Type::ConstantArray:
651      result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
652      break;
653    default:
654      break;
655    }
656  }
657  return result;
658}
659
660long long clang_Type_getAlignOf(CXType T) {
661  if (T.kind == CXType_Invalid)
662    return CXTypeLayoutError_Invalid;
663  ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
664  QualType QT = GetQualType(T);
665  // [expr.alignof] p1: return size_t value for complete object type, reference
666  //                    or array.
667  // [expr.alignof] p3: if reference type, return size of referenced type
668  if (QT->isReferenceType())
669    QT = QT.getNonReferenceType();
670  if (QT->isIncompleteType())
671    return CXTypeLayoutError_Incomplete;
672  if (QT->isDependentType())
673    return CXTypeLayoutError_Dependent;
674  // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
675  // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
676  // if (QT->isVoidType()) return 1;
677  return Ctx.getTypeAlignInChars(QT).getQuantity();
678}
679
680long long clang_Type_getSizeOf(CXType T) {
681  if (T.kind == CXType_Invalid)
682    return CXTypeLayoutError_Invalid;
683  ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
684  QualType QT = GetQualType(T);
685  // [expr.sizeof] p2: if reference type, return size of referenced type
686  if (QT->isReferenceType())
687    QT = QT.getNonReferenceType();
688  // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
689  //                   enumeration
690  // Note: We get the cxtype, not the cxcursor, so we can't call
691  //       FieldDecl->isBitField()
692  // [expr.sizeof] p3: pointer ok, function not ok.
693  // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
694  if (QT->isIncompleteType())
695    return CXTypeLayoutError_Incomplete;
696  if (QT->isDependentType())
697    return CXTypeLayoutError_Dependent;
698  if (!QT->isConstantSizeType())
699    return CXTypeLayoutError_NotConstantSize;
700  // [gcc extension] lib/AST/ExprConstant.cpp:1372
701  //                 HandleSizeof : {voidtype,functype} == 1
702  // not handled by ASTContext.cpp:1313 getTypeInfoImpl
703  if (QT->isVoidType() || QT->isFunctionType())
704    return 1;
705  return Ctx.getTypeSizeInChars(QT).getQuantity();
706}
707
708static long long visitRecordForValidation(const RecordDecl *RD) {
709  for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
710       I != E; ++I){
711    QualType FQT = (*I)->getType();
712    if (FQT->isIncompleteType())
713      return CXTypeLayoutError_Incomplete;
714    if (FQT->isDependentType())
715      return CXTypeLayoutError_Dependent;
716    // recurse
717    if (const RecordType *ChildType = (*I)->getType()->getAs<RecordType>()) {
718      if (const RecordDecl *Child = ChildType->getDecl()) {
719        long long ret = visitRecordForValidation(Child);
720        if (ret < 0)
721          return ret;
722      }
723    }
724    // else try next field
725  }
726  return 0;
727}
728
729long long clang_Type_getOffsetOf(CXType PT, const char *S) {
730  // check that PT is not incomplete/dependent
731  CXCursor PC = clang_getTypeDeclaration(PT);
732  if (clang_isInvalid(PC.kind))
733    return CXTypeLayoutError_Invalid;
734  const RecordDecl *RD =
735        dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
736  if (!RD)
737    return CXTypeLayoutError_Invalid;
738  RD = RD->getDefinition();
739  if (!RD)
740    return CXTypeLayoutError_Incomplete;
741  QualType RT = GetQualType(PT);
742  if (RT->isIncompleteType())
743    return CXTypeLayoutError_Incomplete;
744  if (RT->isDependentType())
745    return CXTypeLayoutError_Dependent;
746  // We recurse into all record fields to detect incomplete and dependent types.
747  long long Error = visitRecordForValidation(RD);
748  if (Error < 0)
749    return Error;
750  if (!S)
751    return CXTypeLayoutError_InvalidFieldName;
752  // lookup field
753  ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();
754  IdentifierInfo *II = &Ctx.Idents.get(S);
755  DeclarationName FieldName(II);
756  RecordDecl::lookup_const_result Res = RD->lookup(FieldName);
757  // If a field of the parent record is incomplete, lookup will fail.
758  // and we would return InvalidFieldName instead of Incomplete.
759  // But this erroneous results does protects again a hidden assertion failure
760  // in the RecordLayoutBuilder
761  if (Res.size() != 1)
762    return CXTypeLayoutError_InvalidFieldName;
763  if (const FieldDecl *FD = dyn_cast<FieldDecl>(Res.front()))
764    return Ctx.getFieldOffset(FD);
765  if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Res.front()))
766    return Ctx.getFieldOffset(IFD);
767  // we don't want any other Decl Type.
768  return CXTypeLayoutError_InvalidFieldName;
769}
770
771unsigned clang_Cursor_isBitField(CXCursor C) {
772  if (!clang_isDeclaration(C.kind))
773    return 0;
774  const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(cxcursor::getCursorDecl(C));
775  if (!FD)
776    return 0;
777  return FD->isBitField();
778}
779
780CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
781  if (!clang_isDeclaration(C.kind))
782    return cxstring::createEmpty();
783
784  const Decl *D = cxcursor::getCursorDecl(C);
785  ASTContext &Ctx = cxcursor::getCursorContext(C);
786  std::string encoding;
787
788  if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
789    if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
790      return cxstring::createRef("?");
791  } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
792    Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
793  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
794    Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
795  else {
796    QualType Ty;
797    if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
798      Ty = Ctx.getTypeDeclType(TD);
799    if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
800      Ty = VD->getType();
801    else return cxstring::createRef("?");
802    Ctx.getObjCEncodingForType(Ty, encoding);
803  }
804
805  return cxstring::createDup(encoding);
806}
807
808} // end: extern "C"
809