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