Bug Summary

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