Bug Summary

File:build/source/clang/tools/libclang/CXType.cpp
Warning:line 1040, column 8
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

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