• 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     default:
93       return CXType_Unexposed;
94   }
95 #undef TKCASE
96 }
97 
98 
MakeCXType(QualType T,CXTranslationUnit TU)99 CXType 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 
121 using cxtype::MakeCXType;
122 
GetQualType(CXType CT)123 static inline QualType GetQualType(CXType CT) {
124   return QualType::getFromOpaquePtr(CT.data[0]);
125 }
126 
GetTU(CXType CT)127 static inline CXTranslationUnit GetTU(CXType CT) {
128   return static_cast<CXTranslationUnit>(CT.data[1]);
129 }
130 
131 extern "C" {
132 
clang_getCursorType(CXCursor C)133 CXType 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 
clang_getTypeSpelling(CXType CT)214 CXString 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 
clang_getTypedefDeclUnderlyingType(CXCursor C)229 CXType 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 
clang_getEnumDeclIntegerType(CXCursor C)247 CXType 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 
clang_getEnumConstantDeclValue(CXCursor C)265 long 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 
clang_getEnumConstantDeclUnsignedValue(CXCursor C)281 unsigned 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 
clang_getFieldDeclBitWidth(CXCursor C)297 int 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 
clang_getCanonicalType(CXType CT)312 CXType 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 
clang_isConstQualifiedType(CXType CT)327 unsigned clang_isConstQualifiedType(CXType CT) {
328   QualType T = GetQualType(CT);
329   return T.isLocalConstQualified();
330 }
331 
clang_isVolatileQualifiedType(CXType CT)332 unsigned clang_isVolatileQualifiedType(CXType CT) {
333   QualType T = GetQualType(CT);
334   return T.isLocalVolatileQualified();
335 }
336 
clang_isRestrictQualifiedType(CXType CT)337 unsigned clang_isRestrictQualifiedType(CXType CT) {
338   QualType T = GetQualType(CT);
339   return T.isLocalRestrictQualified();
340 }
341 
clang_getPointeeType(CXType CT)342 CXType 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 
clang_getTypeDeclaration(CXType CT)370 CXCursor 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 
382 try_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 
clang_getTypeKindSpelling(enum CXTypeKind K)425 CXString 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 
clang_equalTypes(CXType A,CXType B)481 unsigned clang_equalTypes(CXType A, CXType B) {
482   return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
483 }
484 
clang_isFunctionTypeVariadic(CXType X)485 unsigned 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 
clang_getFunctionTypeCallingConv(CXType X)499 CXCallingConv 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 
clang_getNumArgTypes(CXType X)524 int 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 
clang_getArgType(CXType X,unsigned i)540 CXType 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 
clang_getResultType(CXType X)556 CXType 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 
clang_getCursorResultType(CXCursor C)567 CXType 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 
clang_isPODType(CXType X)579 unsigned 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 
clang_getElementType(CXType CT)589 CXType 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 
clang_getNumElements(CXType CT)621 long 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 
clang_getArrayElementType(CXType CT)641 CXType 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 
clang_getArraySize(CXType CT)667 long 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 
clang_Type_getAlignOf(CXType T)684 long 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 
clang_Type_getSizeOf(CXType T)704 long 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 
visitRecordForValidation(const RecordDecl * RD)732 static 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 
clang_Type_getOffsetOf(CXType PT,const char * S)753 long 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 
clang_Cursor_isBitField(CXCursor C)797 unsigned 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 
clang_getDeclObjCTypeEncoding(CXCursor C)806 CXString 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