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 | |
27 | using namespace clang; |
28 | |
29 | static 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 | |
86 | static 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(BT: cast<BuiltinType>(Val: 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 | |
129 | CXType 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(T: ATT->getEquivalentType(), TU); |
139 | } |
140 | } |
141 | if (auto *ATT = T->getAs<BTFTagAttributedType>()) { |
142 | if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes)) |
143 | return MakeCXType(T: ATT->getWrappedType(), TU); |
144 | } |
145 | // Handle paren types as the original type |
146 | if (auto *PTT = T->getAs<ParenType>()) { |
147 | return MakeCXType(T: 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(T: UnqualT)) |
154 | TK = CXType_ObjCId; |
155 | else if (Ctx.isObjCClassType(T: UnqualT)) |
156 | TK = CXType_ObjCClass; |
157 | else if (Ctx.isObjCSelType(T: 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 = { .kind: TK, .data: { TK == CXType_Invalid ? nullptr |
170 | : T.getAsOpaquePtr(), TU } }; |
171 | return CT; |
172 | } |
173 | |
174 | using cxtype::MakeCXType; |
175 | |
176 | static inline QualType GetQualType(CXType CT) { |
177 | return QualType::getFromOpaquePtr(Ptr: CT.data[0]); |
178 | } |
179 | |
180 | static inline CXTranslationUnit GetTU(CXType CT) { |
181 | return static_cast<CXTranslationUnit>(CT.data[1]); |
182 | } |
183 | |
184 | static std::optional<ArrayRef<TemplateArgument>> |
185 | GetTemplateArguments(QualType Type) { |
186 | assert(!Type.isNull()); |
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>(Val: RecordDecl); |
193 | if (TemplateDecl) |
194 | return TemplateDecl->getTemplateArgs().asArray(); |
195 | } |
196 | |
197 | return std::nullopt; |
198 | } |
199 | |
200 | static std::optional<QualType> |
201 | TemplateArgumentToQualType(const TemplateArgument &A) { |
202 | if (A.getKind() == TemplateArgument::Type) |
203 | return A.getAsType(); |
204 | return std::nullopt; |
205 | } |
206 | |
207 | static std::optional<QualType> |
208 | FindTemplateArgumentTypeAt(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 | |
224 | CXType clang_getCursorType(CXCursor C) { |
225 | using namespace cxcursor; |
226 | |
227 | CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C); |
228 | if (!TU) |
229 | return MakeCXType(T: QualType(), TU); |
230 | |
231 | ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext(); |
232 | if (clang_isExpression(C.kind)) { |
233 | QualType T = cxcursor::getCursorExpr(Cursor: C)->getType(); |
234 | return MakeCXType(T, TU); |
235 | } |
236 | |
237 | if (clang_isDeclaration(C.kind)) { |
238 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
239 | if (!D) |
240 | return MakeCXType(T: QualType(), TU); |
241 | |
242 | if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D)) |
243 | return MakeCXType(T: Context.getTypeDeclType(Decl: TD), TU); |
244 | if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(Val: D)) |
245 | return MakeCXType(T: Context.getObjCInterfaceType(Decl: ID), TU); |
246 | if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(Val: D)) |
247 | return MakeCXType(DD->getType(), TU); |
248 | if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D)) |
249 | return MakeCXType(T: VD->getType(), TU); |
250 | if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Val: D)) |
251 | return MakeCXType(T: PD->getType(), TU); |
252 | if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(Val: D)) |
253 | return MakeCXType(FTD->getTemplatedDecl()->getType(), TU); |
254 | return MakeCXType(T: QualType(), TU); |
255 | } |
256 | |
257 | if (clang_isReference(C.kind)) { |
258 | switch (C.kind) { |
259 | case CXCursor_ObjCSuperClassRef: { |
260 | QualType T |
261 | = Context.getObjCInterfaceType(Decl: getCursorObjCSuperClassRef(C).first); |
262 | return MakeCXType(T, TU); |
263 | } |
264 | |
265 | case CXCursor_ObjCClassRef: { |
266 | QualType T = Context.getObjCInterfaceType(Decl: getCursorObjCClassRef(C).first); |
267 | return MakeCXType(T, TU); |
268 | } |
269 | |
270 | case CXCursor_TypeRef: { |
271 | QualType T = Context.getTypeDeclType(Decl: getCursorTypeRef(C).first); |
272 | return MakeCXType(T, TU); |
273 | |
274 | } |
275 | |
276 | case CXCursor_CXXBaseSpecifier: |
277 | return cxtype::MakeCXType(T: getCursorCXXBaseSpecifier(C)->getType(), TU); |
278 | |
279 | case CXCursor_MemberRef: |
280 | return cxtype::MakeCXType(T: getCursorMemberRef(C).first->getType(), TU); |
281 | |
282 | case CXCursor_VariableRef: |
283 | return cxtype::MakeCXType(T: 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(T: QualType(), TU); |
294 | } |
295 | |
296 | return MakeCXType(T: QualType(), TU); |
297 | } |
298 | |
299 | CXString 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, Policy: PP); |
310 | |
311 | return cxstring::createDup(String: OS.str()); |
312 | } |
313 | |
314 | CXType clang_getTypedefDeclUnderlyingType(CXCursor C) { |
315 | using namespace cxcursor; |
316 | CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C); |
317 | |
318 | if (clang_isDeclaration(C.kind)) { |
319 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
320 | |
321 | if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(Val: D)) { |
322 | QualType T = TD->getUnderlyingType(); |
323 | return MakeCXType(T, TU); |
324 | } |
325 | } |
326 | |
327 | return MakeCXType(T: QualType(), TU); |
328 | } |
329 | |
330 | CXType clang_getEnumDeclIntegerType(CXCursor C) { |
331 | using namespace cxcursor; |
332 | CXTranslationUnit TU = cxcursor::getCursorTU(Cursor: C); |
333 | |
334 | if (clang_isDeclaration(C.kind)) { |
335 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
336 | |
337 | if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(Val: D)) { |
338 | QualType T = TD->getIntegerType(); |
339 | return MakeCXType(T, TU); |
340 | } |
341 | } |
342 | |
343 | return MakeCXType(T: QualType(), TU); |
344 | } |
345 | |
346 | long long clang_getEnumConstantDeclValue(CXCursor C) { |
347 | using namespace cxcursor; |
348 | |
349 | if (clang_isDeclaration(C.kind)) { |
350 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
351 | |
352 | if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(Val: D)) { |
353 | return TD->getInitVal().getSExtValue(); |
354 | } |
355 | } |
356 | |
357 | return LLONG_MIN; |
358 | } |
359 | |
360 | unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) { |
361 | using namespace cxcursor; |
362 | |
363 | if (clang_isDeclaration(C.kind)) { |
364 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
365 | |
366 | if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(Val: D)) { |
367 | return TD->getInitVal().getZExtValue(); |
368 | } |
369 | } |
370 | |
371 | return ULLONG_MAX; |
372 | } |
373 | |
374 | int clang_getFieldDeclBitWidth(CXCursor C) { |
375 | using namespace cxcursor; |
376 | |
377 | if (clang_isDeclaration(C.kind)) { |
378 | const Decl *D = getCursorDecl(Cursor: C); |
379 | |
380 | if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: D)) { |
381 | if (FD->isBitField() && !FD->getBitWidth()->isValueDependent()) |
382 | return FD->getBitWidthValue(Ctx: getCursorContext(Cursor: C)); |
383 | } |
384 | } |
385 | |
386 | return -1; |
387 | } |
388 | |
389 | CXType 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(T: QualType(), TU: GetTU(CT)); |
398 | |
399 | return MakeCXType(T: cxtu::getASTUnit(TU)->getASTContext() |
400 | .getCanonicalType(T), |
401 | TU); |
402 | } |
403 | |
404 | unsigned clang_isConstQualifiedType(CXType CT) { |
405 | QualType T = GetQualType(CT); |
406 | return T.isLocalConstQualified(); |
407 | } |
408 | |
409 | unsigned clang_isVolatileQualifiedType(CXType CT) { |
410 | QualType T = GetQualType(CT); |
411 | return T.isLocalVolatileQualified(); |
412 | } |
413 | |
414 | unsigned clang_isRestrictQualifiedType(CXType CT) { |
415 | QualType T = GetQualType(CT); |
416 | return T.isLocalRestrictQualified(); |
417 | } |
418 | |
419 | unsigned 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 | |
432 | CXString 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 | |
443 | CXType clang_getPointeeType(CXType CT) { |
444 | QualType T = GetQualType(CT); |
445 | const Type *TP = T.getTypePtrOrNull(); |
446 | |
447 | if (!TP) |
448 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
449 | |
450 | try_again: |
451 | switch (TP->getTypeClass()) { |
452 | case Type::Pointer: |
453 | T = cast<PointerType>(Val: TP)->getPointeeType(); |
454 | break; |
455 | case Type::BlockPointer: |
456 | T = cast<BlockPointerType>(Val: TP)->getPointeeType(); |
457 | break; |
458 | case Type::LValueReference: |
459 | case Type::RValueReference: |
460 | T = cast<ReferenceType>(Val: TP)->getPointeeType(); |
461 | break; |
462 | case Type::ObjCObjectPointer: |
463 | T = cast<ObjCObjectPointerType>(Val: TP)->getPointeeType(); |
464 | break; |
465 | case Type::MemberPointer: |
466 | T = cast<MemberPointerType>(Val: TP)->getPointeeType(); |
467 | break; |
468 | case Type::Auto: |
469 | case Type::DeducedTemplateSpecialization: |
470 | TP = cast<DeducedType>(Val: TP)->getDeducedType().getTypePtrOrNull(); |
471 | if (TP) |
472 | goto try_again; |
473 | break; |
474 | default: |
475 | T = QualType(); |
476 | break; |
477 | } |
478 | return MakeCXType(T, TU: GetTU(CT)); |
479 | } |
480 | |
481 | CXType clang_getUnqualifiedType(CXType CT) { |
482 | return MakeCXType(T: GetQualType(CT).getUnqualifiedType(), TU: GetTU(CT)); |
483 | } |
484 | |
485 | CXType clang_getNonReferenceType(CXType CT) { |
486 | return MakeCXType(T: GetQualType(CT).getNonReferenceType(), TU: GetTU(CT)); |
487 | } |
488 | |
489 | CXCursor clang_getTypeDeclaration(CXType CT) { |
490 | if (CT.kind == CXType_Invalid) |
491 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
492 | |
493 | QualType T = GetQualType(CT); |
494 | const Type *TP = T.getTypePtrOrNull(); |
495 | |
496 | if (!TP) |
497 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
498 | |
499 | Decl *D = nullptr; |
500 | |
501 | try_again: |
502 | switch (TP->getTypeClass()) { |
503 | case Type::Typedef: |
504 | D = cast<TypedefType>(Val: TP)->getDecl(); |
505 | break; |
506 | case Type::ObjCObject: |
507 | D = cast<ObjCObjectType>(Val: TP)->getInterface(); |
508 | break; |
509 | case Type::ObjCInterface: |
510 | D = cast<ObjCInterfaceType>(Val: TP)->getDecl(); |
511 | break; |
512 | case Type::Record: |
513 | case Type::Enum: |
514 | D = cast<TagType>(Val: 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>(Val: TP)->getTemplateName() |
521 | .getAsTemplateDecl(); |
522 | break; |
523 | |
524 | case Type::Auto: |
525 | case Type::DeducedTemplateSpecialization: |
526 | TP = cast<DeducedType>(Val: TP)->getDeducedType().getTypePtrOrNull(); |
527 | if (TP) |
528 | goto try_again; |
529 | break; |
530 | |
531 | case Type::InjectedClassName: |
532 | D = cast<InjectedClassNameType>(Val: TP)->getDecl(); |
533 | break; |
534 | |
535 | // FIXME: Template type parameters! |
536 | |
537 | case Type::Elaborated: |
538 | TP = cast<ElaboratedType>(Val: TP)->getNamedType().getTypePtrOrNull(); |
539 | goto try_again; |
540 | |
541 | default: |
542 | break; |
543 | } |
544 | |
545 | if (!D) |
546 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
547 | |
548 | return cxcursor::MakeCXCursor(D, TU: GetTU(CT)); |
549 | } |
550 | |
551 | CXString 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(String: s); |
635 | } |
636 | |
637 | unsigned clang_equalTypes(CXType A, CXType B) { |
638 | return A.data[0] == B.data[0] && A.data[1] == B.data[1]; |
639 | } |
640 | |
641 | unsigned clang_isFunctionTypeVariadic(CXType X) { |
642 | QualType T = GetQualType(CT: 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 | |
655 | CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { |
656 | QualType T = GetQualType(CT: 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 | TCALLINGCONV(M68kRTD); |
682 | TCALLINGCONV(PreserveNone); |
683 | TCALLINGCONV(RISCVVectorCall); |
684 | case CC_SpirFunction: return CXCallingConv_Unexposed; |
685 | case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; |
686 | case CC_OpenCLKernel: return CXCallingConv_Unexposed; |
687 | break; |
688 | } |
689 | #undef TCALLINGCONV |
690 | } |
691 | |
692 | return CXCallingConv_Invalid; |
693 | } |
694 | |
695 | int clang_getNumArgTypes(CXType X) { |
696 | QualType T = GetQualType(CT: X); |
697 | if (T.isNull()) |
698 | return -1; |
699 | |
700 | if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) { |
701 | return FD->getNumParams(); |
702 | } |
703 | |
704 | if (T->getAs<FunctionNoProtoType>()) { |
705 | return 0; |
706 | } |
707 | |
708 | return -1; |
709 | } |
710 | |
711 | CXType clang_getArgType(CXType X, unsigned i) { |
712 | QualType T = GetQualType(CT: X); |
713 | if (T.isNull()) |
714 | return MakeCXType(T: QualType(), TU: GetTU(CT: X)); |
715 | |
716 | if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) { |
717 | unsigned numParams = FD->getNumParams(); |
718 | if (i >= numParams) |
719 | return MakeCXType(T: QualType(), TU: GetTU(CT: X)); |
720 | |
721 | return MakeCXType(T: FD->getParamType(i), TU: GetTU(CT: X)); |
722 | } |
723 | |
724 | return MakeCXType(T: QualType(), TU: GetTU(CT: X)); |
725 | } |
726 | |
727 | CXType clang_getResultType(CXType X) { |
728 | QualType T = GetQualType(CT: X); |
729 | if (T.isNull()) |
730 | return MakeCXType(T: QualType(), TU: GetTU(CT: X)); |
731 | |
732 | if (const FunctionType *FD = T->getAs<FunctionType>()) |
733 | return MakeCXType(T: FD->getReturnType(), TU: GetTU(CT: X)); |
734 | |
735 | return MakeCXType(T: QualType(), TU: GetTU(CT: X)); |
736 | } |
737 | |
738 | CXType clang_getCursorResultType(CXCursor C) { |
739 | if (clang_isDeclaration(C.kind)) { |
740 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
741 | if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Val: D)) |
742 | return MakeCXType(T: MD->getReturnType(), TU: cxcursor::getCursorTU(Cursor: C)); |
743 | |
744 | return clang_getResultType(X: clang_getCursorType(C)); |
745 | } |
746 | |
747 | return MakeCXType(T: QualType(), TU: cxcursor::getCursorTU(Cursor: C)); |
748 | } |
749 | |
750 | // FIXME: We should expose the canThrow(...) result instead of the EST. |
751 | static CXCursor_ExceptionSpecificationKind |
752 | getExternalExceptionSpecificationKind(ExceptionSpecificationType EST) { |
753 | switch (EST) { |
754 | case EST_None: |
755 | return CXCursor_ExceptionSpecificationKind_None; |
756 | case EST_DynamicNone: |
757 | return CXCursor_ExceptionSpecificationKind_DynamicNone; |
758 | case EST_Dynamic: |
759 | return CXCursor_ExceptionSpecificationKind_Dynamic; |
760 | case EST_MSAny: |
761 | return CXCursor_ExceptionSpecificationKind_MSAny; |
762 | case EST_BasicNoexcept: |
763 | return CXCursor_ExceptionSpecificationKind_BasicNoexcept; |
764 | case EST_NoThrow: |
765 | return CXCursor_ExceptionSpecificationKind_NoThrow; |
766 | case EST_NoexceptFalse: |
767 | case EST_NoexceptTrue: |
768 | case EST_DependentNoexcept: |
769 | return CXCursor_ExceptionSpecificationKind_ComputedNoexcept; |
770 | case EST_Unevaluated: |
771 | return CXCursor_ExceptionSpecificationKind_Unevaluated; |
772 | case EST_Uninstantiated: |
773 | return CXCursor_ExceptionSpecificationKind_Uninstantiated; |
774 | case EST_Unparsed: |
775 | return CXCursor_ExceptionSpecificationKind_Unparsed; |
776 | } |
777 | llvm_unreachable("invalid EST value" ); |
778 | } |
779 | |
780 | int clang_getExceptionSpecificationType(CXType X) { |
781 | QualType T = GetQualType(CT: X); |
782 | if (T.isNull()) |
783 | return -1; |
784 | |
785 | if (const auto *FD = T->getAs<FunctionProtoType>()) |
786 | return getExternalExceptionSpecificationKind(EST: FD->getExceptionSpecType()); |
787 | |
788 | return -1; |
789 | } |
790 | |
791 | int clang_getCursorExceptionSpecificationType(CXCursor C) { |
792 | if (clang_isDeclaration(C.kind)) |
793 | return clang_getExceptionSpecificationType(X: clang_getCursorType(C)); |
794 | |
795 | return -1; |
796 | } |
797 | |
798 | unsigned clang_isPODType(CXType X) { |
799 | QualType T = GetQualType(CT: X); |
800 | if (T.isNull()) |
801 | return 0; |
802 | |
803 | CXTranslationUnit TU = GetTU(CT: X); |
804 | |
805 | return T.isPODType(Context: cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0; |
806 | } |
807 | |
808 | CXType clang_getElementType(CXType CT) { |
809 | QualType ET = QualType(); |
810 | QualType T = GetQualType(CT); |
811 | const Type *TP = T.getTypePtrOrNull(); |
812 | |
813 | if (TP) { |
814 | switch (TP->getTypeClass()) { |
815 | case Type::ConstantArray: |
816 | ET = cast<ConstantArrayType> (Val: TP)->getElementType(); |
817 | break; |
818 | case Type::IncompleteArray: |
819 | ET = cast<IncompleteArrayType> (Val: TP)->getElementType(); |
820 | break; |
821 | case Type::VariableArray: |
822 | ET = cast<VariableArrayType> (Val: TP)->getElementType(); |
823 | break; |
824 | case Type::DependentSizedArray: |
825 | ET = cast<DependentSizedArrayType> (Val: TP)->getElementType(); |
826 | break; |
827 | case Type::Vector: |
828 | ET = cast<VectorType> (Val: TP)->getElementType(); |
829 | break; |
830 | case Type::ExtVector: |
831 | ET = cast<ExtVectorType>(Val: TP)->getElementType(); |
832 | break; |
833 | case Type::Complex: |
834 | ET = cast<ComplexType> (Val: TP)->getElementType(); |
835 | break; |
836 | default: |
837 | break; |
838 | } |
839 | } |
840 | return MakeCXType(T: ET, TU: GetTU(CT)); |
841 | } |
842 | |
843 | long long clang_getNumElements(CXType CT) { |
844 | long long result = -1; |
845 | QualType T = GetQualType(CT); |
846 | const Type *TP = T.getTypePtrOrNull(); |
847 | |
848 | if (TP) { |
849 | switch (TP->getTypeClass()) { |
850 | case Type::ConstantArray: |
851 | result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue(); |
852 | break; |
853 | case Type::Vector: |
854 | result = cast<VectorType> (Val: TP)->getNumElements(); |
855 | break; |
856 | case Type::ExtVector: |
857 | result = cast<ExtVectorType>(Val: TP)->getNumElements(); |
858 | break; |
859 | default: |
860 | break; |
861 | } |
862 | } |
863 | return result; |
864 | } |
865 | |
866 | CXType clang_getArrayElementType(CXType CT) { |
867 | QualType ET = QualType(); |
868 | QualType T = GetQualType(CT); |
869 | const Type *TP = T.getTypePtrOrNull(); |
870 | |
871 | if (TP) { |
872 | switch (TP->getTypeClass()) { |
873 | case Type::ConstantArray: |
874 | ET = cast<ConstantArrayType> (Val: TP)->getElementType(); |
875 | break; |
876 | case Type::IncompleteArray: |
877 | ET = cast<IncompleteArrayType> (Val: TP)->getElementType(); |
878 | break; |
879 | case Type::VariableArray: |
880 | ET = cast<VariableArrayType> (Val: TP)->getElementType(); |
881 | break; |
882 | case Type::DependentSizedArray: |
883 | ET = cast<DependentSizedArrayType> (Val: TP)->getElementType(); |
884 | break; |
885 | default: |
886 | break; |
887 | } |
888 | } |
889 | return MakeCXType(T: ET, TU: GetTU(CT)); |
890 | } |
891 | |
892 | long long clang_getArraySize(CXType CT) { |
893 | long long result = -1; |
894 | QualType T = GetQualType(CT); |
895 | const Type *TP = T.getTypePtrOrNull(); |
896 | |
897 | if (TP) { |
898 | switch (TP->getTypeClass()) { |
899 | case Type::ConstantArray: |
900 | result = cast<ConstantArrayType> (Val: TP)->getSize().getSExtValue(); |
901 | break; |
902 | default: |
903 | break; |
904 | } |
905 | } |
906 | return result; |
907 | } |
908 | |
909 | static bool isIncompleteTypeWithAlignment(QualType QT) { |
910 | return QT->isIncompleteArrayType() || !QT->isIncompleteType(); |
911 | } |
912 | |
913 | long long clang_Type_getAlignOf(CXType T) { |
914 | if (T.kind == CXType_Invalid) |
915 | return CXTypeLayoutError_Invalid; |
916 | ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext(); |
917 | QualType QT = GetQualType(CT: T); |
918 | // [expr.alignof] p1: return size_t value for complete object type, reference |
919 | // or array. |
920 | // [expr.alignof] p3: if reference type, return size of referenced type |
921 | if (QT->isReferenceType()) |
922 | QT = QT.getNonReferenceType(); |
923 | if (!isIncompleteTypeWithAlignment(QT)) |
924 | return CXTypeLayoutError_Incomplete; |
925 | if (QT->isDependentType()) |
926 | return CXTypeLayoutError_Dependent; |
927 | if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT)) |
928 | if (Deduced->getDeducedType().isNull()) |
929 | return CXTypeLayoutError_Undeduced; |
930 | // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl |
931 | // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1 |
932 | // if (QT->isVoidType()) return 1; |
933 | return Ctx.getTypeAlignInChars(T: QT).getQuantity(); |
934 | } |
935 | |
936 | CXType clang_Type_getClassType(CXType CT) { |
937 | QualType ET = QualType(); |
938 | QualType T = GetQualType(CT); |
939 | const Type *TP = T.getTypePtrOrNull(); |
940 | |
941 | if (TP && TP->getTypeClass() == Type::MemberPointer) { |
942 | ET = QualType(cast<MemberPointerType> (Val: TP)->getClass(), 0); |
943 | } |
944 | return MakeCXType(T: ET, TU: GetTU(CT)); |
945 | } |
946 | |
947 | long long clang_Type_getSizeOf(CXType T) { |
948 | if (T.kind == CXType_Invalid) |
949 | return CXTypeLayoutError_Invalid; |
950 | ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: T))->getASTContext(); |
951 | QualType QT = GetQualType(CT: T); |
952 | // [expr.sizeof] p2: if reference type, return size of referenced type |
953 | if (QT->isReferenceType()) |
954 | QT = QT.getNonReferenceType(); |
955 | // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete |
956 | // enumeration |
957 | // Note: We get the cxtype, not the cxcursor, so we can't call |
958 | // FieldDecl->isBitField() |
959 | // [expr.sizeof] p3: pointer ok, function not ok. |
960 | // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error |
961 | if (QT->isIncompleteType()) |
962 | return CXTypeLayoutError_Incomplete; |
963 | if (QT->isDependentType()) |
964 | return CXTypeLayoutError_Dependent; |
965 | if (!QT->isConstantSizeType()) |
966 | return CXTypeLayoutError_NotConstantSize; |
967 | if (const auto *Deduced = dyn_cast<DeducedType>(Val&: QT)) |
968 | if (Deduced->getDeducedType().isNull()) |
969 | return CXTypeLayoutError_Undeduced; |
970 | // [gcc extension] lib/AST/ExprConstant.cpp:1372 |
971 | // HandleSizeof : {voidtype,functype} == 1 |
972 | // not handled by ASTContext.cpp:1313 getTypeInfoImpl |
973 | if (QT->isVoidType() || QT->isFunctionType()) |
974 | return 1; |
975 | return Ctx.getTypeSizeInChars(T: QT).getQuantity(); |
976 | } |
977 | |
978 | static bool isTypeIncompleteForLayout(QualType QT) { |
979 | return QT->isIncompleteType() && !QT->isIncompleteArrayType(); |
980 | } |
981 | |
982 | static long long visitRecordForValidation(const RecordDecl *RD) { |
983 | for (const auto *I : RD->fields()){ |
984 | QualType FQT = I->getType(); |
985 | if (isTypeIncompleteForLayout(QT: FQT)) |
986 | return CXTypeLayoutError_Incomplete; |
987 | if (FQT->isDependentType()) |
988 | return CXTypeLayoutError_Dependent; |
989 | // recurse |
990 | if (const RecordType *ChildType = I->getType()->getAs<RecordType>()) { |
991 | if (const RecordDecl *Child = ChildType->getDecl()) { |
992 | long long ret = visitRecordForValidation(RD: Child); |
993 | if (ret < 0) |
994 | return ret; |
995 | } |
996 | } |
997 | // else try next field |
998 | } |
999 | return 0; |
1000 | } |
1001 | |
1002 | static long long validateFieldParentType(CXCursor PC, CXType PT){ |
1003 | if (clang_isInvalid(PC.kind)) |
1004 | return CXTypeLayoutError_Invalid; |
1005 | const RecordDecl *RD = |
1006 | dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC)); |
1007 | // validate parent declaration |
1008 | if (!RD || RD->isInvalidDecl()) |
1009 | return CXTypeLayoutError_Invalid; |
1010 | RD = RD->getDefinition(); |
1011 | if (!RD) |
1012 | return CXTypeLayoutError_Incomplete; |
1013 | if (RD->isInvalidDecl()) |
1014 | return CXTypeLayoutError_Invalid; |
1015 | // validate parent type |
1016 | QualType RT = GetQualType(CT: PT); |
1017 | if (RT->isIncompleteType()) |
1018 | return CXTypeLayoutError_Incomplete; |
1019 | if (RT->isDependentType()) |
1020 | return CXTypeLayoutError_Dependent; |
1021 | // We recurse into all record fields to detect incomplete and dependent types. |
1022 | long long Error = visitRecordForValidation(RD); |
1023 | if (Error < 0) |
1024 | return Error; |
1025 | return 0; |
1026 | } |
1027 | |
1028 | long long clang_Type_getOffsetOf(CXType PT, const char *S) { |
1029 | // check that PT is not incomplete/dependent |
1030 | CXCursor PC = clang_getTypeDeclaration(CT: PT); |
1031 | long long Error = validateFieldParentType(PC,PT); |
1032 | if (Error < 0) |
1033 | return Error; |
1034 | if (!S) |
1035 | return CXTypeLayoutError_InvalidFieldName; |
1036 | // lookup field |
1037 | ASTContext &Ctx = cxtu::getASTUnit(TU: GetTU(CT: PT))->getASTContext(); |
1038 | IdentifierInfo *II = &Ctx.Idents.get(Name: S); |
1039 | DeclarationName FieldName(II); |
1040 | const RecordDecl *RD = |
1041 | dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC)); |
1042 | // verified in validateFieldParentType |
1043 | RD = RD->getDefinition(); |
1044 | RecordDecl::lookup_result Res = RD->lookup(FieldName); |
1045 | // If a field of the parent record is incomplete, lookup will fail. |
1046 | // and we would return InvalidFieldName instead of Incomplete. |
1047 | // But this erroneous results does protects again a hidden assertion failure |
1048 | // in the RecordLayoutBuilder |
1049 | if (!Res.isSingleResult()) |
1050 | return CXTypeLayoutError_InvalidFieldName; |
1051 | if (const FieldDecl *FD = dyn_cast<FieldDecl>(Val: Res.front())) |
1052 | return Ctx.getFieldOffset(FD); |
1053 | if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Val: Res.front())) |
1054 | return Ctx.getFieldOffset(IFD); |
1055 | // we don't want any other Decl Type. |
1056 | return CXTypeLayoutError_InvalidFieldName; |
1057 | } |
1058 | |
1059 | CXType clang_Type_getModifiedType(CXType CT) { |
1060 | QualType T = GetQualType(CT); |
1061 | if (T.isNull()) |
1062 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1063 | |
1064 | if (auto *ATT = T->getAs<AttributedType>()) |
1065 | return MakeCXType(T: ATT->getModifiedType(), TU: GetTU(CT)); |
1066 | |
1067 | if (auto *ATT = T->getAs<BTFTagAttributedType>()) |
1068 | return MakeCXType(T: ATT->getWrappedType(), TU: GetTU(CT)); |
1069 | |
1070 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1071 | } |
1072 | |
1073 | long long clang_Cursor_getOffsetOfField(CXCursor C) { |
1074 | if (clang_isDeclaration(C.kind)) { |
1075 | // we need to validate the parent type |
1076 | CXCursor PC = clang_getCursorSemanticParent(cursor: C); |
1077 | CXType PT = clang_getCursorType(C: PC); |
1078 | long long Error = validateFieldParentType(PC,PT); |
1079 | if (Error < 0) |
1080 | return Error; |
1081 | // proceed with the offset calculation |
1082 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
1083 | ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C); |
1084 | if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: D)) |
1085 | return Ctx.getFieldOffset(FD); |
1086 | if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(Val: D)) |
1087 | return Ctx.getFieldOffset(IFD); |
1088 | } |
1089 | return -1; |
1090 | } |
1091 | |
1092 | enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) { |
1093 | QualType QT = GetQualType(CT: T); |
1094 | if (QT.isNull()) |
1095 | return CXRefQualifier_None; |
1096 | const FunctionProtoType *FD = QT->getAs<FunctionProtoType>(); |
1097 | if (!FD) |
1098 | return CXRefQualifier_None; |
1099 | switch (FD->getRefQualifier()) { |
1100 | case RQ_None: |
1101 | return CXRefQualifier_None; |
1102 | case RQ_LValue: |
1103 | return CXRefQualifier_LValue; |
1104 | case RQ_RValue: |
1105 | return CXRefQualifier_RValue; |
1106 | } |
1107 | return CXRefQualifier_None; |
1108 | } |
1109 | |
1110 | unsigned clang_Cursor_isBitField(CXCursor C) { |
1111 | if (!clang_isDeclaration(C.kind)) |
1112 | return 0; |
1113 | const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: cxcursor::getCursorDecl(Cursor: C)); |
1114 | if (!FD) |
1115 | return 0; |
1116 | return FD->isBitField(); |
1117 | } |
1118 | |
1119 | CXString clang_getDeclObjCTypeEncoding(CXCursor C) { |
1120 | if (!clang_isDeclaration(C.kind)) |
1121 | return cxstring::createEmpty(); |
1122 | |
1123 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
1124 | ASTContext &Ctx = cxcursor::getCursorContext(Cursor: C); |
1125 | std::string encoding; |
1126 | |
1127 | if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) { |
1128 | encoding = Ctx.getObjCEncodingForMethodDecl(Decl: OMD); |
1129 | } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(Val: D)) |
1130 | encoding = Ctx.getObjCEncodingForPropertyDecl(PD: OPD, Container: nullptr); |
1131 | else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) |
1132 | encoding = Ctx.getObjCEncodingForFunctionDecl(Decl: FD); |
1133 | else { |
1134 | QualType Ty; |
1135 | if (const TypeDecl *TD = dyn_cast<TypeDecl>(Val: D)) |
1136 | Ty = Ctx.getTypeDeclType(Decl: TD); |
1137 | if (const ValueDecl *VD = dyn_cast<ValueDecl>(Val: D)) |
1138 | Ty = VD->getType(); |
1139 | else return cxstring::createRef(String: "?" ); |
1140 | Ctx.getObjCEncodingForType(T: Ty, S&: encoding); |
1141 | } |
1142 | |
1143 | return cxstring::createDup(String: encoding); |
1144 | } |
1145 | |
1146 | static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> TA) { |
1147 | unsigned size = TA.size(); |
1148 | for (const auto &Arg : TA) |
1149 | if (Arg.getKind() == TemplateArgument::Pack) |
1150 | size += Arg.pack_size() - 1; |
1151 | return size; |
1152 | } |
1153 | |
1154 | int clang_Type_getNumTemplateArguments(CXType CT) { |
1155 | QualType T = GetQualType(CT); |
1156 | if (T.isNull()) |
1157 | return -1; |
1158 | |
1159 | auto TA = GetTemplateArguments(Type: T); |
1160 | if (!TA) |
1161 | return -1; |
1162 | |
1163 | return GetTemplateArgumentArraySize(TA: *TA); |
1164 | } |
1165 | |
1166 | CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) { |
1167 | QualType T = GetQualType(CT); |
1168 | if (T.isNull()) |
1169 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1170 | |
1171 | auto TA = GetTemplateArguments(Type: T); |
1172 | if (!TA) |
1173 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1174 | |
1175 | std::optional<QualType> QT = FindTemplateArgumentTypeAt(TA: *TA, index); |
1176 | return MakeCXType(T: QT.value_or(u: QualType()), TU: GetTU(CT)); |
1177 | } |
1178 | |
1179 | CXType clang_Type_getObjCObjectBaseType(CXType CT) { |
1180 | QualType T = GetQualType(CT); |
1181 | if (T.isNull()) |
1182 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1183 | |
1184 | const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T); |
1185 | if (!OT) |
1186 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1187 | |
1188 | return MakeCXType(T: OT->getBaseType(), TU: GetTU(CT)); |
1189 | } |
1190 | |
1191 | unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) { |
1192 | QualType T = GetQualType(CT); |
1193 | if (T.isNull()) |
1194 | return 0; |
1195 | |
1196 | const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T); |
1197 | if (!OT) |
1198 | return 0; |
1199 | |
1200 | return OT->getNumProtocols(); |
1201 | } |
1202 | |
1203 | CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) { |
1204 | QualType T = GetQualType(CT); |
1205 | if (T.isNull()) |
1206 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
1207 | |
1208 | const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T); |
1209 | if (!OT) |
1210 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
1211 | |
1212 | const ObjCProtocolDecl *PD = OT->getProtocol(i); |
1213 | if (!PD) |
1214 | return cxcursor::MakeCXCursorInvalid(K: CXCursor_NoDeclFound); |
1215 | |
1216 | return cxcursor::MakeCXCursor(PD, GetTU(CT)); |
1217 | } |
1218 | |
1219 | unsigned clang_Type_getNumObjCTypeArgs(CXType CT) { |
1220 | QualType T = GetQualType(CT); |
1221 | if (T.isNull()) |
1222 | return 0; |
1223 | |
1224 | const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T); |
1225 | if (!OT) |
1226 | return 0; |
1227 | |
1228 | return OT->getTypeArgs().size(); |
1229 | } |
1230 | |
1231 | CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) { |
1232 | QualType T = GetQualType(CT); |
1233 | if (T.isNull()) |
1234 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1235 | |
1236 | const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(Val&: T); |
1237 | if (!OT) |
1238 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1239 | |
1240 | const ArrayRef<QualType> TA = OT->getTypeArgs(); |
1241 | if ((size_t)i >= TA.size()) |
1242 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1243 | |
1244 | return MakeCXType(T: TA[i], TU: GetTU(CT)); |
1245 | } |
1246 | |
1247 | unsigned clang_Type_visitFields(CXType PT, |
1248 | CXFieldVisitor visitor, |
1249 | CXClientData client_data){ |
1250 | CXCursor PC = clang_getTypeDeclaration(CT: PT); |
1251 | if (clang_isInvalid(PC.kind)) |
1252 | return false; |
1253 | const RecordDecl *RD = |
1254 | dyn_cast_or_null<RecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC)); |
1255 | if (!RD || RD->isInvalidDecl()) |
1256 | return false; |
1257 | RD = RD->getDefinition(); |
1258 | if (!RD || RD->isInvalidDecl()) |
1259 | return false; |
1260 | |
1261 | for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); |
1262 | I != E; ++I){ |
1263 | const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(Val: (*I)); |
1264 | // Callback to the client. |
1265 | switch (visitor(cxcursor::MakeCXCursor(FD, GetTU(CT: PT)), client_data)){ |
1266 | case CXVisit_Break: |
1267 | return true; |
1268 | case CXVisit_Continue: |
1269 | break; |
1270 | } |
1271 | } |
1272 | return true; |
1273 | } |
1274 | |
1275 | unsigned clang_Cursor_isAnonymous(CXCursor C){ |
1276 | if (!clang_isDeclaration(C.kind)) |
1277 | return 0; |
1278 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
1279 | if (const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D)) { |
1280 | return ND->isAnonymousNamespace(); |
1281 | } else if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(Val: D)) { |
1282 | return TD->getTypedefNameForAnonDecl() == nullptr && |
1283 | TD->getIdentifier() == nullptr; |
1284 | } |
1285 | |
1286 | return 0; |
1287 | } |
1288 | |
1289 | unsigned clang_Cursor_isAnonymousRecordDecl(CXCursor C){ |
1290 | if (!clang_isDeclaration(C.kind)) |
1291 | return 0; |
1292 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
1293 | if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(Val: D)) |
1294 | return FD->isAnonymousStructOrUnion(); |
1295 | return 0; |
1296 | } |
1297 | |
1298 | unsigned clang_Cursor_isInlineNamespace(CXCursor C) { |
1299 | if (!clang_isDeclaration(C.kind)) |
1300 | return 0; |
1301 | const Decl *D = cxcursor::getCursorDecl(Cursor: C); |
1302 | const NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(Val: D); |
1303 | return ND ? ND->isInline() : 0; |
1304 | } |
1305 | |
1306 | CXType clang_Type_getNamedType(CXType CT){ |
1307 | QualType T = GetQualType(CT); |
1308 | const Type *TP = T.getTypePtrOrNull(); |
1309 | |
1310 | if (TP && TP->getTypeClass() == Type::Elaborated) |
1311 | return MakeCXType(T: cast<ElaboratedType>(Val: TP)->getNamedType(), TU: GetTU(CT)); |
1312 | |
1313 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1314 | } |
1315 | |
1316 | unsigned clang_Type_isTransparentTagTypedef(CXType TT){ |
1317 | QualType T = GetQualType(CT: TT); |
1318 | if (auto *TT = dyn_cast_or_null<TypedefType>(Val: T.getTypePtrOrNull())) { |
1319 | if (auto *D = TT->getDecl()) |
1320 | return D->isTransparentTag(); |
1321 | } |
1322 | return false; |
1323 | } |
1324 | |
1325 | enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) { |
1326 | QualType T = GetQualType(CT); |
1327 | if (T.isNull()) |
1328 | return CXTypeNullability_Invalid; |
1329 | |
1330 | if (auto nullability = T->getNullability()) { |
1331 | switch (*nullability) { |
1332 | case NullabilityKind::NonNull: |
1333 | return CXTypeNullability_NonNull; |
1334 | case NullabilityKind::Nullable: |
1335 | return CXTypeNullability_Nullable; |
1336 | case NullabilityKind::NullableResult: |
1337 | return CXTypeNullability_NullableResult; |
1338 | case NullabilityKind::Unspecified: |
1339 | return CXTypeNullability_Unspecified; |
1340 | } |
1341 | } |
1342 | return CXTypeNullability_Invalid; |
1343 | } |
1344 | |
1345 | CXType clang_Type_getValueType(CXType CT) { |
1346 | QualType T = GetQualType(CT); |
1347 | |
1348 | if (T.isNull() || !T->isAtomicType()) |
1349 | return MakeCXType(T: QualType(), TU: GetTU(CT)); |
1350 | |
1351 | const auto *AT = T->castAs<AtomicType>(); |
1352 | return MakeCXType(T: AT->getValueType(), TU: GetTU(CT)); |
1353 | } |
1354 | |