1//===- CXType.cpp - Implements 'CXTypes' aspect of libclang ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===--------------------------------------------------------------------===//
8//
9// This file implements the 'CXTypes' API hooks in the Clang-C library.
10//
11//===--------------------------------------------------------------------===//
12
13#include "CXType.h"
14#include "CIndexer.h"
15#include "CXCursor.h"
16#include "CXString.h"
17#include "CXTranslationUnit.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DeclTemplate.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/QualTypeNames.h"
23#include "clang/AST/RecordLayout.h"
24#include "clang/AST/Type.h"
25#include "clang/Basic/AddressSpaces.h"
26#include "clang/Frontend/ASTUnit.h"
27#include <optional>
28
29using namespace clang;
30
31static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
32#define BTCASE(K) case BuiltinType::K: return CXType_##K
33 switch (BT->getKind()) {
34 BTCASE(Void);
35 BTCASE(Bool);
36 BTCASE(Char_U);
37 BTCASE(UChar);
38 BTCASE(Char16);
39 BTCASE(Char32);
40 BTCASE(UShort);
41 BTCASE(UInt);
42 BTCASE(ULong);
43 BTCASE(ULongLong);
44 BTCASE(UInt128);
45 BTCASE(Char_S);
46 BTCASE(SChar);
47 case BuiltinType::WChar_S: return CXType_WChar;
48 case BuiltinType::WChar_U: return CXType_WChar;
49 BTCASE(Short);
50 BTCASE(Int);
51 BTCASE(Long);
52 BTCASE(LongLong);
53 BTCASE(Int128);
54 BTCASE(Half);
55 BTCASE(Float);
56 BTCASE(Double);
57 BTCASE(LongDouble);
58 BTCASE(ShortAccum);
59 BTCASE(Accum);
60 BTCASE(LongAccum);
61 BTCASE(UShortAccum);
62 BTCASE(UAccum);
63 BTCASE(ULongAccum);
64 BTCASE(Float16);
65 BTCASE(Float128);
66 BTCASE(Ibm128);
67 BTCASE(NullPtr);
68 BTCASE(Overload);
69 BTCASE(Dependent);
70 BTCASE(ObjCId);
71 BTCASE(ObjCClass);
72 BTCASE(ObjCSel);
73#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) BTCASE(Id);
74#include "clang/Basic/OpenCLImageTypes.def"
75#undef IMAGE_TYPE
76#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) BTCASE(Id);
77#include "clang/Basic/OpenCLExtensionTypes.def"
78 BTCASE(OCLSampler);
79 BTCASE(OCLEvent);
80 BTCASE(OCLQueue);
81 BTCASE(OCLReserveID);
82#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) BTCASE(Id);
83#include "clang/Basic/HLSLIntangibleTypes.def"
84 default:
85 return CXType_Unexposed;
86 }
87#undef BTCASE
88}
89
90static CXTypeKind GetTypeKind(QualType T) {
91 const Type *TP = T.getTypePtrOrNull();
92 if (!TP)
93 return CXType_Invalid;
94
95#define TKCASE(K) case Type::K: return CXType_##K
96 switch (TP->getTypeClass()) {
97 case Type::Builtin:
98 return GetBuiltinTypeKind(BT: cast<BuiltinType>(Val: TP));
99 TKCASE(Complex);
100 TKCASE(Pointer);
101 TKCASE(BlockPointer);
102 TKCASE(LValueReference);
103 TKCASE(RValueReference);
104 TKCASE(Record);
105 TKCASE(Enum);
106 TKCASE(Typedef);
107 TKCASE(ObjCInterface);
108 TKCASE(ObjCObject);
109 TKCASE(ObjCObjectPointer);
110 TKCASE(ObjCTypeParam);
111 TKCASE(FunctionNoProto);
112 TKCASE(FunctionProto);
113 TKCASE(ConstantArray);
114 TKCASE(IncompleteArray);
115 TKCASE(VariableArray);
116 TKCASE(DependentSizedArray);
117 TKCASE(Vector);
118 TKCASE(ExtVector);
119 TKCASE(MemberPointer);
120 TKCASE(Auto);
121 TKCASE(Pipe);
122 TKCASE(Attributed);
123 TKCASE(BTFTagAttributed);
124 TKCASE(Atomic);
125 TKCASE(PredefinedSugar);
126 default:
127 return CXType_Unexposed;
128 }
129#undef TKCASE
130}
131
132
133CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
134 CXTypeKind TK = CXType_Invalid;
135
136 if (TU && !T.isNull()) {
137 // Handle attributed types as the original type
138 if (auto *ATT = T->getAs<AttributedType>()) {
139 if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes)) {
140 // Return the equivalent type which represents the canonically
141 // equivalent type.
142 return MakeCXType(T: ATT->getEquivalentType(), TU);
143 }
144 }
145 if (auto *ATT = T->getAs<BTFTagAttributedType>()) {
146 if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes))
147 return MakeCXType(T: ATT->getWrappedType(), TU);
148 }
149 // Handle paren types as the original type
150 if (auto *PTT = T->getAs<ParenType>()) {
151 return MakeCXType(T: PTT->getInnerType(), TU);
152 }
153
154 ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
155 if (Ctx.getLangOpts().ObjC) {
156 QualType UnqualT = T.getUnqualifiedType();
157 if (Ctx.isObjCIdType(T: UnqualT))
158 TK = CXType_ObjCId;
159 else if (Ctx.isObjCClassType(T: UnqualT))
160 TK = CXType_ObjCClass;
161 else if (Ctx.isObjCSelType(T: UnqualT))
162 TK = CXType_ObjCSel;
163 }
164
165 /* Handle decayed types as the original type */
166 if (const DecayedType *DT = T->getAs<DecayedType>()) {
167 return MakeCXType(T: DT->getOriginalType(), TU);
168 }
169 }
170 if (TK == CXType_Invalid)
171 TK = GetTypeKind(T);
172
173 CXType CT = { .kind: TK, .data: { TK == CXType_Invalid ? nullptr
174 : T.getAsOpaquePtr(), TU } };
175 return CT;
176}
177
178using cxtype::MakeCXType;
179
180static inline QualType GetQualType(CXType CT) {
181 return QualType::getFromOpaquePtr(Ptr: CT.data[0]);
182}
183
184static inline CXTranslationUnit GetTU(CXType CT) {
185 return static_cast<CXTranslationUnit>(CT.data[1]);
186}
187
188static std::optional<ArrayRef<TemplateArgument>>
189GetTemplateArguments(QualType Type) {
190 assert(!Type.isNull());
191 if (const auto *Specialization = Type->getAs<TemplateSpecializationType>())
192 return Specialization->template_arguments();
193
194 if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) {
195 const auto *TemplateDecl =
196 dyn_cast<ClassTemplateSpecializationDecl>(Val: RecordDecl);
197 if (TemplateDecl)
198 return TemplateDecl->getTemplateArgs().asArray();
199 }
200
201 return std::nullopt;
202}
203
204static std::optional<QualType>
205TemplateArgumentToQualType(const TemplateArgument &A) {
206 if (A.getKind() == TemplateArgument::Type)
207 return A.getAsType();
208 return std::nullopt;
209}
210
211static std::optional<QualType>
212FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> TA, unsigned index) {
213 unsigned current = 0;
214 for (const auto &A : TA) {
215 if (A.getKind() == TemplateArgument::Pack) {
216 if (index < current + A.pack_size())
217 return TemplateArgumentToQualType(A: A.getPackAsArray()[index - current]);
218 current += A.pack_size();
219 continue;
220 }
221 if (current == index)
222 return TemplateArgumentToQualType(A);
223 current++;
224 }
225 return std::nullopt;
226}
227
228static CXType getTypeDeclType(const ASTContext &Context, CXTranslationUnit TU,
229 const TypeDecl *TD) {
230 return MakeCXType(T: Context.getTypeDeclType(Decl: TD), TU);
231}
232
233CXType clang_getCursorType(CXCursor C) {
234 using namespace cxcursor;
235
236 CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C);
237 if (!TU)
238 return MakeCXType(T: QualType(), TU);
239
240 ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext();
241 if (clang_isExpression(C.kind)) {
242 QualType T = cxcursor::getCursorExpr(Cursor: C)->getType();
243 return MakeCXType(T, TU);
244 }
245
246 if (clang_isDeclaration(C.kind)) {
247 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
248 if (!D)
249 return MakeCXType(T: QualType(), TU);
250
251 if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D))
252 return getTypeDeclType(Context, TU, TD);
253 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(Val: D))
254 return MakeCXType(T: Context.getObjCInterfaceType(Decl: ID), TU);
255 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(Val: D))
256 return MakeCXType(T: DD->getType(), TU);
257 if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D))
258 return MakeCXType(T: VD->getType(), TU);
259 if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Val: D))
260 return MakeCXType(T: PD->getType(), TU);
261 if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
262 return MakeCXType(T: FTD->getTemplatedDecl()->getType(), TU);
263 return MakeCXType(T: QualType(), TU);
264 }
265
266 if (clang_isReference(C.kind)) {
267 switch (C.kind) {
268 case CXCursor_ObjCSuperClassRef: {
269 QualType T
270 = Context.getObjCInterfaceType(Decl: getCursorObjCSuperClassRef(C).first);
271 return MakeCXType(T, TU);
272 }
273
274 case CXCursor_ObjCClassRef: {
275 QualType T = Context.getObjCInterfaceType(Decl: getCursorObjCClassRef(C).first);
276 return MakeCXType(T, TU);
277 }
278
279 case CXCursor_TypeRef:
280 return getTypeDeclType(Context, TU, TD: getCursorTypeRef(C).first);
281
282 case CXCursor_CXXBaseSpecifier:
283 return cxtype::MakeCXType(T: getCursorCXXBaseSpecifier(C)->getType(), TU);
284
285 case CXCursor_MemberRef:
286 return cxtype::MakeCXType(T: getCursorMemberRef(C).first->getType(), TU);
287
288 case CXCursor_VariableRef:
289 return cxtype::MakeCXType(T: getCursorVariableRef(C).first->getType(), TU);
290
291 case CXCursor_ObjCProtocolRef:
292 case CXCursor_TemplateRef:
293 case CXCursor_NamespaceRef:
294 case CXCursor_OverloadedDeclRef:
295 default:
296 break;
297 }
298
299 return MakeCXType(T: QualType(), TU);
300 }
301
302 return MakeCXType(T: QualType(), TU);
303}
304
305CXString clang_getTypeSpelling(CXType CT) {
306 QualType T = GetQualType(CT);
307 if (T.isNull())
308 return cxstring::createEmpty();
309
310 CXTranslationUnit TU = GetTU(CT);
311 SmallString<64> Str;
312 llvm::raw_svector_ostream OS(Str);
313 PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
314
315 T.print(OS, Policy: PP);
316
317 return cxstring::createDup(String: OS.str());
318}
319
320CXString clang_getTypePrettyPrinted(CXType CT, CXPrintingPolicy cxPolicy) {
321 QualType T = GetQualType(CT);
322 if (T.isNull())
323 return cxstring::createEmpty();
324
325 SmallString<64> Str;
326 llvm::raw_svector_ostream OS(Str);
327 PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
328
329 T.print(OS, Policy: *UserPolicy);
330
331 return cxstring::createDup(String: OS.str());
332}
333
334CXString clang_getFullyQualifiedName(CXType CT, CXPrintingPolicy cxPolicy,
335 unsigned int WithGlobalNsPrefix) {
336 const QualType T = GetQualType(CT);
337 if (T.isNull())
338 return cxstring::createEmpty();
339 const CXTranslationUnit TU = GetTU(CT);
340 const ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
341 const PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
342 const bool WithGlobalNs = (WithGlobalNsPrefix != 0);
343
344 const std::string Str =
345 TypeName::getFullyQualifiedName(QT: T, Ctx, Policy: *UserPolicy, WithGlobalNsPrefix: WithGlobalNs);
346
347 return cxstring::createDup(String: Str);
348}
349
350CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
351 using namespace cxcursor;
352 CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C);
353
354 if (clang_isDeclaration(C.kind)) {
355 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
356
357 if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(Val: D)) {
358 QualType T = TD->getUnderlyingType();
359 return MakeCXType(T, TU);
360 }
361 }
362
363 return MakeCXType(T: QualType(), TU);
364}
365
366CXType clang_getEnumDeclIntegerType(CXCursor C) {
367 using namespace cxcursor;
368 CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C);
369
370 if (clang_isDeclaration(C.kind)) {
371 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
372
373 if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(Val: D)) {
374 QualType T = TD->getIntegerType();
375 return MakeCXType(T, TU);
376 }
377 }
378
379 return MakeCXType(T: QualType(), TU);
380}
381
382long long clang_getEnumConstantDeclValue(CXCursor C) {
383 using namespace cxcursor;
384
385 if (clang_isDeclaration(C.kind)) {
386 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
387
388 if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(Val: D)) {
389 return TD->getInitVal().getSExtValue();
390 }
391 }
392
393 return LLONG_MIN;
394}
395
396unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
397 using namespace cxcursor;
398
399 if (clang_isDeclaration(C.kind)) {
400 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
401
402 if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(Val: D)) {
403 return TD->getInitVal().getZExtValue();
404 }
405 }
406
407 return ULLONG_MAX;
408}
409
410int clang_getFieldDeclBitWidth(CXCursor C) {
411 using namespace cxcursor;
412
413 if (clang_isDeclaration(C.kind)) {
414 const Decl *D = getCursorDecl(Cursor: C);
415
416 if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: D)) {
417 if (FD->isBitField() && !FD->getBitWidth()->isValueDependent())
418 return FD->getBitWidthValue();
419 }
420 }
421
422 return -1;
423}
424
425CXType clang_getCanonicalType(CXType CT) {
426 if (CT.kind == CXType_Invalid)
427 return CT;
428
429 QualType T = GetQualType(CT);
430 CXTranslationUnit TU = GetTU(CT);
431
432 if (T.isNull())
433 return MakeCXType(T: QualType(), TU: GetTU(CT));
434
435 return MakeCXType(T: cxtu::getASTUnit(TU)->getASTContext()
436 .getCanonicalType(T),
437 TU);
438}
439
440unsigned clang_isConstQualifiedType(CXType CT) {
441 QualType T = GetQualType(CT);
442 return T.isLocalConstQualified();
443}
444
445unsigned clang_isVolatileQualifiedType(CXType CT) {
446 QualType T = GetQualType(CT);
447 return T.isLocalVolatileQualified();
448}
449
450unsigned clang_isRestrictQualifiedType(CXType CT) {
451 QualType T = GetQualType(CT);
452 return T.isLocalRestrictQualified();
453}
454
455unsigned clang_getAddressSpace(CXType CT) {
456 QualType T = GetQualType(CT);
457
458 // For non language-specific address space, use separate helper function.
459 if (T.getAddressSpace() >= LangAS::FirstTargetAddressSpace) {
460 return T.getQualifiers().getAddressSpaceAttributePrintValue();
461 }
462 // FIXME: this function returns either a LangAS or a target AS
463 // Those values can overlap which makes this function rather unpredictable
464 // for any caller
465 return (unsigned)T.getAddressSpace();
466}
467
468CXString clang_getTypedefName(CXType CT) {
469 QualType T = GetQualType(CT);
470 const TypedefType *TT = T->getAs<TypedefType>();
471 if (TT) {
472 TypedefNameDecl *TD = TT->getDecl();
473 if (TD)
474 return cxstring::createDup(String: TD->getNameAsString().c_str());
475 }
476 return cxstring::createEmpty();
477}
478
479CXType clang_getPointeeType(CXType CT) {
480 QualType T = GetQualType(CT);
481 const Type *TP = T.getTypePtrOrNull();
482
483 if (!TP)
484 return MakeCXType(T: QualType(), TU: GetTU(CT));
485
486try_again:
487 switch (TP->getTypeClass()) {
488 case Type::Pointer:
489 T = cast<PointerType>(Val: TP)->getPointeeType();
490 break;
491 case Type::BlockPointer:
492 T = cast<BlockPointerType>(Val: TP)->getPointeeType();
493 break;
494 case Type::LValueReference:
495 case Type::RValueReference:
496 T = cast<ReferenceType>(Val: TP)->getPointeeType();
497 break;
498 case Type::ObjCObjectPointer:
499 T = cast<ObjCObjectPointerType>(Val: TP)->getPointeeType();
500 break;
501 case Type::MemberPointer:
502 T = cast<MemberPointerType>(Val: TP)->getPointeeType();
503 break;
504 case Type::Auto:
505 case Type::DeducedTemplateSpecialization:
506 TP = cast<DeducedType>(Val: TP)->getDeducedType().getTypePtrOrNull();
507 if (TP)
508 goto try_again;
509 break;
510 default:
511 T = QualType();
512 break;
513 }
514 return MakeCXType(T, TU: GetTU(CT));
515}
516
517CXType clang_getUnqualifiedType(CXType CT) {
518 return MakeCXType(T: GetQualType(CT).getUnqualifiedType(), TU: GetTU(CT));
519}
520
521CXType clang_getNonReferenceType(CXType CT) {
522 return MakeCXType(T: GetQualType(CT).getNonReferenceType(), TU: GetTU(CT));
523}
524
525CXCursor clang_getTypeDeclaration(CXType CT) {
526 if (CT.kind == CXType_Invalid)
527 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
528
529 QualType T = GetQualType(CT);
530 const Type *TP = T.getTypePtrOrNull();
531
532 if (!TP)
533 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
534
535 Decl *D = nullptr;
536
537try_again:
538 switch (TP->getTypeClass()) {
539 case Type::Typedef:
540 D = cast<TypedefType>(Val: TP)->getDecl();
541 break;
542 case Type::ObjCObject:
543 D = cast<ObjCObjectType>(Val: TP)->getInterface();
544 break;
545 case Type::ObjCInterface:
546 D = cast<ObjCInterfaceType>(Val: TP)->getDecl();
547 break;
548 case Type::Record:
549 case Type::Enum:
550 D = cast<TagType>(Val: TP)->getDecl();
551 break;
552 case Type::TemplateSpecialization:
553 if (const RecordType *Record = TP->getAs<RecordType>())
554 D = Record->getDecl();
555 else
556 D = cast<TemplateSpecializationType>(Val: TP)->getTemplateName()
557 .getAsTemplateDecl();
558 break;
559
560 case Type::Auto:
561 case Type::DeducedTemplateSpecialization:
562 TP = cast<DeducedType>(Val: TP)->getDeducedType().getTypePtrOrNull();
563 if (TP)
564 goto try_again;
565 break;
566
567 case Type::InjectedClassName:
568 D = cast<InjectedClassNameType>(Val: TP)->getDecl();
569 break;
570
571 // FIXME: Template type parameters!
572
573 default:
574 break;
575 }
576
577 if (!D)
578 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
579
580 return cxcursor::MakeCXCursor(D, TU: GetTU(CT));
581}
582
583CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
584 const char *s = nullptr;
585#define TKIND(X) case CXType_##X: s = "" #X ""; break
586 switch (K) {
587 TKIND(Invalid);
588 TKIND(Unexposed);
589 TKIND(Void);
590 TKIND(Bool);
591 TKIND(Char_U);
592 TKIND(UChar);
593 TKIND(Char16);
594 TKIND(Char32);
595 TKIND(UShort);
596 TKIND(UInt);
597 TKIND(ULong);
598 TKIND(ULongLong);
599 TKIND(UInt128);
600 TKIND(Char_S);
601 TKIND(SChar);
602 case CXType_WChar: s = "WChar"; break;
603 TKIND(Short);
604 TKIND(Int);
605 TKIND(Long);
606 TKIND(LongLong);
607 TKIND(Int128);
608 TKIND(Half);
609 TKIND(Float);
610 TKIND(Double);
611 TKIND(LongDouble);
612 TKIND(ShortAccum);
613 TKIND(Accum);
614 TKIND(LongAccum);
615 TKIND(UShortAccum);
616 TKIND(UAccum);
617 TKIND(ULongAccum);
618 TKIND(Float16);
619 TKIND(Float128);
620 TKIND(Ibm128);
621 TKIND(NullPtr);
622 TKIND(Overload);
623 TKIND(Dependent);
624 TKIND(ObjCId);
625 TKIND(ObjCClass);
626 TKIND(ObjCSel);
627 TKIND(Complex);
628 TKIND(Pointer);
629 TKIND(BlockPointer);
630 TKIND(LValueReference);
631 TKIND(RValueReference);
632 TKIND(Record);
633 TKIND(Enum);
634 TKIND(Typedef);
635 TKIND(ObjCInterface);
636 TKIND(ObjCObject);
637 TKIND(ObjCObjectPointer);
638 TKIND(ObjCTypeParam);
639 TKIND(FunctionNoProto);
640 TKIND(FunctionProto);
641 TKIND(ConstantArray);
642 TKIND(IncompleteArray);
643 TKIND(VariableArray);
644 TKIND(DependentSizedArray);
645 TKIND(Vector);
646 TKIND(ExtVector);
647 TKIND(MemberPointer);
648 TKIND(Auto);
649 TKIND(Elaborated);
650 TKIND(Pipe);
651 TKIND(Attributed);
652 TKIND(BTFTagAttributed);
653 TKIND(HLSLAttributedResource);
654 TKIND(HLSLInlineSpirv);
655 TKIND(PredefinedSugar);
656 TKIND(BFloat16);
657#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id);
658#include "clang/Basic/OpenCLImageTypes.def"
659#undef IMAGE_TYPE
660#define EXT_OPAQUE_TYPE(ExtTYpe, Id, Ext) TKIND(Id);
661#include "clang/Basic/OpenCLExtensionTypes.def"
662 TKIND(OCLSampler);
663 TKIND(OCLEvent);
664 TKIND(OCLQueue);
665 TKIND(OCLReserveID);
666#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) TKIND(Id);
667#include "clang/Basic/HLSLIntangibleTypes.def"
668 TKIND(Atomic);
669 }
670#undef TKIND
671 return cxstring::createRef(String: s);
672}
673
674unsigned clang_equalTypes(CXType A, CXType B) {
675 return A.data[0] == B.data[0] && A.data[1] == B.data[1];
676}
677
678unsigned clang_isFunctionTypeVariadic(CXType X) {
679 QualType T = GetQualType(CT: X);
680 if (T.isNull())
681 return 0;
682
683 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
684 return (unsigned)FD->isVariadic();
685
686 if (T->getAs<FunctionNoProtoType>())
687 return 1;
688
689 return 0;
690}
691
692CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
693 QualType T = GetQualType(CT: X);
694 if (T.isNull())
695 return CXCallingConv_Invalid;
696
697 if (const FunctionType *FD = T->getAs<FunctionType>()) {
698#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
699 switch (FD->getCallConv()) {
700 TCALLINGCONV(C);
701 TCALLINGCONV(X86StdCall);
702 TCALLINGCONV(X86FastCall);
703 TCALLINGCONV(X86ThisCall);
704 TCALLINGCONV(X86Pascal);
705 TCALLINGCONV(X86RegCall);
706 TCALLINGCONV(X86VectorCall);
707 TCALLINGCONV(AArch64VectorCall);
708 TCALLINGCONV(AArch64SVEPCS);
709 TCALLINGCONV(Win64);
710 TCALLINGCONV(X86_64SysV);
711 TCALLINGCONV(AAPCS);
712 TCALLINGCONV(AAPCS_VFP);
713 TCALLINGCONV(IntelOclBicc);
714 TCALLINGCONV(Swift);
715 TCALLINGCONV(SwiftAsync);
716 TCALLINGCONV(PreserveMost);
717 TCALLINGCONV(PreserveAll);
718 TCALLINGCONV(M68kRTD);
719 TCALLINGCONV(PreserveNone);
720 TCALLINGCONV(RISCVVectorCall);
721 TCALLINGCONV(RISCVVLSCall_32);
722 TCALLINGCONV(RISCVVLSCall_64);
723 TCALLINGCONV(RISCVVLSCall_128);
724 TCALLINGCONV(RISCVVLSCall_256);
725 TCALLINGCONV(RISCVVLSCall_512);
726 TCALLINGCONV(RISCVVLSCall_1024);
727 TCALLINGCONV(RISCVVLSCall_2048);
728 TCALLINGCONV(RISCVVLSCall_4096);
729 TCALLINGCONV(RISCVVLSCall_8192);
730 TCALLINGCONV(RISCVVLSCall_16384);
731 TCALLINGCONV(RISCVVLSCall_32768);
732 TCALLINGCONV(RISCVVLSCall_65536);
733 case CC_SpirFunction: return CXCallingConv_Unexposed;
734 case CC_DeviceKernel:
735 return CXCallingConv_Unexposed;
736 break;
737 }
738#undef TCALLINGCONV
739 }
740
741 return CXCallingConv_Invalid;
742}
743
744int clang_getNumArgTypes(CXType X) {
745 QualType T = GetQualType(CT: X);
746 if (T.isNull())
747 return -1;
748
749 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
750 return FD->getNumParams();
751 }
752
753 if (T->getAs<FunctionNoProtoType>()) {
754 return 0;
755 }
756
757 return -1;
758}
759
760CXType clang_getArgType(CXType X, unsigned i) {
761 QualType T = GetQualType(CT: X);
762 if (T.isNull())
763 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
764
765 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
766 unsigned numParams = FD->getNumParams();
767 if (i >= numParams)
768 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
769
770 return MakeCXType(T: FD->getParamType(i), TU: GetTU(CT: X));
771 }
772
773 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
774}
775
776CXType clang_getResultType(CXType X) {
777 QualType T = GetQualType(CT: X);
778 if (T.isNull())
779 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
780
781 if (const FunctionType *FD = T->getAs<FunctionType>())
782 return MakeCXType(T: FD->getReturnType(), TU: GetTU(CT: X));
783
784 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
785}
786
787CXType clang_getCursorResultType(CXCursor C) {
788 if (clang_isDeclaration(C.kind)) {
789 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
790 if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Val: D))
791 return MakeCXType(T: MD->getReturnType(), TU: cxcursor::getCursorTU(Cursor: C));
792
793 return clang_getResultType(X: clang_getCursorType(C));
794 }
795
796 return MakeCXType(T: QualType(), TU: cxcursor::getCursorTU(Cursor: C));
797}
798
799// FIXME: We should expose the canThrow(...) result instead of the EST.
800static CXCursor_ExceptionSpecificationKind
801getExternalExceptionSpecificationKind(ExceptionSpecificationType EST) {
802 switch (EST) {
803 case EST_None:
804 return CXCursor_ExceptionSpecificationKind_None;
805 case EST_DynamicNone:
806 return CXCursor_ExceptionSpecificationKind_DynamicNone;
807 case EST_Dynamic:
808 return CXCursor_ExceptionSpecificationKind_Dynamic;
809 case EST_MSAny:
810 return CXCursor_ExceptionSpecificationKind_MSAny;
811 case EST_BasicNoexcept:
812 return CXCursor_ExceptionSpecificationKind_BasicNoexcept;
813 case EST_NoThrow:
814 return CXCursor_ExceptionSpecificationKind_NoThrow;
815 case EST_NoexceptFalse:
816 case EST_NoexceptTrue:
817 case EST_DependentNoexcept:
818 return CXCursor_ExceptionSpecificationKind_ComputedNoexcept;
819 case EST_Unevaluated:
820 return CXCursor_ExceptionSpecificationKind_Unevaluated;
821 case EST_Uninstantiated:
822 return CXCursor_ExceptionSpecificationKind_Uninstantiated;
823 case EST_Unparsed:
824 return CXCursor_ExceptionSpecificationKind_Unparsed;
825 }
826 llvm_unreachable("invalid EST value");
827}
828
829int clang_getExceptionSpecificationType(CXType X) {
830 QualType T = GetQualType(CT: X);
831 if (T.isNull())
832 return -1;
833
834 if (const auto *FD = T->getAs<FunctionProtoType>())
835 return getExternalExceptionSpecificationKind(EST: FD->getExceptionSpecType());
836
837 return -1;
838}
839
840int clang_getCursorExceptionSpecificationType(CXCursor C) {
841 if (clang_isDeclaration(C.kind))
842 return clang_getExceptionSpecificationType(X: clang_getCursorType(C));
843
844 return -1;
845}
846
847unsigned clang_isPODType(CXType X) {
848 QualType T = GetQualType(CT: X);
849 if (T.isNull())
850 return 0;
851
852 CXTranslationUnit TU = GetTU(CT: X);
853
854 return T.isPODType(Context: cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
855}
856
857CXType clang_getElementType(CXType CT) {
858 QualType ET = QualType();
859 QualType T = GetQualType(CT);
860 const Type *TP = T.getTypePtrOrNull();
861
862 if (TP) {
863 switch (TP->getTypeClass()) {
864 case Type::ConstantArray:
865 ET = cast<ConstantArrayType> (Val: TP)->getElementType();
866 break;
867 case Type::IncompleteArray:
868 ET = cast<IncompleteArrayType> (Val: TP)->getElementType();
869 break;
870 case Type::VariableArray:
871 ET = cast<VariableArrayType> (Val: TP)->getElementType();
872 break;
873 case Type::DependentSizedArray:
874 ET = cast<DependentSizedArrayType> (Val: TP)->getElementType();
875 break;
876 case Type::Vector:
877 ET = cast<VectorType> (Val: TP)->getElementType();
878 break;
879 case Type::ExtVector:
880 ET = cast<ExtVectorType>(Val: TP)->getElementType();
881 break;
882 case Type::Complex:
883 ET = cast<ComplexType> (Val: TP)->getElementType();
884 break;
885 default:
886 break;
887 }
888 }
889 return MakeCXType(T: ET, TU: GetTU(CT));
890}
891
892long long clang_getNumElements(CXType CT) {
893 long long result = -1;
894 QualType T = GetQualType(CT);
895 const Type *TP = T.getTypePtrOrNull();
896
897 if (TP) {
898 switch (TP->getTypeClass()) {
899 case Type::ConstantArray:
900 result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue();
901 break;
902 case Type::Vector:
903 result = cast<VectorType> (Val: TP)->getNumElements();
904 break;
905 case Type::ExtVector:
906 result = cast<ExtVectorType>(Val: TP)->getNumElements();
907 break;
908 default:
909 break;
910 }
911 }
912 return result;
913}
914
915CXType clang_getArrayElementType(CXType CT) {
916 QualType ET = QualType();
917 QualType T = GetQualType(CT);
918 const Type *TP = T.getTypePtrOrNull();
919
920 if (TP) {
921 switch (TP->getTypeClass()) {
922 case Type::ConstantArray:
923 ET = cast<ConstantArrayType> (Val: TP)->getElementType();
924 break;
925 case Type::IncompleteArray:
926 ET = cast<IncompleteArrayType> (Val: TP)->getElementType();
927 break;
928 case Type::VariableArray:
929 ET = cast<VariableArrayType> (Val: TP)->getElementType();
930 break;
931 case Type::DependentSizedArray:
932 ET = cast<DependentSizedArrayType> (Val: TP)->getElementType();
933 break;
934 default:
935 break;
936 }
937 }
938 return MakeCXType(T: ET, TU: GetTU(CT));
939}
940
941long long clang_getArraySize(CXType CT) {
942 long long result = -1;
943 QualType T = GetQualType(CT);
944 const Type *TP = T.getTypePtrOrNull();
945
946 if (TP) {
947 switch (TP->getTypeClass()) {
948 case Type::ConstantArray:
949 result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue();
950 break;
951 default:
952 break;
953 }
954 }
955 return result;
956}
957
958static bool isIncompleteTypeWithAlignment(QualType QT) {
959 return QT->isIncompleteArrayType() || !QT->isIncompleteType();
960}
961
962long long clang_Type_getAlignOf(CXType T) {
963 if (T.kind == CXType_Invalid)
964 return CXTypeLayoutError_Invalid;
965 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext();
966 QualType QT = GetQualType(CT: T);
967 // [expr.alignof] p1: return size_t value for complete object type, reference
968 // or array.
969 // [expr.alignof] p3: if reference type, return size of referenced type
970 if (QT->isReferenceType())
971 QT = QT.getNonReferenceType();
972 if (!isIncompleteTypeWithAlignment(QT))
973 return CXTypeLayoutError_Incomplete;
974 if (QT->isDependentType())
975 return CXTypeLayoutError_Dependent;
976 if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT))
977 if (Deduced->getDeducedType().isNull())
978 return CXTypeLayoutError_Undeduced;
979 // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
980 // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
981 // if (QT->isVoidType()) return 1;
982 return Ctx.getTypeAlignInChars(T: QT).getQuantity();
983}
984
985CXType clang_Type_getClassType(CXType CT) {
986 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT))->getASTContext();
987 QualType ET = QualType();
988 QualType T = GetQualType(CT);
989 const Type *TP = T.getTypePtrOrNull();
990
991 if (TP && TP->getTypeClass() == Type::MemberPointer) {
992 ET = Ctx.getCanonicalTagType(
993 TD: cast<MemberPointerType>(Val: TP)->getMostRecentCXXRecordDecl());
994 }
995 return MakeCXType(T: ET, TU: GetTU(CT));
996}
997
998long long clang_Type_getSizeOf(CXType T) {
999 if (T.kind == CXType_Invalid)
1000 return CXTypeLayoutError_Invalid;
1001 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext();
1002 QualType QT = GetQualType(CT: T);
1003 // [expr.sizeof] p2: if reference type, return size of referenced type
1004 if (QT->isReferenceType())
1005 QT = QT.getNonReferenceType();
1006 // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
1007 // enumeration
1008 // Note: We get the cxtype, not the cxcursor, so we can't call
1009 // FieldDecl->isBitField()
1010 // [expr.sizeof] p3: pointer ok, function not ok.
1011 // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
1012 if (QT->isIncompleteType())
1013 return CXTypeLayoutError_Incomplete;
1014 if (QT->isDependentType())
1015 return CXTypeLayoutError_Dependent;
1016 if (!QT->isConstantSizeType())
1017 return CXTypeLayoutError_NotConstantSize;
1018 if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT))
1019 if (Deduced->getDeducedType().isNull())
1020 return CXTypeLayoutError_Undeduced;
1021 // [gcc extension] lib/AST/ExprConstant.cpp:1372
1022 // HandleSizeof : {voidtype,functype} == 1
1023 // not handled by ASTContext.cpp:1313 getTypeInfoImpl
1024 if (QT->isVoidType() || QT->isFunctionType())
1025 return 1;
1026 return Ctx.getTypeSizeInChars(T: QT).getQuantity();
1027}
1028
1029static bool isTypeIncompleteForLayout(QualType QT) {
1030 return QT->isIncompleteType() && !QT->isIncompleteArrayType();
1031}
1032
1033static long long visitRecordForValidation(const RecordDecl *RD) {
1034 for (const auto *I : RD->fields()){
1035 QualType FQT = I->getType();
1036 if (isTypeIncompleteForLayout(QT: FQT))
1037 return CXTypeLayoutError_Incomplete;
1038 if (FQT->isDependentType())
1039 return CXTypeLayoutError_Dependent;
1040 // recurse
1041 if (const RecordType *ChildType = I->getType()->getAs<RecordType>()) {
1042 if (const RecordDecl *Child = ChildType->getDecl()) {
1043 long long ret = visitRecordForValidation(RD: Child);
1044 if (ret < 0)
1045 return ret;
1046 }
1047 }
1048 // else try next field
1049 }
1050 return 0;
1051}
1052
1053static long long validateFieldParentType(CXCursor PC, CXType PT){
1054 if (clang_isInvalid(PC.kind))
1055 return CXTypeLayoutError_Invalid;
1056 const RecordDecl *RD =
1057 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1058 // validate parent declaration
1059 if (!RD || RD->isInvalidDecl())
1060 return CXTypeLayoutError_Invalid;
1061 RD = RD->getDefinition();
1062 if (!RD)
1063 return CXTypeLayoutError_Incomplete;
1064 if (RD->isInvalidDecl())
1065 return CXTypeLayoutError_Invalid;
1066 // validate parent type
1067 QualType RT = GetQualType(CT: PT);
1068 if (RT->isIncompleteType())
1069 return CXTypeLayoutError_Incomplete;
1070 if (RT->isDependentType())
1071 return CXTypeLayoutError_Dependent;
1072 // We recurse into all record fields to detect incomplete and dependent types.
1073 long long Error = visitRecordForValidation(RD);
1074 if (Error < 0)
1075 return Error;
1076 return 0;
1077}
1078
1079long long clang_Type_getOffsetOf(CXType PT, const char *S) {
1080 // check that PT is not incomplete/dependent
1081 CXCursor PC = clang_getTypeDeclaration(CT: PT);
1082 long long Error = validateFieldParentType(PC,PT);
1083 if (Error < 0)
1084 return Error;
1085 if (!S)
1086 return CXTypeLayoutError_InvalidFieldName;
1087 // lookup field
1088 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: PT))->getASTContext();
1089 IdentifierInfo *II = &Ctx.Idents.get(Name: S);
1090 DeclarationName FieldName(II);
1091 const RecordDecl *RD =
1092 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1093 // verified in validateFieldParentType
1094 RD = RD->getDefinition();
1095 RecordDecl::lookup_result Res = RD->lookup(Name: FieldName);
1096 // If a field of the parent record is incomplete, lookup will fail.
1097 // and we would return InvalidFieldName instead of Incomplete.
1098 // But this erroneous results does protects again a hidden assertion failure
1099 // in the RecordLayoutBuilder
1100 if (!Res.isSingleResult())
1101 return CXTypeLayoutError_InvalidFieldName;
1102 if (const FieldDecl *FD = dyn_cast<FieldDecl>(Val: Res.front()))
1103 return Ctx.getFieldOffset(FD);
1104 if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Val: Res.front()))
1105 return Ctx.getFieldOffset(FD: IFD);
1106 // we don't want any other Decl Type.
1107 return CXTypeLayoutError_InvalidFieldName;
1108}
1109
1110CXType clang_Type_getModifiedType(CXType CT) {
1111 QualType T = GetQualType(CT);
1112 if (T.isNull())
1113 return MakeCXType(T: QualType(), TU: GetTU(CT));
1114
1115 if (auto *ATT = T->getAs<AttributedType>())
1116 return MakeCXType(T: ATT->getModifiedType(), TU: GetTU(CT));
1117
1118 if (auto *ATT = T->getAs<BTFTagAttributedType>())
1119 return MakeCXType(T: ATT->getWrappedType(), TU: GetTU(CT));
1120
1121 return MakeCXType(T: QualType(), TU: GetTU(CT));
1122}
1123
1124long long clang_Cursor_getOffsetOfField(CXCursor C) {
1125 if (clang_isDeclaration(C.kind)) {
1126 // we need to validate the parent type
1127 CXCursor PC = clang_getCursorSemanticParent(cursor: C);
1128 CXType PT = clang_getCursorType(C: PC);
1129 long long Error = validateFieldParentType(PC,PT);
1130 if (Error < 0)
1131 return Error;
1132 // proceed with the offset calculation
1133 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1134 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C);
1135 if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: D))
1136 return Ctx.getFieldOffset(FD);
1137 if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(Val: D))
1138 return Ctx.getFieldOffset(FD: IFD);
1139 }
1140 return -1;
1141}
1142
1143long long clang_getOffsetOfBase(CXCursor Parent, CXCursor Base) {
1144 if (Base.kind != CXCursor_CXXBaseSpecifier)
1145 return -1;
1146
1147 if (!clang_isDeclaration(Parent.kind))
1148 return -1;
1149
1150 // we need to validate the parent type
1151 CXType PT = clang_getCursorType(C: Parent);
1152 long long Error = validateFieldParentType(PC: Parent, PT);
1153 if (Error < 0)
1154 return Error;
1155
1156 const CXXRecordDecl *ParentRD =
1157 dyn_cast<CXXRecordDecl>(Val: cxcursor::getCursorDecl(Cursor: Parent));
1158 if (!ParentRD)
1159 return -1;
1160
1161 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: Base);
1162 const CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C: Base);
1163 if (ParentRD->bases_begin() > B || ParentRD->bases_end() <= B)
1164 return -1;
1165
1166 const CXXRecordDecl *BaseRD = B->getType()->getAsCXXRecordDecl();
1167 if (!BaseRD)
1168 return -1;
1169
1170 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(D: ParentRD);
1171 if (B->isVirtual())
1172 return Ctx.toBits(CharSize: Layout.getVBaseClassOffset(VBase: BaseRD));
1173 return Ctx.toBits(CharSize: Layout.getBaseClassOffset(Base: BaseRD));
1174}
1175
1176enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {
1177 QualType QT = GetQualType(CT: T);
1178 if (QT.isNull())
1179 return CXRefQualifier_None;
1180 const FunctionProtoType *FD = QT->getAs<FunctionProtoType>();
1181 if (!FD)
1182 return CXRefQualifier_None;
1183 switch (FD->getRefQualifier()) {
1184 case RQ_None:
1185 return CXRefQualifier_None;
1186 case RQ_LValue:
1187 return CXRefQualifier_LValue;
1188 case RQ_RValue:
1189 return CXRefQualifier_RValue;
1190 }
1191 return CXRefQualifier_None;
1192}
1193
1194unsigned clang_Cursor_isBitField(CXCursor C) {
1195 if (!clang_isDeclaration(C.kind))
1196 return 0;
1197 const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: cxcursor::getCursorDecl(Cursor: C));
1198 if (!FD)
1199 return 0;
1200 return FD->isBitField();
1201}
1202
1203CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
1204 if (!clang_isDeclaration(C.kind))
1205 return cxstring::createEmpty();
1206
1207 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1208 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C);
1209 std::string encoding;
1210
1211 if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) {
1212 encoding = Ctx.getObjCEncodingForMethodDecl(Decl: OMD);
1213 } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(Val: D))
1214 encoding = Ctx.getObjCEncodingForPropertyDecl(PD: OPD, Container: nullptr);
1215 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D))
1216 encoding = Ctx.getObjCEncodingForFunctionDecl(Decl: FD);
1217 else {
1218 QualType Ty;
1219 if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D))
1220 Ty = Ctx.getTypeDeclType(Decl: TD);
1221 if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D))
1222 Ty = VD->getType();
1223 else return cxstring::createRef(String: "?");
1224 Ctx.getObjCEncodingForType(T: Ty, S&: encoding);
1225 }
1226
1227 return cxstring::createDup(String: encoding);
1228}
1229
1230static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> TA) {
1231 unsigned size = TA.size();
1232 for (const auto &Arg : TA)
1233 if (Arg.getKind() == TemplateArgument::Pack)
1234 size += Arg.pack_size() - 1;
1235 return size;
1236}
1237
1238int clang_Type_getNumTemplateArguments(CXType CT) {
1239 QualType T = GetQualType(CT);
1240 if (T.isNull())
1241 return -1;
1242
1243 auto TA = GetTemplateArguments(Type: T);
1244 if (!TA)
1245 return -1;
1246
1247 return GetTemplateArgumentArraySize(TA: *TA);
1248}
1249
1250CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
1251 QualType T = GetQualType(CT);
1252 if (T.isNull())
1253 return MakeCXType(T: QualType(), TU: GetTU(CT));
1254
1255 auto TA = GetTemplateArguments(Type: T);
1256 if (!TA)
1257 return MakeCXType(T: QualType(), TU: GetTU(CT));
1258
1259 std::optional<QualType> QT = FindTemplateArgumentTypeAt(TA: *TA, index);
1260 return MakeCXType(T: QT.value_or(u: QualType()), TU: GetTU(CT));
1261}
1262
1263CXType clang_Type_getObjCObjectBaseType(CXType CT) {
1264 QualType T = GetQualType(CT);
1265 if (T.isNull())
1266 return MakeCXType(T: QualType(), TU: GetTU(CT));
1267
1268 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1269 if (!OT)
1270 return MakeCXType(T: QualType(), TU: GetTU(CT));
1271
1272 return MakeCXType(T: OT->getBaseType(), TU: GetTU(CT));
1273}
1274
1275unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) {
1276 QualType T = GetQualType(CT);
1277 if (T.isNull())
1278 return 0;
1279
1280 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1281 if (!OT)
1282 return 0;
1283
1284 return OT->getNumProtocols();
1285}
1286
1287CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) {
1288 QualType T = GetQualType(CT);
1289 if (T.isNull())
1290 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1291
1292 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1293 if (!OT)
1294 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1295
1296 const ObjCProtocolDecl *PD = OT->getProtocol(I: i);
1297 if (!PD)
1298 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1299
1300 return cxcursor::MakeCXCursor(D: PD, TU: GetTU(CT));
1301}
1302
1303unsigned clang_Type_getNumObjCTypeArgs(CXType CT) {
1304 QualType T = GetQualType(CT);
1305 if (T.isNull())
1306 return 0;
1307
1308 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1309 if (!OT)
1310 return 0;
1311
1312 return OT->getTypeArgs().size();
1313}
1314
1315CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) {
1316 QualType T = GetQualType(CT);
1317 if (T.isNull())
1318 return MakeCXType(T: QualType(), TU: GetTU(CT));
1319
1320 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1321 if (!OT)
1322 return MakeCXType(T: QualType(), TU: GetTU(CT));
1323
1324 const ArrayRef<QualType> TA = OT->getTypeArgs();
1325 if ((size_t)i >= TA.size())
1326 return MakeCXType(T: QualType(), TU: GetTU(CT));
1327
1328 return MakeCXType(T: TA[i], TU: GetTU(CT));
1329}
1330
1331unsigned clang_Type_visitFields(CXType PT,
1332 CXFieldVisitor visitor,
1333 CXClientData client_data){
1334 CXCursor PC = clang_getTypeDeclaration(CT: PT);
1335 if (clang_isInvalid(PC.kind))
1336 return false;
1337 const RecordDecl *RD =
1338 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1339 if (!RD || RD->isInvalidDecl())
1340 return false;
1341 RD = RD->getDefinition();
1342 if (!RD || RD->isInvalidDecl())
1343 return false;
1344
1345 for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
1346 I != E; ++I){
1347 const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: (*I));
1348 // Callback to the client.
1349 switch (visitor(cxcursor::MakeCXCursor(D: FD, TU: GetTU(CT: PT)), client_data)){
1350 case CXVisit_Break:
1351 return true;
1352 case CXVisit_Continue:
1353 break;
1354 }
1355 }
1356 return true;
1357}
1358
1359unsigned clang_Cursor_isAnonymous(CXCursor C){
1360 if (!clang_isDeclaration(C.kind))
1361 return 0;
1362 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1363 if (const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D)) {
1364 return ND->isAnonymousNamespace();
1365 } else if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(Val: D)) {
1366 return TD->getTypedefNameForAnonDecl() == nullptr &&
1367 TD->getIdentifier() == nullptr;
1368 }
1369
1370 return 0;
1371}
1372
1373unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C){
1374 if (!clang_isDeclaration(C.kind))
1375 return 0;
1376 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1377 if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(Val: D))
1378 return FD->isAnonymousStructOrUnion();
1379 return 0;
1380}
1381
1382unsigned clang_Cursor_isInlineNamespace(CXCursor C) {
1383 if (!clang_isDeclaration(C.kind))
1384 return 0;
1385 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1386 const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D);
1387 return ND ? ND->isInline() : 0;
1388}
1389
1390CXType clang_Type_getNamedType(CXType CT){
1391 QualType T = GetQualType(CT);
1392
1393 if (!T.isNull() && !T.isCanonical())
1394 return MakeCXType(T, TU: GetTU(CT));
1395
1396 return MakeCXType(T: QualType(), TU: GetTU(CT));
1397}
1398
1399unsigned clang_Type_isTransparentTagTypedef(CXType TT){
1400 QualType T = GetQualType(CT: TT);
1401 if (auto *TT = dyn_cast_or_null<TypedefType>(Val: T.getTypePtrOrNull())) {
1402 if (auto *D = TT->getDecl())
1403 return D->isTransparentTag();
1404 }
1405 return false;
1406}
1407
1408enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) {
1409 QualType T = GetQualType(CT);
1410 if (T.isNull())
1411 return CXTypeNullability_Invalid;
1412
1413 if (auto nullability = T->getNullability()) {
1414 switch (*nullability) {
1415 case NullabilityKind::NonNull:
1416 return CXTypeNullability_NonNull;
1417 case NullabilityKind::Nullable:
1418 return CXTypeNullability_Nullable;
1419 case NullabilityKind::NullableResult:
1420 return CXTypeNullability_NullableResult;
1421 case NullabilityKind::Unspecified:
1422 return CXTypeNullability_Unspecified;
1423 }
1424 }
1425 return CXTypeNullability_Invalid;
1426}
1427
1428CXType clang_Type_getValueType(CXType CT) {
1429 QualType T = GetQualType(CT);
1430
1431 if (T.isNull() || !T->isAtomicType())
1432 return MakeCXType(T: QualType(), TU: GetTU(CT));
1433
1434 const auto *AT = T->castAs<AtomicType>();
1435 return MakeCXType(T: AT->getValueType(), TU: GetTU(CT));
1436}
1437