clang 20.0.0git
SemaAPINotes.cpp
Go to the documentation of this file.
1//===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//
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 mapping from API notes to declaration attributes.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CheckExprLifetime.h"
14#include "TypeLocBuilder.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DeclObjC.h"
19#include "clang/AST/TypeLoc.h"
21#include "clang/Lex/Lexer.h"
22#include "clang/Sema/SemaObjC.h"
24#include <stack>
25
26using namespace clang;
27
28namespace {
29enum class IsActive_t : bool { Inactive, Active };
30enum class IsSubstitution_t : bool { Original, Replacement };
31
32struct VersionedInfoMetadata {
33 /// An empty version refers to unversioned metadata.
34 VersionTuple Version;
35 unsigned IsActive : 1;
36 unsigned IsReplacement : 1;
37
38 VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
39 IsSubstitution_t Replacement)
40 : Version(Version), IsActive(Active == IsActive_t::Active),
41 IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
42};
43} // end anonymous namespace
44
45/// Determine whether this is a multi-level pointer type.
47 QualType Pointee = Type->getPointeeType();
48 if (Pointee.isNull())
49 return false;
50
51 return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
52 Pointee->isMemberPointerType();
53}
54
55/// Apply nullability to the given declaration.
56static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability,
57 VersionedInfoMetadata Metadata) {
58 if (!Metadata.IsActive)
59 return;
60
61 auto GetModified =
62 [&](Decl *D, QualType QT,
63 NullabilityKind Nullability) -> std::optional<QualType> {
64 QualType Original = QT;
66 isa<ParmVarDecl>(D),
67 /*OverrideExisting=*/true);
68 return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
69 : std::nullopt;
70 };
71
72 if (auto Function = dyn_cast<FunctionDecl>(D)) {
73 if (auto Modified =
74 GetModified(D, Function->getReturnType(), Nullability)) {
75 const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
76 if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
78 *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
79 else
80 Function->setType(
81 S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
82 }
83 } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
84 if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
85 Method->setReturnType(*Modified);
86
87 // Make it a context-sensitive keyword if we can.
88 if (!isIndirectPointerType(*Modified))
89 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
90 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
91 }
92 } else if (auto Value = dyn_cast<ValueDecl>(D)) {
93 if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
94 Value->setType(*Modified);
95
96 // Make it a context-sensitive keyword if we can.
97 if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
98 if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
99 Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
100 Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
101 }
102 }
103 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
104 if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
105 Property->setType(*Modified, Property->getTypeSourceInfo());
106
107 // Make it a property attribute if we can.
108 if (!isIndirectPointerType(*Modified))
109 Property->setPropertyAttributes(
111 }
112 }
113}
114
115/// Copy a string into ASTContext-allocated memory.
116static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {
117 void *mem = Ctx.Allocate(String.size(), alignof(char *));
118 memcpy(mem, String.data(), String.size());
119 return StringRef(static_cast<char *>(mem), String.size());
120}
121
126 /*Spelling*/ 0, /*IsAlignas*/ false,
127 /*IsRegularKeywordAttribute*/ false});
128}
129
130namespace {
131template <typename A> struct AttrKindFor {};
132
133#define ATTR(X) \
134 template <> struct AttrKindFor<X##Attr> { \
135 static const attr::Kind value = attr::X; \
136 };
137#include "clang/Basic/AttrList.inc"
138
139/// Handle an attribute introduced by API notes.
140///
141/// \param IsAddition Whether we should add a new attribute
142/// (otherwise, we might remove an existing attribute).
143/// \param CreateAttr Create the new attribute to be added.
144template <typename A>
145void handleAPINotedAttribute(
146 Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,
147 llvm::function_ref<A *()> CreateAttr,
148 llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {
149 if (Metadata.IsActive) {
150 auto Existing = GetExistingAttr(D);
151 if (Existing != D->attr_end()) {
152 // Remove the existing attribute, and treat it as a superseded
153 // non-versioned attribute.
154 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
155 S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);
156
157 D->getAttrs().erase(Existing);
158 D->addAttr(Versioned);
159 }
160
161 // If we're supposed to add a new attribute, do so.
162 if (IsAddition) {
163 if (auto Attr = CreateAttr())
164 D->addAttr(Attr);
165 }
166
167 return;
168 }
169 if (IsAddition) {
170 if (auto Attr = CreateAttr()) {
171 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
172 S.Context, Metadata.Version, Attr,
173 /*IsReplacedByActive*/ Metadata.IsReplacement);
174 D->addAttr(Versioned);
175 }
176 } else {
177 // FIXME: This isn't preserving enough information for things like
178 // availability, where we're trying to remove a /specific/ kind of
179 // attribute.
180 auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
181 S.Context, Metadata.Version, AttrKindFor<A>::value,
182 /*IsReplacedByActive*/ Metadata.IsReplacement);
183 D->addAttr(Versioned);
184 }
185}
186
187template <typename A>
188void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,
189 VersionedInfoMetadata Metadata,
190 llvm::function_ref<A *()> CreateAttr) {
191 handleAPINotedAttribute<A>(
192 S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {
193 return llvm::find_if(D->attrs(),
194 [](const Attr *Next) { return isa<A>(Next); });
195 });
196}
197} // namespace
198
199template <typename A>
201 bool ShouldAddAttribute,
202 VersionedInfoMetadata Metadata) {
203 // The template argument has a default to make the "removal" case more
204 // concise; it doesn't matter /which/ attribute is being removed.
205 handleAPINotedAttribute<A>(
206 S, D, ShouldAddAttribute, Metadata,
207 [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },
208 [](const Decl *D) -> Decl::attr_iterator {
209 return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {
210 return isa<CFReturnsRetainedAttr>(Next) ||
211 isa<CFReturnsNotRetainedAttr>(Next) ||
212 isa<NSReturnsRetainedAttr>(Next) ||
213 isa<NSReturnsNotRetainedAttr>(Next) ||
214 isa<CFAuditedTransferAttr>(Next);
215 });
216 });
217}
218
220 Sema &S, Decl *D, VersionedInfoMetadata Metadata,
221 std::optional<api_notes::RetainCountConventionKind> Convention) {
222 if (!Convention)
223 return;
224 switch (*Convention) {
225 case api_notes::RetainCountConventionKind::None:
226 if (isa<FunctionDecl>(D)) {
227 handleAPINotedRetainCountAttribute<CFUnknownTransferAttr>(
228 S, D, /*shouldAddAttribute*/ true, Metadata);
229 } else {
230 handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
231 S, D, /*shouldAddAttribute*/ false, Metadata);
232 }
233 break;
234 case api_notes::RetainCountConventionKind::CFReturnsRetained:
235 handleAPINotedRetainCountAttribute<CFReturnsRetainedAttr>(
236 S, D, /*shouldAddAttribute*/ true, Metadata);
237 break;
238 case api_notes::RetainCountConventionKind::CFReturnsNotRetained:
239 handleAPINotedRetainCountAttribute<CFReturnsNotRetainedAttr>(
240 S, D, /*shouldAddAttribute*/ true, Metadata);
241 break;
242 case api_notes::RetainCountConventionKind::NSReturnsRetained:
243 handleAPINotedRetainCountAttribute<NSReturnsRetainedAttr>(
244 S, D, /*shouldAddAttribute*/ true, Metadata);
245 break;
246 case api_notes::RetainCountConventionKind::NSReturnsNotRetained:
247 handleAPINotedRetainCountAttribute<NSReturnsNotRetainedAttr>(
248 S, D, /*shouldAddAttribute*/ true, Metadata);
249 break;
250 }
251}
252
253static void ProcessAPINotes(Sema &S, Decl *D,
254 const api_notes::CommonEntityInfo &Info,
255 VersionedInfoMetadata Metadata) {
256 // Availability
257 if (Info.Unavailable) {
258 handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
259 return new (S.Context)
260 UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
262 });
263 }
264
265 if (Info.UnavailableInSwift) {
266 handleAPINotedAttribute<AvailabilityAttr>(
267 S, D, true, Metadata,
268 [&] {
269 return new (S.Context) AvailabilityAttr(
271 &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
272 VersionTuple(),
273 /*Unavailable=*/true,
275 /*Strict=*/false,
276 /*Replacement=*/StringRef(),
277 /*Priority=*/Sema::AP_Explicit,
278 /*Environment=*/nullptr);
279 },
280 [](const Decl *D) {
281 return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
282 if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
283 if (const auto *II = AA->getPlatform())
284 return II->isStr("swift");
285 return false;
286 });
287 });
288 }
289
290 // swift_private
291 if (auto SwiftPrivate = Info.isSwiftPrivate()) {
292 handleAPINotedAttribute<SwiftPrivateAttr>(
293 S, D, *SwiftPrivate, Metadata, [&] {
294 return new (S.Context)
295 SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
296 });
297 }
298
299 // swift_name
300 if (!Info.SwiftName.empty()) {
301 handleAPINotedAttribute<SwiftNameAttr>(
302 S, D, true, Metadata, [&]() -> SwiftNameAttr * {
303 AttributeFactory AF{};
304 AttributePool AP{AF};
305 auto &C = S.getASTContext();
306 ParsedAttr *SNA =
307 AP.create(&C.Idents.get("swift_name"), SourceRange(), nullptr,
308 SourceLocation(), nullptr, nullptr, nullptr,
309 ParsedAttr::Form::GNU());
310
311 if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
312 /*IsAsync=*/false))
313 return nullptr;
314
315 return new (S.Context)
316 SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
318 });
319 }
320}
321
322static void ProcessAPINotes(Sema &S, Decl *D,
323 const api_notes::CommonTypeInfo &Info,
324 VersionedInfoMetadata Metadata) {
325 // swift_bridge
326 if (auto SwiftBridge = Info.getSwiftBridge()) {
327 handleAPINotedAttribute<SwiftBridgeAttr>(
328 S, D, !SwiftBridge->empty(), Metadata, [&] {
329 return new (S.Context)
330 SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
331 ASTAllocateString(S.Context, *SwiftBridge));
332 });
333 }
334
335 // ns_error_domain
336 if (auto NSErrorDomain = Info.getNSErrorDomain()) {
337 handleAPINotedAttribute<NSErrorDomainAttr>(
338 S, D, !NSErrorDomain->empty(), Metadata, [&] {
339 return new (S.Context)
340 NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
341 &S.Context.Idents.get(*NSErrorDomain));
342 });
343 }
344
345 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
346 Metadata);
347}
348
349/// Check that the replacement type provided by API notes is reasonable.
350///
351/// This is a very weak form of ABI check.
353 QualType OrigType,
354 QualType ReplacementType) {
355 if (S.Context.getTypeSize(OrigType) !=
356 S.Context.getTypeSize(ReplacementType)) {
357 S.Diag(Loc, diag::err_incompatible_replacement_type)
358 << ReplacementType << OrigType;
359 return true;
360 }
361
362 return false;
363}
364
365/// Process API notes for a variable or property.
366static void ProcessAPINotes(Sema &S, Decl *D,
367 const api_notes::VariableInfo &Info,
368 VersionedInfoMetadata Metadata) {
369 // Type override.
370 if (Metadata.IsActive && !Info.getType().empty() &&
373 Info.getType(), "<API Notes>", D->getLocation());
374 if (ParsedType.isUsable()) {
376 auto TypeInfo =
378
379 if (auto Var = dyn_cast<VarDecl>(D)) {
380 // Make adjustments to parameter types.
381 if (isa<ParmVarDecl>(Var)) {
385 }
386
387 if (!checkAPINotesReplacementType(S, Var->getLocation(), Var->getType(),
388 Type)) {
389 Var->setType(Type);
390 Var->setTypeSourceInfo(TypeInfo);
391 }
392 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
393 if (!checkAPINotesReplacementType(S, Property->getLocation(),
394 Property->getType(), Type))
395 Property->setType(Type, TypeInfo);
396
397 } else
398 llvm_unreachable("API notes allowed a type on an unknown declaration");
399 }
400 }
401
402 // Nullability.
403 if (auto Nullability = Info.getNullability())
404 applyNullability(S, D, *Nullability, Metadata);
405
406 // Handle common entity information.
407 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
408 Metadata);
409}
410
411/// Process API notes for a parameter.
413 const api_notes::ParamInfo &Info,
414 VersionedInfoMetadata Metadata) {
415 // noescape
416 if (auto NoEscape = Info.isNoEscape())
417 handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
418 return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
419 });
420
421 if (auto Lifetimebound = Info.isLifetimebound())
422 handleAPINotedAttribute<LifetimeBoundAttr>(
423 S, D, *Lifetimebound, Metadata, [&] {
424 return new (S.Context)
425 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
426 });
427
428 // Retain count convention
431
432 // Handle common entity information.
433 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
434 Metadata);
435}
436
437/// Process API notes for a global variable.
438static void ProcessAPINotes(Sema &S, VarDecl *D,
440 VersionedInfoMetadata metadata) {
441 // Handle common entity information.
442 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
443 metadata);
444}
445
446/// Process API notes for a C field.
448 const api_notes::FieldInfo &Info,
449 VersionedInfoMetadata metadata) {
450 // Handle common entity information.
451 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
452 metadata);
453}
454
455/// Process API notes for an Objective-C property.
457 const api_notes::ObjCPropertyInfo &Info,
458 VersionedInfoMetadata Metadata) {
459 // Handle common entity information.
460 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
461 Metadata);
462
463 if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
464 handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
465 S, D, *AsAccessors, Metadata, [&] {
466 return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
468 });
469 }
470}
471
472namespace {
473typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
474}
475
476/// Process API notes for a function or method.
477static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
478 const api_notes::FunctionInfo &Info,
479 VersionedInfoMetadata Metadata) {
480 // Find the declaration itself.
481 FunctionDecl *FD = AnyFunc.dyn_cast<FunctionDecl *>();
482 Decl *D = FD;
483 ObjCMethodDecl *MD = nullptr;
484 if (!D) {
485 MD = cast<ObjCMethodDecl *>(AnyFunc);
486 D = MD;
487 }
488
489 assert((FD || MD) && "Expecting Function or ObjCMethod");
490
491 // Nullability of return type.
492 if (Info.NullabilityAudited)
493 applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
494
495 // Parameters.
496 unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
497
498 bool AnyTypeChanged = false;
499 for (unsigned I = 0; I != NumParams; ++I) {
500 ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
501 QualType ParamTypeBefore = Param->getType();
502
503 if (I < Info.Params.size())
504 ProcessAPINotes(S, Param, Info.Params[I], Metadata);
505
506 // Nullability.
507 if (Info.NullabilityAudited)
508 applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
509
510 if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
511 AnyTypeChanged = true;
512 }
513
514 // returns_(un)retained
515 if (!Info.SwiftReturnOwnership.empty())
516 D->addAttr(SwiftAttrAttr::Create(S.Context,
517 "returns_" + Info.SwiftReturnOwnership));
518
519 // Result type override.
520 QualType OverriddenResultType;
521 if (Metadata.IsActive && !Info.ResultType.empty() &&
524 Info.ResultType, "<API Notes>", D->getLocation());
525 if (ParsedType.isUsable()) {
527
528 if (MD) {
530 MD->getReturnType(), ResultType)) {
531 auto ResultTypeInfo =
533 MD->setReturnType(ResultType);
534 MD->setReturnTypeSourceInfo(ResultTypeInfo);
535 }
537 S, FD->getLocation(), FD->getReturnType(), ResultType)) {
538 OverriddenResultType = ResultType;
539 AnyTypeChanged = true;
540 }
541 }
542 }
543
544 // If the result type or any of the parameter types changed for a function
545 // declaration, we have to rebuild the type.
546 if (FD && AnyTypeChanged) {
547 if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
548 if (OverriddenResultType.isNull())
549 OverriddenResultType = fnProtoType->getReturnType();
550
551 SmallVector<QualType, 4> ParamTypes;
552 for (auto Param : FD->parameters())
553 ParamTypes.push_back(Param->getType());
554
555 FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
556 fnProtoType->getExtProtoInfo()));
557 } else if (!OverriddenResultType.isNull()) {
558 const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
560 OverriddenResultType, FnNoProtoType->getExtInfo()));
561 }
562 }
563
564 // Retain count convention
567
568 // Handle common entity information.
569 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
570 Metadata);
571}
572
573/// Process API notes for a C++ method.
574static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
575 const api_notes::CXXMethodInfo &Info,
576 VersionedInfoMetadata Metadata) {
577 if (Info.This && Info.This->isLifetimebound() &&
579 auto MethodType = Method->getType();
580 auto *attr = ::new (S.Context)
581 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
583 S.Context.getAttributedType(attr, MethodType, MethodType);
584 TypeLocBuilder TLB;
585 TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
587 TyLoc.setAttr(attr);
588 Method->setType(AttributedType);
590 }
591
592 ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
593}
594
595/// Process API notes for a global function.
598 VersionedInfoMetadata Metadata) {
599 // Handle common function information.
600 ProcessAPINotes(S, FunctionOrMethod(D),
601 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
602}
603
604/// Process API notes for an enumerator.
606 const api_notes::EnumConstantInfo &Info,
607 VersionedInfoMetadata Metadata) {
608 // Handle common information.
609 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
610 Metadata);
611}
612
613/// Process API notes for an Objective-C method.
615 const api_notes::ObjCMethodInfo &Info,
616 VersionedInfoMetadata Metadata) {
617 // Designated initializers.
618 if (Info.DesignatedInit) {
619 handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
620 S, D, true, Metadata, [&] {
621 if (ObjCInterfaceDecl *IFace = D->getClassInterface())
622 IFace->setHasDesignatedInitializers();
623
624 return new (S.Context) ObjCDesignatedInitializerAttr(
626 });
627 }
628
629 // Handle common function information.
630 ProcessAPINotes(S, FunctionOrMethod(D),
631 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
632}
633
634/// Process API notes for a tag.
635static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
636 VersionedInfoMetadata Metadata) {
637 if (auto ImportAs = Info.SwiftImportAs)
638 D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));
639
640 if (auto RetainOp = Info.SwiftRetainOp)
641 D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));
642
643 if (auto ReleaseOp = Info.SwiftReleaseOp)
644 D->addAttr(
645 SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
646
647 if (auto ConformsTo = Info.SwiftConformance)
648 D->addAttr(
649 SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
650
651 if (auto Copyable = Info.isSwiftCopyable()) {
652 if (!*Copyable)
653 D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
654 }
655
656 if (auto Escapable = Info.isSwiftEscapable()) {
657 D->addAttr(SwiftAttrAttr::Create(S.Context,
658 *Escapable ? "Escapable" : "~Escapable"));
659 }
660
661 if (auto Extensibility = Info.EnumExtensibility) {
663 bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
664 handleAPINotedAttribute<EnumExtensibilityAttr>(
665 S, D, ShouldAddAttribute, Metadata, [&] {
666 EnumExtensibilityAttr::Kind kind;
667 switch (*Extensibility) {
668 case EnumExtensibilityKind::None:
669 llvm_unreachable("remove only");
670 case EnumExtensibilityKind::Open:
671 kind = EnumExtensibilityAttr::Open;
672 break;
673 case EnumExtensibilityKind::Closed:
674 kind = EnumExtensibilityAttr::Closed;
675 break;
676 }
677 return new (S.Context)
678 EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
679 });
680 }
681
682 if (auto FlagEnum = Info.isFlagEnum()) {
683 handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
684 return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
685 });
686 }
687
688 // Handle common type information.
689 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
690 Metadata);
691}
692
693/// Process API notes for a typedef.
695 const api_notes::TypedefInfo &Info,
696 VersionedInfoMetadata Metadata) {
697 // swift_wrapper
698 using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
699
700 if (auto SwiftWrapper = Info.SwiftWrapper) {
701 handleAPINotedAttribute<SwiftNewTypeAttr>(
702 S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
703 SwiftNewTypeAttr::NewtypeKind Kind;
704 switch (*SwiftWrapper) {
705 case SwiftWrapperKind::None:
706 llvm_unreachable("Shouldn't build an attribute");
707
708 case SwiftWrapperKind::Struct:
709 Kind = SwiftNewTypeAttr::NK_Struct;
710 break;
711
712 case SwiftWrapperKind::Enum:
713 Kind = SwiftNewTypeAttr::NK_Enum;
714 break;
715 }
716 AttributeCommonInfo SyntaxInfo{
717 SourceRange(),
718 AttributeCommonInfo::AT_SwiftNewType,
719 {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
720 /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
721 return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
722 });
723 }
724
725 // Handle common type information.
726 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
727 Metadata);
728}
729
730/// Process API notes for an Objective-C class or protocol.
732 const api_notes::ContextInfo &Info,
733 VersionedInfoMetadata Metadata) {
734 // Handle common type information.
735 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
736 Metadata);
737}
738
739/// Process API notes for an Objective-C class.
741 const api_notes::ContextInfo &Info,
742 VersionedInfoMetadata Metadata) {
743 if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
744 handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
745 S, D, *AsNonGeneric, Metadata, [&] {
746 return new (S.Context)
747 SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
748 });
749 }
750
751 if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
752 handleAPINotedAttribute<SwiftObjCMembersAttr>(
753 S, D, *ObjcMembers, Metadata, [&] {
754 return new (S.Context)
755 SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
756 });
757 }
758
759 // Handle information common to Objective-C classes and protocols.
760 ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
761 Metadata);
762}
763
764/// If we're applying API notes with an active, non-default version, and the
765/// versioned API notes have a SwiftName but the declaration normally wouldn't
766/// have one, add a removal attribute to make it clear that the new SwiftName
767/// attribute only applies to the active version of \p D, not to all versions.
768///
769/// This must be run \em before processing API notes for \p D, because otherwise
770/// any existing SwiftName attribute will have been packaged up in a
771/// SwiftVersionedAdditionAttr.
772template <typename SpecificInfo>
774 Sema &S, Decl *D,
776 if (D->hasAttr<SwiftNameAttr>())
777 return;
778 if (!Info.getSelected())
779 return;
780
781 // Is the active slice versioned, and does it set a Swift name?
782 VersionTuple SelectedVersion;
783 SpecificInfo SelectedInfoSlice;
784 std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
785 if (SelectedVersion.empty())
786 return;
787 if (SelectedInfoSlice.SwiftName.empty())
788 return;
789
790 // Does the unversioned slice /not/ set a Swift name?
791 for (const auto &VersionAndInfoSlice : Info) {
792 if (!VersionAndInfoSlice.first.empty())
793 continue;
794 if (!VersionAndInfoSlice.second.SwiftName.empty())
795 return;
796 }
797
798 // Then explicitly call that out with a removal attribute.
799 VersionedInfoMetadata DummyFutureMetadata(
800 SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
801 handleAPINotedAttribute<SwiftNameAttr>(
802 S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
803 llvm_unreachable("should not try to add an attribute here");
804 });
805}
806
807/// Processes all versions of versioned API notes.
808///
809/// Just dispatches to the various ProcessAPINotes functions in this file.
810template <typename SpecificDecl, typename SpecificInfo>
812 Sema &S, SpecificDecl *D,
814
816
817 unsigned Selected = Info.getSelected().value_or(Info.size());
818
819 VersionTuple Version;
820 SpecificInfo InfoSlice;
821 for (unsigned i = 0, e = Info.size(); i != e; ++i) {
822 std::tie(Version, InfoSlice) = Info[i];
823 auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
824 auto Replacement = IsSubstitution_t::Original;
825 if (Active == IsActive_t::Inactive && Version.empty()) {
826 Replacement = IsSubstitution_t::Replacement;
827 Version = Info[Selected].first;
828 }
829 ProcessAPINotes(S, D, InfoSlice,
830 VersionedInfoMetadata(Version, Active, Replacement));
831 }
832}
833
834static std::optional<api_notes::Context>
836 if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
837 for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
838 // Retrieve the context ID for the parent namespace of the decl.
839 std::stack<NamespaceDecl *> NamespaceStack;
840 {
841 for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
842 CurrentNamespace =
843 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
844 if (!CurrentNamespace->isInlineNamespace())
845 NamespaceStack.push(CurrentNamespace);
846 }
847 }
848 std::optional<api_notes::ContextID> NamespaceID;
849 while (!NamespaceStack.empty()) {
850 auto CurrentNamespace = NamespaceStack.top();
851 NamespaceStack.pop();
852 NamespaceID =
853 Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
854 if (!NamespaceID)
855 return std::nullopt;
856 }
857 if (NamespaceID)
858 return api_notes::Context(*NamespaceID,
859 api_notes::ContextKind::Namespace);
860 }
861 }
862 return std::nullopt;
863}
864
865static std::optional<api_notes::Context>
867 assert(DC && "tag context must not be null");
868 for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
869 // Retrieve the context ID for the parent tag of the decl.
870 std::stack<TagDecl *> TagStack;
871 {
872 for (auto CurrentTag = DC; CurrentTag;
873 CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
874 TagStack.push(CurrentTag);
875 }
876 assert(!TagStack.empty());
877 std::optional<api_notes::Context> Ctx =
878 UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
879 while (!TagStack.empty()) {
880 auto CurrentTag = TagStack.top();
881 TagStack.pop();
882 auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
883 if (!CtxID)
884 return std::nullopt;
885 Ctx = api_notes::Context(*CtxID, api_notes::ContextKind::Tag);
886 }
887 return Ctx;
888 }
889 return std::nullopt;
890}
891
892/// Process API notes that are associated with this declaration, mapping them
893/// to attributes as appropriate.
895 if (!D)
896 return;
897
898 auto *DC = D->getDeclContext();
899 // Globals.
900 if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
901 DC->isExternCXXContext()) {
902 std::optional<api_notes::Context> APINotesContext =
904 // Global variables.
905 if (auto VD = dyn_cast<VarDecl>(D)) {
906 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
907 auto Info =
908 Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
909 ProcessVersionedAPINotes(*this, VD, Info);
910 }
911
912 return;
913 }
914
915 // Global functions.
916 if (auto FD = dyn_cast<FunctionDecl>(D)) {
917 if (FD->getDeclName().isIdentifier()) {
918 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
919 auto Info =
920 Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
921 ProcessVersionedAPINotes(*this, FD, Info);
922 }
923 }
924
925 return;
926 }
927
928 // Objective-C classes.
929 if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
930 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
931 auto Info = Reader->lookupObjCClassInfo(Class->getName());
932 ProcessVersionedAPINotes(*this, Class, Info);
933 }
934
935 return;
936 }
937
938 // Objective-C protocols.
939 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
940 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
941 auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
942 ProcessVersionedAPINotes(*this, Protocol, Info);
943 }
944
945 return;
946 }
947
948 // Tags
949 if (auto Tag = dyn_cast<TagDecl>(D)) {
950 // Determine the name of the entity to search for. If this is an
951 // anonymous tag that gets its linked name from a typedef, look for the
952 // typedef name. This allows tag-specific information to be added
953 // to the declaration.
954 std::string LookupName;
955 if (auto typedefName = Tag->getTypedefNameForAnonDecl())
956 LookupName = typedefName->getName().str();
957 else
958 LookupName = Tag->getName().str();
959
960 // Use the source location to discern if this Tag is an OPTIONS macro.
961 // For now we would like to limit this trick of looking up the APINote tag
962 // using the EnumDecl's QualType in the case where the enum is anonymous.
963 // This is only being used to support APINotes lookup for C++
964 // NS/CF_OPTIONS when C++-Interop is enabled.
965 std::string MacroName =
966 LookupName.empty() && Tag->getOuterLocStart().isMacroID()
968 Tag->getOuterLocStart(),
969 Tag->getASTContext().getSourceManager(), LangOpts)
970 .str()
971 : "";
972
973 if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
974 (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
975 MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
976
977 clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
979 T.split(), getASTContext().getPrintingPolicy());
980 }
981
982 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
983 if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
984 APINotesContext = UnwindTagContext(ParentTag, APINotes);
985 auto Info = Reader->lookupTag(LookupName, APINotesContext);
986 ProcessVersionedAPINotes(*this, Tag, Info);
987 }
988
989 return;
990 }
991
992 // Typedefs
993 if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
994 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
995 auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
996 ProcessVersionedAPINotes(*this, Typedef, Info);
997 }
998
999 return;
1000 }
1001 }
1002
1003 // Enumerators.
1004 if (DC->getRedeclContext()->isFileContext() ||
1005 DC->getRedeclContext()->isExternCContext()) {
1006 if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1007 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1008 auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1009 ProcessVersionedAPINotes(*this, EnumConstant, Info);
1010 }
1011
1012 return;
1013 }
1014 }
1015
1016 if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1017 // Location function that looks up an Objective-C context.
1018 auto GetContext = [&](api_notes::APINotesReader *Reader)
1019 -> std::optional<api_notes::ContextID> {
1020 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1021 if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1022 return *Found;
1023
1024 return std::nullopt;
1025 }
1026
1027 if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1028 if (auto Cat = Impl->getCategoryDecl())
1029 ObjCContainer = Cat->getClassInterface();
1030 else
1031 return std::nullopt;
1032 }
1033
1034 if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1035 if (Category->getClassInterface())
1036 ObjCContainer = Category->getClassInterface();
1037 else
1038 return std::nullopt;
1039 }
1040
1041 if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1042 if (Impl->getClassInterface())
1043 ObjCContainer = Impl->getClassInterface();
1044 else
1045 return std::nullopt;
1046 }
1047
1048 if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1049 if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1050 return *Found;
1051
1052 return std::nullopt;
1053 }
1054
1055 return std::nullopt;
1056 };
1057
1058 // Objective-C methods.
1059 if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1060 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1061 if (auto Context = GetContext(Reader)) {
1062 // Map the selector.
1063 Selector Sel = Method->getSelector();
1064 SmallVector<StringRef, 2> SelPieces;
1065 if (Sel.isUnarySelector()) {
1066 SelPieces.push_back(Sel.getNameForSlot(0));
1067 } else {
1068 for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1069 SelPieces.push_back(Sel.getNameForSlot(i));
1070 }
1071
1072 api_notes::ObjCSelectorRef SelectorRef;
1073 SelectorRef.NumArgs = Sel.getNumArgs();
1074 SelectorRef.Identifiers = SelPieces;
1075
1076 auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1077 Method->isInstanceMethod());
1078 ProcessVersionedAPINotes(*this, Method, Info);
1079 }
1080 }
1081 }
1082
1083 // Objective-C properties.
1084 if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1085 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1086 if (auto Context = GetContext(Reader)) {
1087 bool isInstanceProperty =
1088 (Property->getPropertyAttributesAsWritten() &
1090 auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1091 isInstanceProperty);
1092 ProcessVersionedAPINotes(*this, Property, Info);
1093 }
1094 }
1095
1096 return;
1097 }
1098 }
1099
1100 if (auto TagContext = dyn_cast<TagDecl>(DC)) {
1101 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1102 if (!isa<CXXConstructorDecl>(CXXMethod) &&
1103 !isa<CXXDestructorDecl>(CXXMethod) &&
1104 !isa<CXXConversionDecl>(CXXMethod) &&
1105 !CXXMethod->isOverloadedOperator()) {
1106 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1107 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1108 auto Info =
1109 Reader->lookupCXXMethod(Context->id, CXXMethod->getName());
1110 ProcessVersionedAPINotes(*this, CXXMethod, Info);
1111 }
1112 }
1113 }
1114 }
1115
1116 if (auto Field = dyn_cast<FieldDecl>(D)) {
1117 if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1118 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1119 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1120 auto Info = Reader->lookupField(Context->id, Field->getName());
1121 ProcessVersionedAPINotes(*this, Field, Info);
1122 }
1123 }
1124 }
1125 }
1126
1127 if (auto Tag = dyn_cast<TagDecl>(D)) {
1128 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1129 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1130 auto Info = Reader->lookupTag(Tag->getName(), Context);
1131 ProcessVersionedAPINotes(*this, Tag, Info);
1132 }
1133 }
1134 }
1135 }
1136}
const Decl * D
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
int Category
Definition: Format.cpp:3035
static std::optional< api_notes::Context > UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes)
static void ProcessVersionedAPINotes(Sema &S, SpecificDecl *D, const api_notes::APINotesReader::VersionedInfo< SpecificInfo > Info)
Processes all versions of versioned API notes.
static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc, QualType OrigType, QualType ReplacementType)
Check that the replacement type provided by API notes is reasonable.
static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, VersionedInfoMetadata Metadata)
Apply nullability to the given declaration.
static std::optional< api_notes::Context > UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes)
static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String)
Copy a string into ASTContext-allocated memory.
static void handleAPINotedRetainCountConvention(Sema &S, Decl *D, VersionedInfoMetadata Metadata, std::optional< api_notes::RetainCountConventionKind > Convention)
static void handleAPINotedRetainCountAttribute(Sema &S, Decl *D, bool ShouldAddAttribute, VersionedInfoMetadata Metadata)
static AttributeCommonInfo getPlaceholderAttrInfo()
static void ProcessAPINotes(Sema &S, Decl *D, const api_notes::CommonEntityInfo &Info, VersionedInfoMetadata Metadata)
static void maybeAttachUnversionedSwiftName(Sema &S, Decl *D, const api_notes::APINotesReader::VersionedInfo< SpecificInfo > Info)
If we're applying API notes with an active, non-default version, and the versioned API notes have a S...
static bool isIndirectPointerType(QualType Type)
Determine whether this is a multi-level pointer type.
SourceLocation Loc
Definition: SemaObjC.cpp:759
This file declares semantic analysis for Objective-C.
This file declares semantic analysis functions specific to Swift.
Defines the clang::SourceLocation class and associated facilities.
Defines the clang::TypeLoc interface and its subclasses.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType, QualType equivalentType, const Attr *attr=nullptr) const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
IdentifierTable & Idents
Definition: ASTContext.h:680
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2482
void * Allocate(size_t Size, unsigned Align=8) const
Definition: ASTContext.h:754
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1681
QualType getAdjustedParameterType(QualType T) const
Perform adjustment on the parameter type of a function.
Attr - This represents one attribute.
Definition: Attr.h:43
A factory, from which one makes pools, from which one creates individual attributes which are dealloc...
Definition: ParsedAttr.h:637
Type source information for an attributed type.
Definition: TypeLoc.h:875
void setAttr(const Attr *A)
Definition: TypeLoc.h:901
An attributed type is a type to which a type attribute has been applied.
Definition: Type.h:6127
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2078
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void addAttr(Attr *A)
Definition: DeclBase.cpp:1010
attr_iterator attr_end() const
Definition: DeclBase.h:545
AttrVec::const_iterator attr_iterator
Definition: DeclBase.h:535
ObjCDeclQualifier
ObjCDeclQualifier - 'Qualifiers' written next to the return and parameter types in method declaration...
Definition: DeclBase.h:198
@ OBJC_TQ_CSNullability
The nullability qualifier is set when the nullability of the result or parameter was expressed via a ...
Definition: DeclBase.h:210
SourceLocation getLocation() const
Definition: DeclBase.h:442
DeclContext * getDeclContext()
Definition: DeclBase.h:451
attr_range attrs() const
Definition: DeclBase.h:538
AttrVec & getAttrs()
Definition: DeclBase.h:527
bool hasAttr() const
Definition: DeclBase.h:580
void setTypeSourceInfo(TypeSourceInfo *TI)
Definition: Decl.h:769
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:764
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3277
Represents a member of a struct/union/class.
Definition: Decl.h:3033
Represents a function declaration or definition.
Definition: Decl.h:1935
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2672
QualType getReturnType() const
Definition: Decl.h:2720
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2649
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3702
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition: Type.h:4681
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5102
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:4321
ExtInfo getExtInfo() const
Definition: Type.h:4655
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:1059
ObjCContainerDecl - Represents a container for method declarations.
Definition: DeclObjC.h:947
Represents an ObjC class declaration.
Definition: DeclObjC.h:1153
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
unsigned param_size() const
Definition: DeclObjC.h:347
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo)
Definition: DeclObjC.h:344
param_const_iterator param_begin() const
Definition: DeclObjC.h:354
void setReturnType(QualType T)
Definition: DeclObjC.h:330
QualType getReturnType() const
Definition: DeclObjC.h:329
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:730
PtrTy get() const
Definition: Ownership.h:80
Represents a parameter to a function.
Definition: Decl.h:1725
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
A (possibly-)qualified type.
Definition: Type.h:929
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
std::string getAsString() const
void * getAsOpaquePtr() const
Definition: Type.h:976
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
bool isUnarySelector() const
unsigned getNumArgs() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
QualType AdjustParameterTypeForObjCAutoRefCount(QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo)
bool DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc, const ParsedAttr &AL, bool IsAsync)
Do a check to make sure Name looks like a legal argument for the swift_name attribute applied to decl...
Definition: SemaSwift.cpp:515
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:463
ASTContext & Context
Definition: Sema.h:908
SemaObjC & ObjC()
Definition: Sema.h:1110
ASTContext & getASTContext() const
Definition: Sema.h:531
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:816
api_notes::APINotesManager APINotes
Definition: Sema.h:912
const LangOptions & LangOpts
Definition: Sema.h:906
SemaSwift & Swift()
Definition: Sema.h:1150
std::function< TypeResult(StringRef, StringRef, SourceLocation)> ParseTypeFromStringCallback
Callback to the parser to parse a type expressed as a string.
Definition: Sema.h:963
bool CheckImplicitNullabilityTypeSpecifier(QualType &Type, NullabilityKind Nullability, SourceLocation DiagLoc, bool AllowArrayTypes, bool OverrideExisting)
Check whether a nullability type specifier can be added to the given type through some means not writ...
Definition: SemaType.cpp:7407
@ AP_Explicit
The availability attribute was specified explicitly next to the declaration.
Definition: Sema.h:4382
void ProcessAPINotes(Decl *D)
Map any API notes provided for this declaration to attributes on the declaration.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:2750
Encodes a location in the source.
A trivial tuple used to represent a source range.
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3564
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
void pushFullCopy(TypeLoc L)
Pushes a copy of the given TypeLoc onto this builder.
TypeSourceInfo * getTypeSourceInfo(ASTContext &Context, QualType T)
Creates a TypeSourceInfo for the given type.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
The base class of the type hierarchy.
Definition: Type.h:1828
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8800
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
bool isMemberPointerType() const
Definition: Type.h:8240
bool isObjCObjectPointerType() const
Definition: Type.h:8328
bool isAnyPointerType() const
Definition: Type.h:8194
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3413
void setType(QualType newType)
Definition: Decl.h:683
QualType getType() const
Definition: Decl.h:682
QualType getType() const
Definition: Value.cpp:234
Represents a variable declaration or definition.
Definition: Decl.h:882
The API notes manager helps find API notes associated with declarations.
llvm::SmallVector< APINotesReader *, 2 > findAPINotes(SourceLocation Loc)
Find the API notes readers that correspond to the given source location.
Captures the completed versioned information for a particular part of API notes, including both unver...
unsigned size() const
Return the number of versioned results we know about.
std::optional< unsigned > getSelected() const
Retrieve the selected index in the result set.
A class that reads API notes data from a binary file that was written by the APINotesWriter.
Describes API notes data for a C++ method.
Definition: Types.h:696
std::optional< ParamInfo > This
Definition: Types.h:700
Describes API notes data for any entity.
Definition: Types.h:52
unsigned UnavailableInSwift
Whether this entity is marked unavailable in Swift.
Definition: Types.h:63
unsigned Unavailable
Whether this entity is marked unavailable.
Definition: Types.h:59
std::string SwiftName
Swift name of this entity.
Definition: Types.h:76
std::string UnavailableMsg
Message to use when this entity is unavailable.
Definition: Types.h:55
std::optional< bool > isSwiftPrivate() const
Definition: Types.h:82
Describes API notes for types.
Definition: Types.h:135
const std::optional< std::string > & getSwiftBridge() const
Definition: Types.h:147
const std::optional< std::string > & getNSErrorDomain() const
Definition: Types.h:155
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
Definition: Types.h:197
std::optional< bool > getSwiftImportAsNonGeneric() const
Definition: Types.h:247
std::optional< bool > getSwiftObjCMembers() const
Definition: Types.h:257
Describes API notes data for an enumerator.
Definition: Types.h:714
Describes API notes data for a C/C++ record field.
Definition: Types.h:690
API notes for a function or method.
Definition: Types.h:513
std::string SwiftReturnOwnership
Ownership convention for return value.
Definition: Types.h:546
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition: Types.h:593
std::vector< ParamInfo > Params
The function parameters.
Definition: Types.h:549
NullabilityKind getReturnTypeInfo() const
Definition: Types.h:591
NullabilityKind getParamTypeInfo(unsigned index) const
Definition: Types.h:587
std::string ResultType
The result type of this function, as a C type.
Definition: Types.h:543
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Definition: Types.h:527
Describes API notes data for a global function.
Definition: Types.h:684
Describes API notes data for a global variable.
Definition: Types.h:678
Describes API notes data for an Objective-C method.
Definition: Types.h:637
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition: Types.h:641
Describes API notes data for an Objective-C property.
Definition: Types.h:361
std::optional< bool > getSwiftImportAsAccessors() const
Definition: Types.h:371
Describes a function or method parameter.
Definition: Types.h:419
std::optional< bool > isNoEscape() const
Definition: Types.h:447
std::optional< bool > isLifetimebound() const
Definition: Types.h:455
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition: Types.h:464
Describes API notes data for a tag.
Definition: Types.h:720
std::optional< std::string > SwiftReleaseOp
Definition: Types.h:739
std::optional< std::string > SwiftRetainOp
Definition: Types.h:738
std::optional< std::string > SwiftImportAs
Definition: Types.h:737
std::optional< EnumExtensibilityKind > EnumExtensibility
Definition: Types.h:744
std::optional< bool > isFlagEnum() const
Definition: Types.h:751
std::optional< bool > isSwiftCopyable() const
Definition: Types.h:761
std::optional< bool > isSwiftEscapable() const
Definition: Types.h:770
std::optional< std::string > SwiftConformance
The Swift protocol that this type should be automatically conformed to.
Definition: Types.h:742
Describes API notes data for a typedef.
Definition: Types.h:830
std::optional< SwiftNewTypeKind > SwiftWrapper
Definition: Types.h:832
API notes for a variable/property.
Definition: Types.h:304
std::optional< NullabilityKind > getNullability() const
Definition: Types.h:320
const std::string & getType() const
Definition: Types.h:331
SwiftNewTypeKind
The kind of a swift_wrapper/swift_newtype.
Definition: Types.h:43
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
Definition: Types.h:36
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
Definition: Specifiers.h:336
@ Property
The type of a property.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition: Types.h:889
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition: Types.h:891