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