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_DeviceKernel:
734 return CXCallingConv_Unexposed;
735 break;
736 }
737#undef TCALLINGCONV
738 }
739
740 return CXCallingConv_Invalid;
741}
742
743int clang_getNumArgTypes(CXType X) {
744 QualType T = GetQualType(CT: X);
745 if (T.isNull())
746 return -1;
747
748 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
749 return FD->getNumParams();
750 }
751
752 if (T->getAs<FunctionNoProtoType>()) {
753 return 0;
754 }
755
756 return -1;
757}
758
759CXType clang_getArgType(CXType X, unsigned i) {
760 QualType T = GetQualType(CT: X);
761 if (T.isNull())
762 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
763
764 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
765 unsigned numParams = FD->getNumParams();
766 if (i >= numParams)
767 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
768
769 return MakeCXType(T: FD->getParamType(i), TU: GetTU(CT: X));
770 }
771
772 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
773}
774
775CXType clang_getResultType(CXType X) {
776 QualType T = GetQualType(CT: X);
777 if (T.isNull())
778 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
779
780 if (const FunctionType *FD = T->getAs<FunctionType>())
781 return MakeCXType(T: FD->getReturnType(), TU: GetTU(CT: X));
782
783 return MakeCXType(T: QualType(), TU: GetTU(CT: X));
784}
785
786CXType clang_getCursorResultType(CXCursor C) {
787 if (clang_isDeclaration(C.kind)) {
788 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
789 if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Val: D))
790 return MakeCXType(T: MD->getReturnType(), TU: cxcursor::getCursorTU(Cursor: C));
791
792 return clang_getResultType(X: clang_getCursorType(C));
793 }
794
795 return MakeCXType(T: QualType(), TU: cxcursor::getCursorTU(Cursor: C));
796}
797
798// FIXME: We should expose the canThrow(...) result instead of the EST.
799static CXCursor_ExceptionSpecificationKind
800getExternalExceptionSpecificationKind(ExceptionSpecificationType EST) {
801 switch (EST) {
802 case EST_None:
803 return CXCursor_ExceptionSpecificationKind_None;
804 case EST_DynamicNone:
805 return CXCursor_ExceptionSpecificationKind_DynamicNone;
806 case EST_Dynamic:
807 return CXCursor_ExceptionSpecificationKind_Dynamic;
808 case EST_MSAny:
809 return CXCursor_ExceptionSpecificationKind_MSAny;
810 case EST_BasicNoexcept:
811 return CXCursor_ExceptionSpecificationKind_BasicNoexcept;
812 case EST_NoThrow:
813 return CXCursor_ExceptionSpecificationKind_NoThrow;
814 case EST_NoexceptFalse:
815 case EST_NoexceptTrue:
816 case EST_DependentNoexcept:
817 return CXCursor_ExceptionSpecificationKind_ComputedNoexcept;
818 case EST_Unevaluated:
819 return CXCursor_ExceptionSpecificationKind_Unevaluated;
820 case EST_Uninstantiated:
821 return CXCursor_ExceptionSpecificationKind_Uninstantiated;
822 case EST_Unparsed:
823 return CXCursor_ExceptionSpecificationKind_Unparsed;
824 }
825 llvm_unreachable("invalid EST value");
826}
827
828int clang_getExceptionSpecificationType(CXType X) {
829 QualType T = GetQualType(CT: X);
830 if (T.isNull())
831 return -1;
832
833 if (const auto *FD = T->getAs<FunctionProtoType>())
834 return getExternalExceptionSpecificationKind(EST: FD->getExceptionSpecType());
835
836 return -1;
837}
838
839int clang_getCursorExceptionSpecificationType(CXCursor C) {
840 if (clang_isDeclaration(C.kind))
841 return clang_getExceptionSpecificationType(X: clang_getCursorType(C));
842
843 return -1;
844}
845
846unsigned clang_isPODType(CXType X) {
847 QualType T = GetQualType(CT: X);
848 if (T.isNull())
849 return 0;
850
851 CXTranslationUnit TU = GetTU(CT: X);
852
853 return T.isPODType(Context: cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
854}
855
856CXType clang_getElementType(CXType CT) {
857 QualType ET = QualType();
858 QualType T = GetQualType(CT);
859 const Type *TP = T.getTypePtrOrNull();
860
861 if (TP) {
862 switch (TP->getTypeClass()) {
863 case Type::ConstantArray:
864 ET = cast<ConstantArrayType> (Val: TP)->getElementType();
865 break;
866 case Type::IncompleteArray:
867 ET = cast<IncompleteArrayType> (Val: TP)->getElementType();
868 break;
869 case Type::VariableArray:
870 ET = cast<VariableArrayType> (Val: TP)->getElementType();
871 break;
872 case Type::DependentSizedArray:
873 ET = cast<DependentSizedArrayType> (Val: TP)->getElementType();
874 break;
875 case Type::Vector:
876 ET = cast<VectorType> (Val: TP)->getElementType();
877 break;
878 case Type::ExtVector:
879 ET = cast<ExtVectorType>(Val: TP)->getElementType();
880 break;
881 case Type::Complex:
882 ET = cast<ComplexType> (Val: TP)->getElementType();
883 break;
884 default:
885 break;
886 }
887 }
888 return MakeCXType(T: ET, TU: GetTU(CT));
889}
890
891long long clang_getNumElements(CXType CT) {
892 long long result = -1;
893 QualType T = GetQualType(CT);
894 const Type *TP = T.getTypePtrOrNull();
895
896 if (TP) {
897 switch (TP->getTypeClass()) {
898 case Type::ConstantArray:
899 result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue();
900 break;
901 case Type::Vector:
902 result = cast<VectorType> (Val: TP)->getNumElements();
903 break;
904 case Type::ExtVector:
905 result = cast<ExtVectorType>(Val: TP)->getNumElements();
906 break;
907 default:
908 break;
909 }
910 }
911 return result;
912}
913
914CXType clang_getArrayElementType(CXType CT) {
915 QualType ET = QualType();
916 QualType T = GetQualType(CT);
917 const Type *TP = T.getTypePtrOrNull();
918
919 if (TP) {
920 switch (TP->getTypeClass()) {
921 case Type::ConstantArray:
922 ET = cast<ConstantArrayType> (Val: TP)->getElementType();
923 break;
924 case Type::IncompleteArray:
925 ET = cast<IncompleteArrayType> (Val: TP)->getElementType();
926 break;
927 case Type::VariableArray:
928 ET = cast<VariableArrayType> (Val: TP)->getElementType();
929 break;
930 case Type::DependentSizedArray:
931 ET = cast<DependentSizedArrayType> (Val: TP)->getElementType();
932 break;
933 default:
934 break;
935 }
936 }
937 return MakeCXType(T: ET, TU: GetTU(CT));
938}
939
940long long clang_getArraySize(CXType CT) {
941 long long result = -1;
942 QualType T = GetQualType(CT);
943 const Type *TP = T.getTypePtrOrNull();
944
945 if (TP) {
946 switch (TP->getTypeClass()) {
947 case Type::ConstantArray:
948 result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue();
949 break;
950 default:
951 break;
952 }
953 }
954 return result;
955}
956
957static bool isIncompleteTypeWithAlignment(QualType QT) {
958 return QT->isIncompleteArrayType() || !QT->isIncompleteType();
959}
960
961long long clang_Type_getAlignOf(CXType T) {
962 if (T.kind == CXType_Invalid)
963 return CXTypeLayoutError_Invalid;
964 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext();
965 QualType QT = GetQualType(CT: T);
966 // [expr.alignof] p1: return size_t value for complete object type, reference
967 // or array.
968 // [expr.alignof] p3: if reference type, return size of referenced type
969 if (QT->isReferenceType())
970 QT = QT.getNonReferenceType();
971 if (!isIncompleteTypeWithAlignment(QT))
972 return CXTypeLayoutError_Incomplete;
973 if (QT->isDependentType())
974 return CXTypeLayoutError_Dependent;
975 if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT))
976 if (Deduced->getDeducedType().isNull())
977 return CXTypeLayoutError_Undeduced;
978 // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
979 // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
980 // if (QT->isVoidType()) return 1;
981 return Ctx.getTypeAlignInChars(T: QT).getQuantity();
982}
983
984CXType clang_Type_getClassType(CXType CT) {
985 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT))->getASTContext();
986 QualType ET = QualType();
987 QualType T = GetQualType(CT);
988 const Type *TP = T.getTypePtrOrNull();
989
990 if (TP && TP->getTypeClass() == Type::MemberPointer) {
991 ET = Ctx.getCanonicalTagType(
992 TD: cast<MemberPointerType>(Val: TP)->getMostRecentCXXRecordDecl());
993 }
994 return MakeCXType(T: ET, TU: GetTU(CT));
995}
996
997long long clang_Type_getSizeOf(CXType T) {
998 if (T.kind == CXType_Invalid)
999 return CXTypeLayoutError_Invalid;
1000 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext();
1001 QualType QT = GetQualType(CT: T);
1002 // [expr.sizeof] p2: if reference type, return size of referenced type
1003 if (QT->isReferenceType())
1004 QT = QT.getNonReferenceType();
1005 // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
1006 // enumeration
1007 // Note: We get the cxtype, not the cxcursor, so we can't call
1008 // FieldDecl->isBitField()
1009 // [expr.sizeof] p3: pointer ok, function not ok.
1010 // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
1011 if (QT->isIncompleteType())
1012 return CXTypeLayoutError_Incomplete;
1013 if (QT->isDependentType())
1014 return CXTypeLayoutError_Dependent;
1015 if (!QT->isConstantSizeType())
1016 return CXTypeLayoutError_NotConstantSize;
1017 if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT))
1018 if (Deduced->getDeducedType().isNull())
1019 return CXTypeLayoutError_Undeduced;
1020 // [gcc extension] lib/AST/ExprConstant.cpp:1372
1021 // HandleSizeof : {voidtype,functype} == 1
1022 // not handled by ASTContext.cpp:1313 getTypeInfoImpl
1023 if (QT->isVoidType() || QT->isFunctionType())
1024 return 1;
1025 return Ctx.getTypeSizeInChars(T: QT).getQuantity();
1026}
1027
1028static bool isTypeIncompleteForLayout(QualType QT) {
1029 return QT->isIncompleteType() && !QT->isIncompleteArrayType();
1030}
1031
1032static long long visitRecordForValidation(const RecordDecl *RD) {
1033 for (const auto *I : RD->fields()){
1034 QualType FQT = I->getType();
1035 if (isTypeIncompleteForLayout(QT: FQT))
1036 return CXTypeLayoutError_Incomplete;
1037 if (FQT->isDependentType())
1038 return CXTypeLayoutError_Dependent;
1039 // recurse
1040 if (const RecordType *ChildType = I->getType()->getAs<RecordType>()) {
1041 if (const RecordDecl *Child = ChildType->getDecl()) {
1042 long long ret = visitRecordForValidation(RD: Child);
1043 if (ret < 0)
1044 return ret;
1045 }
1046 }
1047 // else try next field
1048 }
1049 return 0;
1050}
1051
1052static long long validateFieldParentType(CXCursor PC, CXType PT){
1053 if (clang_isInvalid(PC.kind))
1054 return CXTypeLayoutError_Invalid;
1055 const RecordDecl *RD =
1056 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1057 // validate parent declaration
1058 if (!RD || RD->isInvalidDecl())
1059 return CXTypeLayoutError_Invalid;
1060 RD = RD->getDefinition();
1061 if (!RD)
1062 return CXTypeLayoutError_Incomplete;
1063 if (RD->isInvalidDecl())
1064 return CXTypeLayoutError_Invalid;
1065 // validate parent type
1066 QualType RT = GetQualType(CT: PT);
1067 if (RT->isIncompleteType())
1068 return CXTypeLayoutError_Incomplete;
1069 if (RT->isDependentType())
1070 return CXTypeLayoutError_Dependent;
1071 // We recurse into all record fields to detect incomplete and dependent types.
1072 long long Error = visitRecordForValidation(RD);
1073 if (Error < 0)
1074 return Error;
1075 return 0;
1076}
1077
1078long long clang_Type_getOffsetOf(CXType PT, const char *S) {
1079 // check that PT is not incomplete/dependent
1080 CXCursor PC = clang_getTypeDeclaration(CT: PT);
1081 long long Error = validateFieldParentType(PC,PT);
1082 if (Error < 0)
1083 return Error;
1084 if (!S)
1085 return CXTypeLayoutError_InvalidFieldName;
1086 // lookup field
1087 ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: PT))->getASTContext();
1088 IdentifierInfo *II = &Ctx.Idents.get(Name: S);
1089 DeclarationName FieldName(II);
1090 const RecordDecl *RD =
1091 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1092 // verified in validateFieldParentType
1093 RD = RD->getDefinition();
1094 RecordDecl::lookup_result Res = RD->lookup(Name: FieldName);
1095 // If a field of the parent record is incomplete, lookup will fail.
1096 // and we would return InvalidFieldName instead of Incomplete.
1097 // But this erroneous results does protects again a hidden assertion failure
1098 // in the RecordLayoutBuilder
1099 if (!Res.isSingleResult())
1100 return CXTypeLayoutError_InvalidFieldName;
1101 if (const FieldDecl *FD = dyn_cast<FieldDecl>(Val: Res.front()))
1102 return Ctx.getFieldOffset(FD);
1103 if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Val: Res.front()))
1104 return Ctx.getFieldOffset(FD: IFD);
1105 // we don't want any other Decl Type.
1106 return CXTypeLayoutError_InvalidFieldName;
1107}
1108
1109CXType clang_Type_getModifiedType(CXType CT) {
1110 QualType T = GetQualType(CT);
1111 if (T.isNull())
1112 return MakeCXType(T: QualType(), TU: GetTU(CT));
1113
1114 if (auto *ATT = T->getAs<AttributedType>())
1115 return MakeCXType(T: ATT->getModifiedType(), TU: GetTU(CT));
1116
1117 if (auto *ATT = T->getAs<BTFTagAttributedType>())
1118 return MakeCXType(T: ATT->getWrappedType(), TU: GetTU(CT));
1119
1120 return MakeCXType(T: QualType(), TU: GetTU(CT));
1121}
1122
1123long long clang_Cursor_getOffsetOfField(CXCursor C) {
1124 if (clang_isDeclaration(C.kind)) {
1125 // we need to validate the parent type
1126 CXCursor PC = clang_getCursorSemanticParent(cursor: C);
1127 CXType PT = clang_getCursorType(C: PC);
1128 long long Error = validateFieldParentType(PC,PT);
1129 if (Error < 0)
1130 return Error;
1131 // proceed with the offset calculation
1132 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1133 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C);
1134 if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: D))
1135 return Ctx.getFieldOffset(FD);
1136 if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(Val: D))
1137 return Ctx.getFieldOffset(FD: IFD);
1138 }
1139 return -1;
1140}
1141
1142long long clang_getOffsetOfBase(CXCursor Parent, CXCursor Base) {
1143 if (Base.kind != CXCursor_CXXBaseSpecifier)
1144 return -1;
1145
1146 if (!clang_isDeclaration(Parent.kind))
1147 return -1;
1148
1149 // we need to validate the parent type
1150 CXType PT = clang_getCursorType(C: Parent);
1151 long long Error = validateFieldParentType(PC: Parent, PT);
1152 if (Error < 0)
1153 return Error;
1154
1155 const CXXRecordDecl *ParentRD =
1156 dyn_cast<CXXRecordDecl>(Val: cxcursor::getCursorDecl(Cursor: Parent));
1157 if (!ParentRD)
1158 return -1;
1159
1160 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: Base);
1161 const CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C: Base);
1162 if (ParentRD->bases_begin() > B || ParentRD->bases_end() <= B)
1163 return -1;
1164
1165 const CXXRecordDecl *BaseRD = B->getType()->getAsCXXRecordDecl();
1166 if (!BaseRD)
1167 return -1;
1168
1169 const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(D: ParentRD);
1170 if (B->isVirtual())
1171 return Ctx.toBits(CharSize: Layout.getVBaseClassOffset(VBase: BaseRD));
1172 return Ctx.toBits(CharSize: Layout.getBaseClassOffset(Base: BaseRD));
1173}
1174
1175enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {
1176 QualType QT = GetQualType(CT: T);
1177 if (QT.isNull())
1178 return CXRefQualifier_None;
1179 const FunctionProtoType *FD = QT->getAs<FunctionProtoType>();
1180 if (!FD)
1181 return CXRefQualifier_None;
1182 switch (FD->getRefQualifier()) {
1183 case RQ_None:
1184 return CXRefQualifier_None;
1185 case RQ_LValue:
1186 return CXRefQualifier_LValue;
1187 case RQ_RValue:
1188 return CXRefQualifier_RValue;
1189 }
1190 return CXRefQualifier_None;
1191}
1192
1193unsigned clang_Cursor_isBitField(CXCursor C) {
1194 if (!clang_isDeclaration(C.kind))
1195 return 0;
1196 const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: cxcursor::getCursorDecl(Cursor: C));
1197 if (!FD)
1198 return 0;
1199 return FD->isBitField();
1200}
1201
1202CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
1203 if (!clang_isDeclaration(C.kind))
1204 return cxstring::createEmpty();
1205
1206 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1207 ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C);
1208 std::string encoding;
1209
1210 if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) {
1211 encoding = Ctx.getObjCEncodingForMethodDecl(Decl: OMD);
1212 } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(Val: D))
1213 encoding = Ctx.getObjCEncodingForPropertyDecl(PD: OPD, Container: nullptr);
1214 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D))
1215 encoding = Ctx.getObjCEncodingForFunctionDecl(Decl: FD);
1216 else {
1217 QualType Ty;
1218 if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D))
1219 Ty = Ctx.getTypeDeclType(Decl: TD);
1220 if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D))
1221 Ty = VD->getType();
1222 else return cxstring::createRef(String: "?");
1223 Ctx.getObjCEncodingForType(T: Ty, S&: encoding);
1224 }
1225
1226 return cxstring::createDup(String: encoding);
1227}
1228
1229static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> TA) {
1230 unsigned size = TA.size();
1231 for (const auto &Arg : TA)
1232 if (Arg.getKind() == TemplateArgument::Pack)
1233 size += Arg.pack_size() - 1;
1234 return size;
1235}
1236
1237int clang_Type_getNumTemplateArguments(CXType CT) {
1238 QualType T = GetQualType(CT);
1239 if (T.isNull())
1240 return -1;
1241
1242 auto TA = GetTemplateArguments(Type: T);
1243 if (!TA)
1244 return -1;
1245
1246 return GetTemplateArgumentArraySize(TA: *TA);
1247}
1248
1249CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
1250 QualType T = GetQualType(CT);
1251 if (T.isNull())
1252 return MakeCXType(T: QualType(), TU: GetTU(CT));
1253
1254 auto TA = GetTemplateArguments(Type: T);
1255 if (!TA)
1256 return MakeCXType(T: QualType(), TU: GetTU(CT));
1257
1258 std::optional<QualType> QT = FindTemplateArgumentTypeAt(TA: *TA, index);
1259 return MakeCXType(T: QT.value_or(u: QualType()), TU: GetTU(CT));
1260}
1261
1262CXType clang_Type_getObjCObjectBaseType(CXType CT) {
1263 QualType T = GetQualType(CT);
1264 if (T.isNull())
1265 return MakeCXType(T: QualType(), TU: GetTU(CT));
1266
1267 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1268 if (!OT)
1269 return MakeCXType(T: QualType(), TU: GetTU(CT));
1270
1271 return MakeCXType(T: OT->getBaseType(), TU: GetTU(CT));
1272}
1273
1274unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) {
1275 QualType T = GetQualType(CT);
1276 if (T.isNull())
1277 return 0;
1278
1279 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1280 if (!OT)
1281 return 0;
1282
1283 return OT->getNumProtocols();
1284}
1285
1286CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) {
1287 QualType T = GetQualType(CT);
1288 if (T.isNull())
1289 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1290
1291 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1292 if (!OT)
1293 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1294
1295 const ObjCProtocolDecl *PD = OT->getProtocol(I: i);
1296 if (!PD)
1297 return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound);
1298
1299 return cxcursor::MakeCXCursor(D: PD, TU: GetTU(CT));
1300}
1301
1302unsigned clang_Type_getNumObjCTypeArgs(CXType CT) {
1303 QualType T = GetQualType(CT);
1304 if (T.isNull())
1305 return 0;
1306
1307 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1308 if (!OT)
1309 return 0;
1310
1311 return OT->getTypeArgs().size();
1312}
1313
1314CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) {
1315 QualType T = GetQualType(CT);
1316 if (T.isNull())
1317 return MakeCXType(T: QualType(), TU: GetTU(CT));
1318
1319 const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T);
1320 if (!OT)
1321 return MakeCXType(T: QualType(), TU: GetTU(CT));
1322
1323 const ArrayRef<QualType> TA = OT->getTypeArgs();
1324 if ((size_t)i >= TA.size())
1325 return MakeCXType(T: QualType(), TU: GetTU(CT));
1326
1327 return MakeCXType(T: TA[i], TU: GetTU(CT));
1328}
1329
1330unsigned clang_Type_visitFields(CXType PT,
1331 CXFieldVisitor visitor,
1332 CXClientData client_data){
1333 CXCursor PC = clang_getTypeDeclaration(CT: PT);
1334 if (clang_isInvalid(PC.kind))
1335 return false;
1336 const RecordDecl *RD =
1337 dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
1338 if (!RD || RD->isInvalidDecl())
1339 return false;
1340 RD = RD->getDefinition();
1341 if (!RD || RD->isInvalidDecl())
1342 return false;
1343
1344 for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
1345 I != E; ++I){
1346 const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: (*I));
1347 // Callback to the client.
1348 switch (visitor(cxcursor::MakeCXCursor(D: FD, TU: GetTU(CT: PT)), client_data)){
1349 case CXVisit_Break:
1350 return true;
1351 case CXVisit_Continue:
1352 break;
1353 }
1354 }
1355 return true;
1356}
1357
1358unsigned clang_Cursor_isAnonymous(CXCursor C){
1359 if (!clang_isDeclaration(C.kind))
1360 return 0;
1361 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1362 if (const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D)) {
1363 return ND->isAnonymousNamespace();
1364 } else if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(Val: D)) {
1365 return TD->getTypedefNameForAnonDecl() == nullptr &&
1366 TD->getIdentifier() == nullptr;
1367 }
1368
1369 return 0;
1370}
1371
1372unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C){
1373 if (!clang_isDeclaration(C.kind))
1374 return 0;
1375 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1376 if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(Val: D))
1377 return FD->isAnonymousStructOrUnion();
1378 return 0;
1379}
1380
1381unsigned clang_Cursor_isInlineNamespace(CXCursor C) {
1382 if (!clang_isDeclaration(C.kind))
1383 return 0;
1384 const Decl *D = cxcursor::getCursorDecl(Cursor: C);
1385 const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D);
1386 return ND ? ND->isInline() : 0;
1387}
1388
1389CXType clang_Type_getNamedType(CXType CT){
1390 QualType T = GetQualType(CT);
1391
1392 if (!T.isNull() && !T.isCanonical())
1393 return MakeCXType(T, TU: GetTU(CT));
1394
1395 return MakeCXType(T: QualType(), TU: GetTU(CT));
1396}
1397
1398unsigned clang_Type_isTransparentTagTypedef(CXType TT){
1399 QualType T = GetQualType(CT: TT);
1400 if (auto *TT = dyn_cast_or_null<TypedefType>(Val: T.getTypePtrOrNull())) {
1401 if (auto *D = TT->getDecl())
1402 return D->isTransparentTag();
1403 }
1404 return false;
1405}
1406
1407enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) {
1408 QualType T = GetQualType(CT);
1409 if (T.isNull())
1410 return CXTypeNullability_Invalid;
1411
1412 if (auto nullability = T->getNullability()) {
1413 switch (*nullability) {
1414 case NullabilityKind::NonNull:
1415 return CXTypeNullability_NonNull;
1416 case NullabilityKind::Nullable:
1417 return CXTypeNullability_Nullable;
1418 case NullabilityKind::NullableResult:
1419 return CXTypeNullability_NullableResult;
1420 case NullabilityKind::Unspecified:
1421 return CXTypeNullability_Unspecified;
1422 }
1423 }
1424 return CXTypeNullability_Invalid;
1425}
1426
1427CXType clang_Type_getValueType(CXType CT) {
1428 QualType T = GetQualType(CT);
1429
1430 if (T.isNull() || !T->isAtomicType())
1431 return MakeCXType(T: QualType(), TU: GetTU(CT));
1432
1433 const auto *AT = T->castAs<AtomicType>();
1434 return MakeCXType(T: AT->getValueType(), TU: GetTU(CT));
1435}
1436