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