clang 24.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 "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"
22#include "clang/Lex/Lexer.h"
23#include "clang/Sema/SemaObjC.h"
25#include <stack>
26
27using namespace clang;
28
29namespace {
30enum class IsActive_t : bool { Inactive, Active };
31enum class IsSubstitution_t : bool { Original, Replacement };
32
33struct VersionedInfoMetadata {
34 /// An empty version refers to unversioned metadata.
35 VersionTuple Version;
36 unsigned IsActive : 1;
37 unsigned IsReplacement : 1;
38
39 VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
40 IsSubstitution_t Replacement)
41 : Version(Version), IsActive(Active == IsActive_t::Active),
42 IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
43};
44} // end anonymous namespace
45
46/// Determine whether this is a multi-level pointer type.
48 QualType Pointee = Type->getPointeeType();
49 if (Pointee.isNull())
50 return false;
51
52 return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
53 Pointee->isMemberPointerType();
54}
55
56static void applyAPINotesType(Sema &S, Decl *decl, StringRef typeString,
57 VersionedInfoMetadata metadata) {
58 if (typeString.empty())
59
60 return;
61
62 // Version-independent APINotes add "type" annotations
63 // with a versioned attribute for the client to select and apply.
65 auto *typeAttr = SwiftTypeAttr::CreateImplicit(S.Context, typeString);
66 auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
67 S.Context, metadata.Version, typeAttr, metadata.IsReplacement);
68 decl->addAttr(versioned);
69 } else {
70 if (!metadata.IsActive)
71 return;
72 S.ApplyAPINotesType(decl, typeString);
73 }
74}
75
76/// Apply nullability to the given declaration.
77static void applyNullability(Sema &S, Decl *decl, NullabilityKind nullability,
78 VersionedInfoMetadata metadata) {
79 // Version-independent APINotes add "nullability" annotations
80 // with a versioned attribute for the client to select and apply.
82 SwiftNullabilityAttr::Kind attrNullabilityKind;
83 switch (nullability) {
85 attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;
86 break;
88 attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;
89 break;
91 attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;
92 break;
94 attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;
95 break;
96 }
97 auto *nullabilityAttr =
98 SwiftNullabilityAttr::CreateImplicit(S.Context, attrNullabilityKind);
99 auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
100 S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement);
101 decl->addAttr(versioned);
102 return;
103 } else {
104 if (!metadata.IsActive)
105 return;
106
107 S.ApplyNullability(decl, nullability);
108 }
109}
110
111/// Copy a string into ASTContext-allocated memory.
112static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {
113 void *mem = Ctx.Allocate(String.size(), alignof(char *));
114 memcpy(mem, String.data(), String.size());
115 return StringRef(static_cast<char *>(mem), String.size());
116}
117
122 /*Spelling*/ 0, /*IsAlignas*/ false,
123 /*IsRegularKeywordAttribute*/ false});
124}
125
126namespace {
127template <typename A> struct AttrKindFor {};
128
129#define ATTR(X) \
130 template <> struct AttrKindFor<X##Attr> { \
131 static const attr::Kind value = attr::X; \
132 };
133#include "clang/Basic/AttrList.inc"
134
135/// Handle an attribute introduced by API notes.
136///
137/// \param IsAddition Whether we should add a new attribute
138/// (otherwise, we might remove an existing attribute).
139/// \param CreateAttr Create the new attribute to be added.
140template <typename A>
141void handleAPINotedAttribute(
142 Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,
143 llvm::function_ref<A *()> CreateAttr,
144 llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {
145 if (Metadata.IsActive) {
146 auto Existing = GetExistingAttr(D);
147 if (Existing != D->attr_end()) {
148 // Remove the existing attribute, and treat it as a superseded
149 // non-versioned attribute.
150 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
151 S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true);
152
153 D->getAttrs().erase(Existing);
154 D->addAttr(Versioned);
155 }
156
157 // If we're supposed to add a new attribute, do so.
158 if (IsAddition) {
159 if (auto Attr = CreateAttr())
160 D->addAttr(Attr);
161 }
162
163 return;
164 }
165 if (IsAddition) {
166 if (auto Attr = CreateAttr()) {
167 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
168 S.Context, Metadata.Version, Attr,
169 /*IsReplacedByActive*/ Metadata.IsReplacement);
170 D->addAttr(Versioned);
171 }
172 } else {
173 // FIXME: This isn't preserving enough information for things like
174 // availability, where we're trying to remove a /specific/ kind of
175 // attribute.
176 auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
177 S.Context, Metadata.Version, AttrKindFor<A>::value,
178 /*IsReplacedByActive*/ Metadata.IsReplacement);
179 D->addAttr(Versioned);
180 }
181}
182
183template <typename A>
184void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,
185 VersionedInfoMetadata Metadata,
186 llvm::function_ref<A *()> CreateAttr) {
187 handleAPINotedAttribute<A>(
188 S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {
189 return llvm::find_if(D->attrs(),
190 [](const Attr *Next) { return isa<A>(Next); });
191 });
192}
193} // namespace
194
195template <typename A>
197 bool ShouldAddAttribute,
198 VersionedInfoMetadata Metadata) {
199 // The template argument has a default to make the "removal" case more
200 // concise; it doesn't matter /which/ attribute is being removed.
201 handleAPINotedAttribute<A>(
202 S, D, ShouldAddAttribute, Metadata,
203 [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },
204 [](const Decl *D) -> Decl::attr_iterator {
205 return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {
206 return isa<CFReturnsRetainedAttr>(Next) ||
207 isa<CFReturnsNotRetainedAttr>(Next) ||
208 isa<NSReturnsRetainedAttr>(Next) ||
209 isa<NSReturnsNotRetainedAttr>(Next) ||
210 isa<CFAuditedTransferAttr>(Next);
211 });
212 });
213}
214
216 Sema &S, Decl *D, VersionedInfoMetadata Metadata,
217 std::optional<api_notes::RetainCountConventionKind> Convention) {
218 if (!Convention)
219 return;
220 switch (*Convention) {
222 if (isa<FunctionDecl>(D)) {
224 S, D, /*shouldAddAttribute*/ true, Metadata);
225 } else {
227 S, D, /*shouldAddAttribute*/ false, Metadata);
228 }
229 break;
232 S, D, /*shouldAddAttribute*/ true, Metadata);
233 break;
236 S, D, /*shouldAddAttribute*/ true, Metadata);
237 break;
240 S, D, /*shouldAddAttribute*/ true, Metadata);
241 break;
244 S, D, /*shouldAddAttribute*/ true, Metadata);
245 break;
246 }
247}
248
249static void ProcessAPINotes(Sema &S, Decl *D,
250 const api_notes::CommonEntityInfo &Info,
251 VersionedInfoMetadata Metadata) {
252 // Availability
253 if (Info.Unavailable) {
254 handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
255 return new (S.Context)
256 UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
258 });
259 }
260
261 if (Info.UnavailableInSwift) {
262 handleAPINotedAttribute<AvailabilityAttr>(
263 S, D, true, Metadata,
264 [&] {
265 return new (S.Context) AvailabilityAttr(
267 &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
268 VersionTuple(),
269 /*Unavailable=*/true,
271 /*Strict=*/false,
272 /*Replacement=*/StringRef(),
273 /*Priority=*/Sema::AP_Explicit,
274 /*Environment=*/nullptr);
275 },
276 [](const Decl *D) {
277 return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
278 if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
279 if (const auto *II = AA->getPlatform())
280 return II->isStr("swift");
281 return false;
282 });
283 });
284 }
285
286 // swift_private
287 if (auto SwiftPrivate = Info.isSwiftPrivate()) {
288 handleAPINotedAttribute<SwiftPrivateAttr>(
289 S, D, *SwiftPrivate, Metadata, [&] {
290 return new (S.Context)
291 SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
292 });
293 }
294
295 // swift_safety
296 if (auto SafetyKind = Info.getSwiftSafety()) {
298 handleAPINotedAttribute<SwiftAttrAttr>(
299 S, D, Addition, Metadata,
300 [&] {
301 return SwiftAttrAttr::Create(
303 ? "safe"
304 : "unsafe");
305 },
306 [](const Decl *D) {
307 return llvm::find_if(D->attrs(), [](const Attr *attr) {
308 if (const auto *swiftAttr = dyn_cast<SwiftAttrAttr>(attr)) {
309 if (swiftAttr->getAttribute() == "safe" ||
310 swiftAttr->getAttribute() == "unsafe")
311 return true;
312 }
313 return false;
314 });
315 });
316 }
317
318 // swift_name
319 if (!Info.SwiftName.empty()) {
320 handleAPINotedAttribute<SwiftNameAttr>(
321 S, D, true, Metadata, [&]() -> SwiftNameAttr * {
322 AttributeFactory AF{};
323 AttributePool AP{AF};
324 auto &C = S.getASTContext();
325 ParsedAttr *SNA = AP.create(
326 &C.Idents.get("swift_name"), SourceRange(), AttributeScopeInfo(),
327 nullptr, nullptr, nullptr, ParsedAttr::Form::GNU());
328
329 if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
330 /*IsAsync=*/false))
331 return nullptr;
332
333 return new (S.Context)
334 SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
335 ASTAllocateString(S.Context, Info.SwiftName));
336 });
337 }
338}
339
340static void ProcessAPINotes(Sema &S, Decl *D,
341 const api_notes::CommonTypeInfo &Info,
342 VersionedInfoMetadata Metadata) {
343 // swift_bridge
344 if (auto SwiftBridge = Info.getSwiftBridge()) {
345 handleAPINotedAttribute<SwiftBridgeAttr>(
346 S, D, !SwiftBridge->empty(), Metadata, [&] {
347 return new (S.Context)
348 SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
349 ASTAllocateString(S.Context, *SwiftBridge));
350 });
351 }
352
353 // ns_error_domain
354 if (auto NSErrorDomain = Info.getNSErrorDomain()) {
355 handleAPINotedAttribute<NSErrorDomainAttr>(
356 S, D, !NSErrorDomain->empty(), Metadata, [&] {
357 return new (S.Context)
358 NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
359 &S.Context.Idents.get(*NSErrorDomain));
360 });
361 }
362
363 if (auto ConformsTo = Info.getSwiftConformance())
364 D->addAttr(
365 SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
366
367 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
368 Metadata);
369}
370
371/// Check that the replacement type provided by API notes is reasonable.
372///
373/// This is a very weak form of ABI check.
375 QualType OrigType,
376 QualType ReplacementType) {
377 if (S.Context.getTypeSize(OrigType) !=
378 S.Context.getTypeSize(ReplacementType)) {
379 S.Diag(Loc, diag::err_incompatible_replacement_type)
380 << ReplacementType << OrigType;
381 return true;
382 }
383
384 return false;
385}
386
387void Sema::ApplyAPINotesType(Decl *D, StringRef TypeString) {
388 if (!TypeString.empty() && ParseTypeFromStringCallback) {
389 auto ParsedType = ParseTypeFromStringCallback(TypeString, "<API Notes>",
390 D->getLocation());
391 if (ParsedType.isUsable()) {
393 auto TypeInfo = Context.getTrivialTypeSourceInfo(Type, D->getLocation());
394 if (auto Var = dyn_cast<VarDecl>(D)) {
395 // Make adjustments to parameter types.
396 if (isa<ParmVarDecl>(Var)) {
398 Type, D->getLocation(), TypeInfo);
399 Type = Context.getAdjustedParameterType(Type);
400 }
401
402 if (!checkAPINotesReplacementType(*this, Var->getLocation(),
403 Var->getType(), Type)) {
404 Var->setType(Type);
405 Var->setTypeSourceInfo(TypeInfo);
406 }
407 } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
408 if (!checkAPINotesReplacementType(*this, property->getLocation(),
409 property->getType(), Type)) {
410 property->setType(Type, TypeInfo);
411 }
412 } else if (auto field = dyn_cast<FieldDecl>(D)) {
413 if (!checkAPINotesReplacementType(*this, field->getLocation(),
414 field->getType(), Type)) {
415 field->setType(Type);
416 field->setTypeSourceInfo(TypeInfo);
417 }
418 } else {
419 llvm_unreachable("API notes allowed a type on an unknown declaration");
420 }
421 }
422 }
423}
424
426 auto GetModified =
427 [&](class Decl *D, QualType QT,
428 NullabilityKind Nullability) -> std::optional<QualType> {
429 QualType Original = QT;
432 /*OverrideExisting=*/true);
433 return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
434 : std::nullopt;
435 };
436
437 if (auto Function = dyn_cast<FunctionDecl>(D)) {
438 if (auto Modified =
439 GetModified(D, Function->getReturnType(), Nullability)) {
440 const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
441 if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
442 Function->setType(Context.getFunctionType(
443 *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
444 else
445 Function->setType(
446 Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
447 }
448 } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
449 if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
450 Method->setReturnType(*Modified);
451
452 // Make it a context-sensitive keyword if we can.
453 if (!isIndirectPointerType(*Modified))
454 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
455 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
456 }
457 } else if (auto Value = dyn_cast<ValueDecl>(D)) {
458 if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
459 Value->setType(*Modified);
460
461 // Make it a context-sensitive keyword if we can.
462 if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
463 if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
464 Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
465 Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
466 }
467 }
468 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
469 if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
470 Property->setType(*Modified, Property->getTypeSourceInfo());
471
472 // Make it a property attribute if we can.
473 if (!isIndirectPointerType(*Modified))
474 Property->setPropertyAttributes(
476 }
477 }
478}
479
480/// Process API notes for a variable or property.
481static void ProcessAPINotes(Sema &S, Decl *D,
482 const api_notes::VariableInfo &Info,
483 VersionedInfoMetadata Metadata) {
484 // Type override.
485 applyAPINotesType(S, D, Info.getType(), Metadata);
486
487 // Nullability.
488 if (auto Nullability = Info.getNullability())
489 applyNullability(S, D, *Nullability, Metadata);
490
491 // Handle common entity information.
492 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
493 Metadata);
494}
495
496/// Process API notes for a parameter.
498 const api_notes::ParamInfo &Info,
499 VersionedInfoMetadata Metadata) {
500 // noescape
501 if (auto NoEscape = Info.isNoEscape())
502 handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
503 return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
504 });
505
506 if (auto Lifetimebound = Info.isLifetimebound())
507 handleAPINotedAttribute<LifetimeBoundAttr>(
508 S, D, *Lifetimebound, Metadata, [&] {
509 return new (S.Context)
510 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
511 });
512
513 // Retain count convention
516
517 // Handle common entity information.
518 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
519 Metadata);
520}
521
522/// Process API notes for a global variable.
523static void ProcessAPINotes(Sema &S, VarDecl *D,
525 VersionedInfoMetadata metadata) {
526 // Handle common entity information.
527 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
528 metadata);
529}
530
531/// Process API notes for a C field.
532static void ProcessAPINotes(Sema &S, FieldDecl *D,
533 const api_notes::FieldInfo &Info,
534 VersionedInfoMetadata metadata) {
535 // Handle common entity information.
536 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
537 metadata);
538}
539
540/// Process API notes for an Objective-C property.
542 const api_notes::ObjCPropertyInfo &Info,
543 VersionedInfoMetadata Metadata) {
544 // Handle common entity information.
545 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
546 Metadata);
547
548 if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
549 handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
550 S, D, *AsAccessors, Metadata, [&] {
551 return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
553 });
554 }
555}
556
557namespace {
558typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
559}
560
561/// Process API notes for a function or method.
562static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
563 const api_notes::FunctionInfo &Info,
564 VersionedInfoMetadata Metadata) {
565 // Find the declaration itself.
566 FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
567 Decl *D = FD;
568 ObjCMethodDecl *MD = nullptr;
569 if (!D) {
570 MD = cast<ObjCMethodDecl *>(AnyFunc);
571 D = MD;
572 }
573
574 assert((FD || MD) && "Expecting Function or ObjCMethod");
575
576 // Nullability of return type.
577 if (Info.NullabilityAudited)
578 applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
579
580 // Add [[clang::unsafe_buffer_usage]]
581 if (Info.UnsafeBufferUsage && !D->getAttr<UnsafeBufferUsageAttr>()) {
582 handleAPINotedAttribute<UnsafeBufferUsageAttr>(S, D, true, Metadata, [&]() {
583 return UnsafeBufferUsageAttr::Create(S.getASTContext(),
585 });
586 }
587
588 // Parameters.
589 unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
590
591 bool AnyTypeChanged = false;
592 for (unsigned I = 0; I != NumParams; ++I) {
593 ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
594 QualType ParamTypeBefore = Param->getType();
595
596 if (I < Info.Params.size())
597 ProcessAPINotes(S, Param, Info.Params[I], Metadata);
598
599 // Nullability.
600 if (Info.NullabilityAudited)
601 applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
602
603 if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
604 AnyTypeChanged = true;
605 }
606
607 // returns_(un)retained
608 if (!Info.SwiftReturnOwnership.empty())
609 D->addAttr(SwiftAttrAttr::Create(S.Context,
610 "returns_" + Info.SwiftReturnOwnership));
611
612 // Result type override.
613 QualType OverriddenResultType;
614 if (Metadata.IsActive && !Info.ResultType.empty() &&
617 Info.ResultType, "<API Notes>", D->getLocation());
618 if (ParsedType.isUsable()) {
619 QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());
620
621 if (MD) {
623 MD->getReturnType(), ResultType)) {
624 auto ResultTypeInfo =
625 S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
626 MD->setReturnType(ResultType);
627 MD->setReturnTypeSourceInfo(ResultTypeInfo);
628 }
630 S, FD->getLocation(), FD->getReturnType(), ResultType)) {
631 OverriddenResultType = ResultType;
632 AnyTypeChanged = true;
633 }
634 }
635 }
636
637 // If the result type or any of the parameter types changed for a function
638 // declaration, we have to rebuild the type.
639 if (FD && AnyTypeChanged) {
640 if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
641 if (OverriddenResultType.isNull())
642 OverriddenResultType = fnProtoType->getReturnType();
643
644 SmallVector<QualType, 4> ParamTypes;
645 for (auto Param : FD->parameters())
646 ParamTypes.push_back(Param->getType());
647
648 FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
649 fnProtoType->getExtProtoInfo()));
650 } else if (!OverriddenResultType.isNull()) {
651 const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
653 OverriddenResultType, FnNoProtoType->getExtInfo()));
654 }
655 }
656
657 // Retain count convention
660
661 // Handle common entity information.
662 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
663 Metadata);
664}
665
666/// Process API notes for a C++ method.
667static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
668 const api_notes::CXXMethodInfo &Info,
669 VersionedInfoMetadata Metadata) {
670 if (Info.This && Info.This->isLifetimebound() &&
672 auto MethodType = Method->getType();
673 auto *attr = ::new (S.Context)
674 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
675 QualType AttributedType =
676 S.Context.getAttributedType(attr, MethodType, MethodType);
677 TypeLocBuilder TLB;
678 TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
679 AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
680 TyLoc.setAttr(attr);
681 Method->setType(AttributedType);
682 Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
683 }
684
685 ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
686}
687
688/// Process API notes for a global function.
691 VersionedInfoMetadata Metadata) {
692 // Handle common function information.
693 ProcessAPINotes(S, FunctionOrMethod(D),
694 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
695}
696
697/// Process API notes for an enumerator.
699 const api_notes::EnumConstantInfo &Info,
700 VersionedInfoMetadata Metadata) {
701 // Handle common information.
702 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
703 Metadata);
704}
705
706/// Process API notes for an Objective-C method.
708 const api_notes::ObjCMethodInfo &Info,
709 VersionedInfoMetadata Metadata) {
710 // Designated initializers.
711 if (Info.DesignatedInit) {
712 handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
713 S, D, true, Metadata, [&] {
714 if (ObjCInterfaceDecl *IFace = D->getClassInterface())
715 IFace->setHasDesignatedInitializers();
716
717 return new (S.Context) ObjCDesignatedInitializerAttr(
719 });
720 }
721
722 // Handle common function information.
723 ProcessAPINotes(S, FunctionOrMethod(D),
724 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
725}
726
727/// Process API notes for a tag.
728static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
729 VersionedInfoMetadata Metadata) {
730 if (auto ImportAs = Info.SwiftImportAs)
731 D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));
732
733 if (auto RetainOp = Info.SwiftRetainOp)
734 D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));
735
736 if (auto ReleaseOp = Info.SwiftReleaseOp)
737 D->addAttr(
738 SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
739 if (auto DestroyOp = Info.SwiftDestroyOp)
740 D->addAttr(
741 SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
742 if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
743 D->addAttr(SwiftAttrAttr::Create(
744 S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
745
746 if (auto Copyable = Info.isSwiftCopyable()) {
747 if (!*Copyable)
748 D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
749 }
750
751 if (auto Escapable = Info.isSwiftEscapable()) {
752 D->addAttr(SwiftAttrAttr::Create(S.Context,
753 *Escapable ? "Escapable" : "~Escapable"));
754 }
755
756 if (auto Extensibility = Info.EnumExtensibility) {
758 bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
759 handleAPINotedAttribute<EnumExtensibilityAttr>(
760 S, D, ShouldAddAttribute, Metadata, [&] {
761 EnumExtensibilityAttr::Kind kind;
762 switch (*Extensibility) {
763 case EnumExtensibilityKind::None:
764 llvm_unreachable("remove only");
765 case EnumExtensibilityKind::Open:
766 kind = EnumExtensibilityAttr::Open;
767 break;
768 case EnumExtensibilityKind::Closed:
769 kind = EnumExtensibilityAttr::Closed;
770 break;
771 }
772 return new (S.Context)
773 EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
774 });
775 }
776
777 if (auto FlagEnum = Info.isFlagEnum()) {
778 handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
779 return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
780 });
781 }
782
783 // Handle common type information.
784 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
785 Metadata);
786}
787
788/// Process API notes for a typedef.
790 const api_notes::TypedefInfo &Info,
791 VersionedInfoMetadata Metadata) {
792 // swift_wrapper
793 using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
794
795 if (auto SwiftWrapper = Info.SwiftWrapper) {
796 handleAPINotedAttribute<SwiftNewTypeAttr>(
797 S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
798 SwiftNewTypeAttr::NewtypeKind Kind;
799 switch (*SwiftWrapper) {
800 case SwiftWrapperKind::None:
801 llvm_unreachable("Shouldn't build an attribute");
802
803 case SwiftWrapperKind::Struct:
804 Kind = SwiftNewTypeAttr::NK_Struct;
805 break;
806
807 case SwiftWrapperKind::Enum:
808 Kind = SwiftNewTypeAttr::NK_Enum;
809 break;
810 }
811 AttributeCommonInfo SyntaxInfo{
812 SourceRange(),
813 AttributeCommonInfo::AT_SwiftNewType,
814 {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
815 /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
816 return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
817 });
818 }
819
820 // Handle common type information.
821 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
822 Metadata);
823}
824
825/// Process API notes for an Objective-C class or protocol.
827 const api_notes::ContextInfo &Info,
828 VersionedInfoMetadata Metadata) {
829 // Handle common type information.
830 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
831 Metadata);
832}
833
834/// Process API notes for an Objective-C class.
836 const api_notes::ContextInfo &Info,
837 VersionedInfoMetadata Metadata) {
838 if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
839 handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
840 S, D, *AsNonGeneric, Metadata, [&] {
841 return new (S.Context)
842 SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
843 });
844 }
845
846 if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
847 handleAPINotedAttribute<SwiftObjCMembersAttr>(
848 S, D, *ObjcMembers, Metadata, [&] {
849 return new (S.Context)
850 SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
851 });
852 }
853
854 // Handle information common to Objective-C classes and protocols.
855 ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
856 Metadata);
857}
858
859/// If we're applying API notes with an active, non-default version, and the
860/// versioned API notes have a SwiftName but the declaration normally wouldn't
861/// have one, add a removal attribute to make it clear that the new SwiftName
862/// attribute only applies to the active version of \p D, not to all versions.
863///
864/// This must be run \em before processing API notes for \p D, because otherwise
865/// any existing SwiftName attribute will have been packaged up in a
866/// SwiftVersionedAdditionAttr.
867template <typename SpecificInfo>
869 Sema &S, Decl *D,
871 if (D->hasAttr<SwiftNameAttr>())
872 return;
873 if (!Info.getSelected())
874 return;
875
876 // Is the active slice versioned, and does it set a Swift name?
877 VersionTuple SelectedVersion;
878 SpecificInfo SelectedInfoSlice;
879 std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
880 if (SelectedVersion.empty())
881 return;
882 if (SelectedInfoSlice.SwiftName.empty())
883 return;
884
885 // Does the unversioned slice /not/ set a Swift name?
886 for (const auto &VersionAndInfoSlice : Info) {
887 if (!VersionAndInfoSlice.first.empty())
888 continue;
889 if (!VersionAndInfoSlice.second.SwiftName.empty())
890 return;
891 }
892
893 // Then explicitly call that out with a removal attribute.
894 VersionedInfoMetadata DummyFutureMetadata(
895 SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
896 handleAPINotedAttribute<SwiftNameAttr>(
897 S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
898 llvm_unreachable("should not try to add an attribute here");
899 });
900}
901
902/// Processes all versions of versioned API notes.
903///
904/// Just dispatches to the various ProcessAPINotes functions in this file.
905template <typename SpecificDecl, typename SpecificInfo>
907 Sema &S, SpecificDecl *D,
909
912
913 unsigned Selected = Info.getSelected().value_or(Info.size());
914
915 VersionTuple Version;
916 SpecificInfo InfoSlice;
917 for (unsigned i = 0, e = Info.size(); i != e; ++i) {
918 std::tie(Version, InfoSlice) = Info[i];
919 auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
920 auto Replacement = IsSubstitution_t::Original;
921
922 // When collecting all APINotes as version-independent,
923 // capture all as inactive and defer to the client to select the
924 // right one.
926 Active = IsActive_t::Inactive;
927 Replacement = IsSubstitution_t::Original;
928 } else if (Active == IsActive_t::Inactive && Version.empty()) {
929 Replacement = IsSubstitution_t::Replacement;
930 Version = Info[Selected].first;
931 }
932
933 ProcessAPINotes(S, D, InfoSlice,
934 VersionedInfoMetadata(Version, Active, Replacement));
935 }
936}
937
938static std::optional<api_notes::Context>
940 if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
941 for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
942 // Retrieve the context ID for the parent namespace of the decl.
943 std::stack<NamespaceDecl *> NamespaceStack;
944 {
945 for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
946 CurrentNamespace =
947 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
948 if (!CurrentNamespace->isInlineNamespace())
949 NamespaceStack.push(CurrentNamespace);
950 }
951 }
952 std::optional<api_notes::ContextID> NamespaceID;
953 while (!NamespaceStack.empty()) {
954 auto CurrentNamespace = NamespaceStack.top();
955 NamespaceStack.pop();
956 NamespaceID =
957 Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
958 if (!NamespaceID)
959 return std::nullopt;
960 }
961 if (NamespaceID)
962 return api_notes::Context(*NamespaceID,
964 }
965 }
966 return std::nullopt;
967}
968
969static std::optional<api_notes::Context>
971 assert(DC && "tag context must not be null");
972 for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
973 // Retrieve the context ID for the parent tag of the decl.
974 std::stack<TagDecl *> TagStack;
975 {
976 for (auto CurrentTag = DC; CurrentTag;
977 CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
978 TagStack.push(CurrentTag);
979 }
980 assert(!TagStack.empty());
981 std::optional<api_notes::Context> Ctx =
982 UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
983 while (!TagStack.empty()) {
984 auto CurrentTag = TagStack.top();
985 TagStack.pop();
986 auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
987 if (!CtxID)
988 return std::nullopt;
990 }
991 return Ctx;
992 }
993 return std::nullopt;
994}
995
997 while (true) {
998 if (!AttributedType::stripOuterNullability(ParamType))
999 return;
1000 }
1001}
1002
1005
1007 return Parameters == Other.Parameters;
1008 }
1009
1011 return !(*this == Other);
1012 }
1013};
1014
1017 std::optional<APINotesParameterSelector> Desugared;
1018};
1019
1020static PrintingPolicy
1022 PrintingPolicy Policy(Context.getLangOpts());
1023 Policy.PrintAsCanonical = false;
1024 Policy.FullyQualifiedName = false;
1025 Policy.SuppressScope = false;
1026 Policy.UsePreferredNames = false;
1027 Policy.MSVCFormatting = false;
1028 Policy.SplitTemplateClosers = false;
1029 Policy.IncludeNewlines = false;
1030 return Policy;
1031}
1032
1033// Print the APINotes selector spelling for one parameter. The source-spelled
1034// selector is tried first. The desugared spelling is only a permissive
1035// fallback.
1037 QualType ParamType, const ASTContext &Context, const PrintingPolicy &Policy,
1038 bool Desugar) {
1039 if (Desugar)
1040 ParamType = ParamType.getDesugaredType(Context);
1041
1042 ParamType.removeLocalConst();
1044
1045 return ParamType.getAsString(Policy);
1046}
1047
1048static std::optional<APINotesParameterSelectorCandidates>
1050 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
1051 if (!FPT)
1052 return std::nullopt;
1053
1055 APINotesParameterSelector Desugared;
1056 Candidates.Source.Parameters.reserve(FPT->getNumParams());
1057 Desugared.Parameters.reserve(FPT->getNumParams());
1058
1059 const PrintingPolicy Policy =
1061 for (QualType ParamType : FPT->param_types()) {
1062 Candidates.Source.Parameters.push_back(
1063 getAPINotesParameterSelectorSpelling(ParamType, S.Context, Policy,
1064 /*Desugar=*/false));
1066 ParamType, S.Context, Policy, /*Desugar=*/true));
1067 }
1068
1069 if (Candidates.Source != Desugared)
1070 Candidates.Desugared = std::move(Desugared);
1071
1072 return Candidates;
1073}
1074
1075// Apply the first exact selector entry found. This preserves source-spelling
1076// precedence over the desugared fallback and avoids applying multiple exact
1077// entries for the same declaration.
1078template <typename SpecificInfo, typename SpecificDecl>
1080 Sema &S, SpecificDecl *D,
1081 const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
1084 LookupExact) {
1085 auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
1086 auto Info = LookupExact(Selector.Parameters);
1087 if (Info.size() == 0)
1088 return false;
1089
1090 ProcessVersionedAPINotes(S, D, Info);
1091 return true;
1092 };
1093
1094 if (ProcessSelector(ParameterSelectorCandidates.Source))
1095 return;
1096
1097 if (ParameterSelectorCandidates.Desugared)
1098 ProcessSelector(*ParameterSelectorCandidates.Desugared);
1099}
1100
1101/// Process API notes that are associated with this declaration, mapping them
1102/// to attributes as appropriate.
1104 if (!D)
1105 return;
1106 if (!APINotes.hasAPINotes())
1107 return;
1108 auto Readers = APINotes.findAPINotes(D->getLocation());
1109 if (Readers.empty())
1110 return;
1111
1112 auto *DC = D->getDeclContext();
1113 // Globals.
1114 if (DC->isFileContext() || DC->isNamespace() ||
1115 DC->getDeclKind() == Decl::LinkageSpec) {
1116 std::optional<api_notes::Context> APINotesContext =
1118 // Global variables.
1119 if (auto VD = dyn_cast<VarDecl>(D)) {
1120 for (auto Reader : Readers) {
1121 auto Info =
1122 Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
1123 ProcessVersionedAPINotes(*this, VD, Info);
1124 }
1125
1126 return;
1127 }
1128
1129 // Global functions.
1130 if (auto FD = dyn_cast<FunctionDecl>(D)) {
1131 if (FD->getDeclName().isIdentifier()) {
1132 auto ParameterSelectorCandidates =
1134 for (auto Reader : Readers) {
1135 auto Info =
1136 Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
1137 ProcessVersionedAPINotes(*this, FD, Info);
1138
1139 if (ParameterSelectorCandidates)
1141 *this, FD, *ParameterSelectorCandidates,
1142 [&](ArrayRef<std::string> Parameters) {
1143 return Reader->lookupGlobalFunction(FD->getName(), Parameters,
1144 APINotesContext);
1145 });
1146 }
1147 }
1148
1149 return;
1150 }
1151
1152 // Objective-C classes.
1153 if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
1154 for (auto Reader : Readers) {
1155 auto Info = Reader->lookupObjCClassInfo(Class->getName());
1156 ProcessVersionedAPINotes(*this, Class, Info);
1157 }
1158
1159 return;
1160 }
1161
1162 // Objective-C protocols.
1163 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
1164 for (auto Reader : Readers) {
1165 auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
1166 ProcessVersionedAPINotes(*this, Protocol, Info);
1167 }
1168
1169 return;
1170 }
1171
1172 // Tags
1173 if (auto Tag = dyn_cast<TagDecl>(D)) {
1174 // Determine the name of the entity to search for. If this is an
1175 // anonymous tag that gets its linked name from a typedef, look for the
1176 // typedef name. This allows tag-specific information to be added
1177 // to the declaration.
1178 std::string LookupName;
1179 if (auto typedefName = Tag->getTypedefNameForAnonDecl())
1180 LookupName = typedefName->getName().str();
1181 else
1182 LookupName = Tag->getName().str();
1183
1184 // Use the source location to discern if this Tag is an OPTIONS macro.
1185 // For now we would like to limit this trick of looking up the APINote tag
1186 // using the EnumDecl's QualType in the case where the enum is anonymous.
1187 // This is only being used to support APINotes lookup for C++
1188 // NS/CF_OPTIONS when C++-Interop is enabled.
1189 std::string MacroName =
1190 LookupName.empty() && Tag->getOuterLocStart().isMacroID()
1192 Tag->getOuterLocStart(),
1193 Tag->getASTContext().getSourceManager(), LangOpts)
1194 .str()
1195 : "";
1196
1197 if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
1198 (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
1199 MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
1200
1201 clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
1203 T.split(), getASTContext().getPrintingPolicy());
1204 }
1205
1206 for (auto Reader : Readers) {
1207 if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
1208 APINotesContext = UnwindTagContext(ParentTag, APINotes);
1209 auto Info = Reader->lookupTag(LookupName, APINotesContext);
1210 ProcessVersionedAPINotes(*this, Tag, Info);
1211 }
1212
1213 return;
1214 }
1215
1216 // Typedefs
1217 if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
1218 for (auto Reader : Readers) {
1219 auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
1220 ProcessVersionedAPINotes(*this, Typedef, Info);
1221 }
1222
1223 return;
1224 }
1225 }
1226
1227 // Enumerators.
1228 if (DC->getRedeclContext()->isFileContext() ||
1229 DC->getRedeclContext()->isExternCContext()) {
1230 if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1231 for (auto Reader : Readers) {
1232 auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1233 ProcessVersionedAPINotes(*this, EnumConstant, Info);
1234 }
1235
1236 return;
1237 }
1238 }
1239
1240 if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1241 // Location function that looks up an Objective-C context.
1242 auto GetContext = [&](api_notes::APINotesReader *Reader)
1243 -> std::optional<api_notes::ContextID> {
1244 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1245 if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1246 return *Found;
1247
1248 return std::nullopt;
1249 }
1250
1251 if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1252 if (auto Cat = Impl->getCategoryDecl())
1253 ObjCContainer = Cat->getClassInterface();
1254 else
1255 return std::nullopt;
1256 }
1257
1258 if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1259 if (Category->getClassInterface())
1260 ObjCContainer = Category->getClassInterface();
1261 else
1262 return std::nullopt;
1263 }
1264
1265 if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1266 if (Impl->getClassInterface())
1267 ObjCContainer = Impl->getClassInterface();
1268 else
1269 return std::nullopt;
1270 }
1271
1272 if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1273 if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1274 return *Found;
1275
1276 return std::nullopt;
1277 }
1278
1279 return std::nullopt;
1280 };
1281
1282 // Objective-C methods.
1283 if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1284 for (auto Reader : Readers) {
1285 if (auto Context = GetContext(Reader)) {
1286 // Map the selector.
1287 Selector Sel = Method->getSelector();
1288 SmallVector<StringRef, 2> SelPieces;
1289 if (Sel.isUnarySelector()) {
1290 SelPieces.push_back(Sel.getNameForSlot(0));
1291 } else {
1292 for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1293 SelPieces.push_back(Sel.getNameForSlot(i));
1294 }
1295
1296 api_notes::ObjCSelectorRef SelectorRef;
1297 SelectorRef.NumArgs = Sel.getNumArgs();
1298 SelectorRef.Identifiers = SelPieces;
1299
1300 auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1301 Method->isInstanceMethod());
1302 ProcessVersionedAPINotes(*this, Method, Info);
1303 }
1304 }
1305 }
1306
1307 // Objective-C properties.
1308 if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1309 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1310 if (auto Context = GetContext(Reader)) {
1311 bool isInstanceProperty =
1312 (Property->getPropertyAttributesAsWritten() &
1314 auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1315 isInstanceProperty);
1316 ProcessVersionedAPINotes(*this, Property, Info);
1317 }
1318 }
1319
1320 return;
1321 }
1322 }
1323
1324 if (auto TagContext = dyn_cast<TagDecl>(DC)) {
1325 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1326 if (!isa<CXXConstructorDecl>(CXXMethod) &&
1327 !isa<CXXDestructorDecl>(CXXMethod) &&
1328 !isa<CXXConversionDecl>(CXXMethod)) {
1329 auto ParameterSelectorCandidates =
1331 for (auto Reader : Readers) {
1332 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1333 std::string MethodName;
1334 if (CXXMethod->isOverloadedOperator())
1335 MethodName =
1336 std::string("operator") +
1337 getOperatorSpelling(CXXMethod->getOverloadedOperator());
1338 else
1339 MethodName = CXXMethod->getName();
1340
1341 auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
1342 ProcessVersionedAPINotes(*this, CXXMethod, Info);
1343
1344 if (ParameterSelectorCandidates)
1346 *this, CXXMethod, *ParameterSelectorCandidates,
1347 [&](ArrayRef<std::string> Parameters) {
1348 return Reader->lookupCXXMethod(Context->id, MethodName,
1349 Parameters);
1350 });
1351 }
1352 }
1353 }
1354 }
1355
1356 if (auto Field = dyn_cast<FieldDecl>(D)) {
1357 if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1358 for (auto Reader : Readers) {
1359 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1360 auto Info = Reader->lookupField(Context->id, Field->getName());
1361 ProcessVersionedAPINotes(*this, Field, Info);
1362 }
1363 }
1364 }
1365 }
1366
1367 if (auto Tag = dyn_cast<TagDecl>(D)) {
1368 for (auto Reader : Readers) {
1369 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1370 auto Info = Reader->lookupTag(Tag->getName(), Context);
1371 ProcessVersionedAPINotes(*this, Tag, Info);
1372 }
1373 }
1374 }
1375 }
1376}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
FormatToken * Next
The next token in the unwrapped line.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static void stripAPINotesParameterNullability(QualType &ParamType)
static std::optional< api_notes::Context > UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes)
static std::string getAPINotesParameterSelectorSpelling(QualType ParamType, const ASTContext &Context, const PrintingPolicy &Policy, bool Desugar)
static std::optional< APINotesParameterSelectorCandidates > getAPINotesParameterSelectorCandidates(const Sema &S, const FunctionDecl *FD)
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 processExactAPINotes(Sema &S, SpecificDecl *D, const APINotesParameterSelectorCandidates &ParameterSelectorCandidates, llvm::function_ref< api_notes::APINotesReader::VersionedInfo< SpecificInfo >(ArrayRef< std::string >)> LookupExact)
static PrintingPolicy getAPINotesParameterSelectorPrintingPolicy(const ASTContext &Context)
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 applyAPINotesType(Sema &S, Decl *decl, StringRef typeString, VersionedInfoMetadata metadata)
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 applyNullability(Sema &S, Decl *decl, NullabilityKind nullability, VersionedInfoMetadata metadata)
Apply nullability to the given declaration.
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.
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:223
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:808
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.
void * Allocate(size_t Size, unsigned Align=8) const
Definition ASTContext.h:882
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Attr - This represents one attribute.
Definition Attr.h:46
A factory, from which one makes pools, from which one creates individual attributes which are dealloc...
Definition ParsedAttr.h:622
ParsedAttr * create(IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope, ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc=SourceLocation())
Definition ParsedAttr.h:735
Type source information for an attributed type.
Definition TypeLoc.h:1008
void setAttr(const Attr *A)
Definition TypeLoc.h:1034
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
void addAttr(Attr *A)
attr_iterator attr_end() const
Definition DeclBase.h:550
AttrVec::const_iterator attr_iterator
Definition DeclBase.h:540
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:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
attr_range attrs() const
Definition DeclBase.h:543
AttrVec & getAttrs()
Definition DeclBase.h:532
bool hasAttr() const
Definition DeclBase.h:585
An instance of this object exists for each enum constant that is defined.
Definition Decl.h:3467
Represents a member of a struct/union/class.
Definition Decl.h:3204
Represents a function declaration or definition.
Definition Decl.h:2029
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2837
QualType getReturnType() const
Definition Decl.h:2885
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2814
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3806
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4984
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5406
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4602
ExtInfo getExtInfo() const
Definition TypeBase.h:4958
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:1111
ObjCContainerDecl - Represents a container for method declarations.
Definition DeclObjC.h:948
Represents an ObjC class declaration.
Definition DeclObjC.h:1154
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
ObjCInterfaceDecl * getClassInterface()
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:731
Represents a parameter to a function.
Definition Decl.h:1819
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1312
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
std::string getAsString() const
void * getAsOpaquePtr() const
Definition TypeBase.h:985
void removeLocalConst()
Definition TypeBase.h:8597
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1348
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)
Emit a diagnostic.
Definition SemaBase.cpp:61
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...
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
ASTContext & Context
Definition Sema.h:1309
SemaObjC & ObjC()
Definition Sema.h:1519
bool captureSwiftVersionIndependentAPINotes()
Whether APINotes should be gathered for all applicable Swift language versions, without being applied...
Definition Sema.h:1670
ASTContext & getASTContext() const
Definition Sema.h:940
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1213
api_notes::APINotesManager APINotes
Definition Sema.h:1313
const LangOptions & LangOpts
Definition Sema.h:1307
SemaSwift & Swift()
Definition Sema.h:1564
std::function< TypeResult(StringRef, StringRef, SourceLocation)> ParseTypeFromStringCallback
Callback to the parser to parse a type expressed as a string.
Definition Sema.h:1362
void ApplyNullability(Decl *D, NullabilityKind Nullability)
Apply the 'Nullability:' annotation to the specified declaration.
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...
@ AP_Explicit
The availability attribute was specified explicitly next to the declaration.
Definition Sema.h:4873
void ApplyAPINotesType(Decl *D, StringRef TypeString)
Apply the 'Type:' annotation to the specified declaration.
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)
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:3761
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.
The base class of the type hierarchy.
Definition TypeBase.h:1876
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9386
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isMemberPointerType() const
Definition TypeBase.h:8807
bool isObjCObjectPointerType() const
Definition TypeBase.h:8905
bool isAnyPointerType() const
Definition TypeBase.h:8734
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9319
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3606
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
QualType getType() const
Definition Value.cpp:238
Represents a variable declaration or definition.
Definition Decl.h:932
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:803
std::optional< ParamInfo > This
Definition Types.h:807
Describes API notes data for any entity.
Definition Types.h:54
unsigned UnavailableInSwift
Whether this entity is marked unavailable in Swift.
Definition Types.h:65
unsigned Unavailable
Whether this entity is marked unavailable.
Definition Types.h:61
std::string UnavailableMsg
Message to use when this entity is unavailable.
Definition Types.h:57
std::optional< SwiftSafetyKind > getSwiftSafety() const
Definition Types.h:100
std::optional< bool > isSwiftPrivate() const
Definition Types.h:90
Describes API notes for types.
Definition Types.h:159
std::optional< std::string > getSwiftConformance() const
Definition Types.h:195
const std::optional< std::string > & getSwiftBridge() const
Definition Types.h:174
const std::optional< std::string > & getNSErrorDomain() const
Definition Types.h:182
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
Definition Types.h:235
std::optional< bool > getSwiftImportAsNonGeneric() const
Definition Types.h:279
std::optional< bool > getSwiftObjCMembers() const
Definition Types.h:289
Describes API notes data for an enumerator.
Definition Types.h:821
Describes API notes data for a C/C++ record field.
Definition Types.h:797
API notes for a function or method.
Definition Types.h:615
std::string SwiftReturnOwnership
Ownership convention for return value.
Definition Types.h:652
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:699
std::vector< ParamInfo > Params
The function parameters.
Definition Types.h:655
NullabilityKind getReturnTypeInfo() const
Definition Types.h:697
NullabilityKind getParamTypeInfo(unsigned index) const
Definition Types.h:693
std::string ResultType
The result type of this function, as a C type.
Definition Types.h:649
unsigned UnsafeBufferUsage
Whether the function has the [[clang::unsafe_buffer_usage]] attribute.
Definition Types.h:639
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Definition Types.h:629
Describes API notes data for a global function.
Definition Types.h:791
Describes API notes data for a global variable.
Definition Types.h:785
Describes API notes data for an Objective-C method.
Definition Types.h:744
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition Types.h:748
Describes API notes data for an Objective-C property.
Definition Types.h:457
std::optional< bool > getSwiftImportAsAccessors() const
Definition Types.h:467
Describes a function or method parameter.
Definition Types.h:515
std::optional< bool > isNoEscape() const
Definition Types.h:545
std::optional< bool > isLifetimebound() const
Definition Types.h:553
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:562
Describes API notes data for a tag.
Definition Types.h:827
std::optional< std::string > SwiftReleaseOp
Definition Types.h:846
std::optional< std::string > SwiftRetainOp
Definition Types.h:845
std::optional< std::string > SwiftImportAs
Definition Types.h:844
std::optional< std::string > SwiftDefaultOwnership
Definition Types.h:848
std::optional< EnumExtensibilityKind > EnumExtensibility
Definition Types.h:850
std::optional< std::string > SwiftDestroyOp
Definition Types.h:847
std::optional< bool > isFlagEnum() const
Definition Types.h:857
std::optional< bool > isSwiftCopyable() const
Definition Types.h:867
std::optional< bool > isSwiftEscapable() const
Definition Types.h:876
Describes API notes data for a typedef.
Definition Types.h:938
std::optional< SwiftNewTypeKind > SwiftWrapper
Definition Types.h:940
API notes for a variable/property.
Definition Types.h:408
const std::string & getType() const
Definition Types.h:428
NullabilityKindOrNone getNullability() const
Definition Types.h:420
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< Decl > decl
Matches declarations.
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
NullabilityKind
Describes the nullability of a particular type.
Definition Specifiers.h:349
@ Nullable
Values of this type can be null.
Definition Specifiers.h:353
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
Definition Specifiers.h:358
@ NonNull
Values of this type can never be null.
Definition Specifiers.h:351
@ Property
The type of a property.
Definition TypeBase.h:912
const FunctionProtoType * T
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
U cast(CodeGen::Address addr)
Definition Address.h:327
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:6016
@ Other
Other implicit parameter.
Definition Decl.h:1774
APINotesParameterSelector Source
std::optional< APINotesParameterSelector > Desugared
bool operator!=(const APINotesParameterSelector &Other) const
SmallVector< std::string, 4 > Parameters
bool operator==(const APINotesParameterSelector &Other) const
Describes how types, statements, expressions, and declarations should be printed.
unsigned FullyQualifiedName
When true, print the fully qualified name of function declarations.
unsigned MSVCFormatting
Use whitespace and punctuation like MSVC does.
unsigned SplitTemplateClosers
Whether nested templates must be closed like 'a<b<c> >' rather than 'a<b<c>>'.
unsigned UsePreferredNames
Whether to use C++ template preferred_name attributes when printing templates.
unsigned SuppressScope
Suppresses printing of scope specifiers.
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
unsigned PrintAsCanonical
Whether to print entities as written or canonically.
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition Types.h:997
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition Types.h:999