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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/tools/libclang/CXType.cpp