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