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
14#include "TypeLocBuilder.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/TypeLoc.h"
23#include "clang/Lex/Lexer.h"
24#include "clang/Sema/SemaObjC.h"
26#include <stack>
27
28using namespace clang;
29
30namespace {
31enum class IsActive_t : bool { Inactive, Active };
32enum class IsSubstitution_t : bool { Original, Replacement };
33
34struct VersionedInfoMetadata {
35 /// An empty version refers to unversioned metadata.
36 VersionTuple Version;
37 /// Which lookup group this slice came from.
38 /// See the SwiftVersionedAddition comment in Attr.td.
39 unsigned SliceGroup;
40 unsigned IsActive : 1;
41 unsigned IsReplacement : 1;
42
43 VersionedInfoMetadata(VersionTuple Version, unsigned SliceGroup,
44 IsActive_t Active, IsSubstitution_t Replacement)
45 : Version(Version), SliceGroup(SliceGroup),
46 IsActive(Active == IsActive_t::Active),
47 IsReplacement(Replacement == IsSubstitution_t::Replacement) {}
48};
49} // end anonymous namespace
50
51/// Determine whether this is a multi-level pointer type.
53 QualType Pointee = Type->getPointeeType();
54 if (Pointee.isNull())
55 return false;
56
57 return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
58 Pointee->isMemberPointerType();
59}
60
61static void applyAPINotesType(Sema &S, Decl *decl, StringRef typeString,
62 VersionedInfoMetadata metadata) {
63 if (typeString.empty())
64
65 return;
66
67 // Version-independent APINotes add "type" annotations
68 // with a versioned attribute for the client to select and apply.
70 auto *typeAttr = SwiftTypeAttr::CreateImplicit(S.Context, typeString);
71 auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
72 S.Context, metadata.Version, typeAttr, metadata.IsReplacement,
73 metadata.SliceGroup);
74 decl->addAttr(versioned);
75 } else {
76 if (!metadata.IsActive)
77 return;
78 S.ApplyAPINotesType(decl, typeString);
79 }
80}
81
82/// Apply nullability to the given declaration.
83static void applyNullability(Sema &S, Decl *decl, NullabilityKind nullability,
84 VersionedInfoMetadata metadata) {
85 // Version-independent APINotes add "nullability" annotations
86 // with a versioned attribute for the client to select and apply.
88 SwiftNullabilityAttr::Kind attrNullabilityKind;
89 switch (nullability) {
91 attrNullabilityKind = SwiftNullabilityAttr::Kind::NonNull;
92 break;
94 attrNullabilityKind = SwiftNullabilityAttr::Kind::Nullable;
95 break;
97 attrNullabilityKind = SwiftNullabilityAttr::Kind::Unspecified;
98 break;
100 attrNullabilityKind = SwiftNullabilityAttr::Kind::NullableResult;
101 break;
102 }
103 auto *nullabilityAttr =
104 SwiftNullabilityAttr::CreateImplicit(S.Context, attrNullabilityKind);
105 auto *versioned = SwiftVersionedAdditionAttr::CreateImplicit(
106 S.Context, metadata.Version, nullabilityAttr, metadata.IsReplacement,
107 metadata.SliceGroup);
108 decl->addAttr(versioned);
109 return;
110 } else {
111 if (!metadata.IsActive)
112 return;
113
114 S.ApplyNullability(decl, nullability);
115 }
116}
117
118/// Copy a string into ASTContext-allocated memory.
119static StringRef ASTAllocateString(ASTContext &Ctx, StringRef String) {
120 void *mem = Ctx.Allocate(String.size(), alignof(char *));
121 memcpy(mem, String.data(), String.size());
122 return StringRef(static_cast<char *>(mem), String.size());
123}
124
129 /*Spelling*/ 0, /*IsAlignas*/ false,
130 /*IsRegularKeywordAttribute*/ false});
131}
132
133namespace {
134template <typename A> struct AttrKindFor {};
135
136#define ATTR(X) \
137 template <> struct AttrKindFor<X##Attr> { \
138 static const attr::Kind value = attr::X; \
139 };
140#include "clang/Basic/AttrList.inc"
141
142/// Handle an attribute introduced by API notes.
143///
144/// \param IsAddition Whether we should add a new attribute
145/// (otherwise, we might remove an existing attribute).
146/// \param CreateAttr Create the new attribute to be added.
147template <typename A>
148void handleAPINotedAttribute(
149 Sema &S, Decl *D, bool IsAddition, VersionedInfoMetadata Metadata,
150 llvm::function_ref<A *()> CreateAttr,
151 llvm::function_ref<Decl::attr_iterator(const Decl *)> GetExistingAttr) {
152 if (Metadata.IsActive) {
153 auto Existing = GetExistingAttr(D);
154 if (Existing != D->attr_end()) {
155 // Remove the existing attribute, and treat it as a superseded
156 // non-versioned attribute.
157 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
158 S.Context, Metadata.Version, *Existing, /*IsReplacedByActive*/ true,
159 Metadata.SliceGroup);
160
161 D->getAttrs().erase(Existing);
162 D->addAttr(Versioned);
163 }
164
165 // If we're supposed to add a new attribute, do so.
166 if (IsAddition) {
167 if (auto Attr = CreateAttr())
168 D->addAttr(Attr);
169 }
170
171 return;
172 }
173 if (IsAddition) {
174 if (auto Attr = CreateAttr()) {
175 auto *Versioned = SwiftVersionedAdditionAttr::CreateImplicit(
176 S.Context, Metadata.Version, Attr,
177 /*IsReplacedByActive*/ Metadata.IsReplacement, Metadata.SliceGroup);
178 D->addAttr(Versioned);
179 }
180 } else {
181 // FIXME: This isn't preserving enough information for things like
182 // availability, where we're trying to remove a /specific/ kind of
183 // attribute.
184 auto *Versioned = SwiftVersionedRemovalAttr::CreateImplicit(
185 S.Context, Metadata.Version, AttrKindFor<A>::value,
186 /*IsReplacedByActive*/ Metadata.IsReplacement, Metadata.SliceGroup);
187 D->addAttr(Versioned);
188 }
189}
190
191template <typename A>
192void handleAPINotedAttribute(Sema &S, Decl *D, bool ShouldAddAttribute,
193 VersionedInfoMetadata Metadata,
194 llvm::function_ref<A *()> CreateAttr) {
195 handleAPINotedAttribute<A>(
196 S, D, ShouldAddAttribute, Metadata, CreateAttr, [](const Decl *D) {
197 return llvm::find_if(D->attrs(),
198 [](const Attr *Next) { return isa<A>(Next); });
199 });
200}
201} // namespace
202
203template <typename A>
205 bool ShouldAddAttribute,
206 VersionedInfoMetadata Metadata) {
207 // The template argument has a default to make the "removal" case more
208 // concise; it doesn't matter /which/ attribute is being removed.
209 handleAPINotedAttribute<A>(
210 S, D, ShouldAddAttribute, Metadata,
211 [&] { return new (S.Context) A(S.Context, getPlaceholderAttrInfo()); },
212 [](const Decl *D) -> Decl::attr_iterator {
213 return llvm::find_if(D->attrs(), [](const Attr *Next) -> bool {
214 return isa<CFReturnsRetainedAttr>(Next) ||
215 isa<CFReturnsNotRetainedAttr>(Next) ||
216 isa<NSReturnsRetainedAttr>(Next) ||
217 isa<NSReturnsNotRetainedAttr>(Next) ||
218 isa<CFAuditedTransferAttr>(Next);
219 });
220 });
221}
222
224 Sema &S, Decl *D, VersionedInfoMetadata Metadata,
225 std::optional<api_notes::RetainCountConventionKind> Convention) {
226 if (!Convention)
227 return;
228 switch (*Convention) {
230 if (isa<FunctionDecl>(D)) {
232 S, D, /*shouldAddAttribute*/ true, Metadata);
233 } else {
235 S, D, /*shouldAddAttribute*/ false, Metadata);
236 }
237 break;
240 S, D, /*shouldAddAttribute*/ true, Metadata);
241 break;
244 S, D, /*shouldAddAttribute*/ true, Metadata);
245 break;
248 S, D, /*shouldAddAttribute*/ true, Metadata);
249 break;
252 S, D, /*shouldAddAttribute*/ true, Metadata);
253 break;
254 }
255}
256
257/// Add a 'swift_attr' unless \p D already carries that exact annotation.
258static void addSwiftAttrIfAbsent(Sema &S, Decl *D, StringRef Attribute) {
259 for (const auto *A : D->specific_attrs<SwiftAttrAttr>())
260 if (A->getAttribute() == Attribute)
261 return;
262
263 D->addAttr(SwiftAttrAttr::Create(S.Context, Attribute));
264}
265
266static void ProcessAPINotes(Sema &S, Decl *D,
267 const api_notes::CommonEntityInfo &Info,
268 VersionedInfoMetadata Metadata) {
269 // Availability
270 if (Info.Unavailable) {
271 handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
272 return new (S.Context)
273 UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
275 });
276 }
277
278 if (Info.UnavailableInSwift) {
279 handleAPINotedAttribute<AvailabilityAttr>(
280 S, D, true, Metadata,
281 [&] {
282 return new (S.Context) AvailabilityAttr(
284 &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
285 VersionTuple(),
286 /*Unavailable=*/true,
288 /*Strict=*/false,
289 /*Replacement=*/StringRef(),
290 /*Priority=*/Sema::AP_Explicit,
291 /*Environment=*/nullptr);
292 },
293 [](const Decl *D) {
294 return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
295 if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
296 if (const auto *II = AA->getPlatform())
297 return II->isStr("swift");
298 return false;
299 });
300 });
301 }
302
303 // swift_private
304 if (auto SwiftPrivate = Info.isSwiftPrivate()) {
305 handleAPINotedAttribute<SwiftPrivateAttr>(
306 S, D, *SwiftPrivate, Metadata, [&] {
307 return new (S.Context)
308 SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
309 });
310 }
311
312 // swift_safety
313 if (auto SafetyKind = Info.getSwiftSafety()) {
315 handleAPINotedAttribute<SwiftAttrAttr>(
316 S, D, Addition, Metadata,
317 [&] {
318 return SwiftAttrAttr::Create(
320 ? "safe"
321 : "unsafe");
322 },
323 [](const Decl *D) {
324 return llvm::find_if(D->attrs(), [](const Attr *attr) {
325 if (const auto *swiftAttr = dyn_cast<SwiftAttrAttr>(attr)) {
326 if (swiftAttr->getAttribute() == "safe" ||
327 swiftAttr->getAttribute() == "unsafe")
328 return true;
329 }
330 return false;
331 });
332 });
333 }
334
335 // swift_name
336 if (!Info.SwiftName.empty()) {
337 handleAPINotedAttribute<SwiftNameAttr>(
338 S, D, true, Metadata, [&]() -> SwiftNameAttr * {
339 AttributeFactory AF{};
340 AttributePool AP{AF};
341 auto &C = S.getASTContext();
342 ParsedAttr *SNA = AP.create(
343 &C.Idents.get("swift_name"), SourceRange(), AttributeScopeInfo(),
344 nullptr, nullptr, nullptr, ParsedAttr::Form::GNU());
345
346 if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
347 /*IsAsync=*/false))
348 return nullptr;
349
350 return new (S.Context)
351 SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
352 ASTAllocateString(S.Context, Info.SwiftName));
353 });
354 }
355}
356
357static void ProcessAPINotes(Sema &S, Decl *D,
358 const api_notes::CommonTypeInfo &Info,
359 VersionedInfoMetadata Metadata) {
360 // swift_bridge
361 if (auto SwiftBridge = Info.getSwiftBridge()) {
362 handleAPINotedAttribute<SwiftBridgeAttr>(
363 S, D, !SwiftBridge->empty(), Metadata, [&] {
364 return new (S.Context)
365 SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
366 ASTAllocateString(S.Context, *SwiftBridge));
367 });
368 }
369
370 // ns_error_domain
371 if (auto NSErrorDomain = Info.getNSErrorDomain()) {
372 handleAPINotedAttribute<NSErrorDomainAttr>(
373 S, D, !NSErrorDomain->empty(), Metadata, [&] {
374 return new (S.Context)
375 NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
376 &S.Context.Idents.get(*NSErrorDomain));
377 });
378 }
379
380 if (auto ConformsTo = Info.getSwiftConformance())
381 addSwiftAttrIfAbsent(S, D, "conforms_to:" + ConformsTo.value());
382
383 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
384 Metadata);
385}
386
387/// Check that the replacement type provided by API notes is reasonable.
388///
389/// This is a very weak form of ABI check.
391 QualType OrigType,
392 QualType ReplacementType) {
393 if (S.Context.getTypeSize(OrigType) !=
394 S.Context.getTypeSize(ReplacementType)) {
395 S.Diag(Loc, diag::err_incompatible_replacement_type)
396 << ReplacementType << OrigType;
397 return true;
398 }
399
400 return false;
401}
402
403void Sema::ApplyAPINotesType(Decl *D, StringRef TypeString) {
404 if (!TypeString.empty() && ParseTypeFromStringCallback) {
405 auto ParsedType = ParseTypeFromStringCallback(TypeString, "<API Notes>",
406 D->getLocation());
407 if (ParsedType.isUsable()) {
409 auto TypeInfo = Context.getTrivialTypeSourceInfo(Type, D->getLocation());
410 if (auto Var = dyn_cast<VarDecl>(D)) {
411 // Make adjustments to parameter types.
412 if (isa<ParmVarDecl>(Var)) {
414 Type, D->getLocation(), TypeInfo);
415 Type = Context.getAdjustedParameterType(Type);
416 }
417
418 if (!checkAPINotesReplacementType(*this, Var->getLocation(),
419 Var->getType(), Type)) {
420 Var->setType(Type);
421 Var->setTypeSourceInfo(TypeInfo);
422 }
423 } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
424 if (!checkAPINotesReplacementType(*this, property->getLocation(),
425 property->getType(), Type)) {
426 property->setType(Type, TypeInfo);
427 }
428 } else if (auto field = dyn_cast<FieldDecl>(D)) {
429 if (!checkAPINotesReplacementType(*this, field->getLocation(),
430 field->getType(), Type)) {
431 field->setType(Type);
432 field->setTypeSourceInfo(TypeInfo);
433 }
434 } else {
435 llvm_unreachable("API notes allowed a type on an unknown declaration");
436 }
437 }
438 }
439}
440
442 auto GetModified =
443 [&](class Decl *D, QualType QT,
444 NullabilityKind Nullability) -> std::optional<QualType> {
445 QualType Original = QT;
448 /*OverrideExisting=*/true);
449 return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
450 : std::nullopt;
451 };
452
453 if (auto Function = dyn_cast<FunctionDecl>(D)) {
454 if (auto Modified =
455 GetModified(D, Function->getReturnType(), Nullability)) {
456 const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
457 if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
458 Function->setType(Context.getFunctionType(
459 *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
460 else
461 Function->setType(
462 Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
463 }
464 } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
465 if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
466 Method->setReturnType(*Modified);
467
468 // Make it a context-sensitive keyword if we can.
469 if (!isIndirectPointerType(*Modified))
470 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
471 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
472 }
473 } else if (auto Value = dyn_cast<ValueDecl>(D)) {
474 if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
475 Value->setType(*Modified);
476
477 // Make it a context-sensitive keyword if we can.
478 if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
479 if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
480 Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
481 Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
482 }
483 }
484 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
485 if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
486 Property->setType(*Modified, Property->getTypeSourceInfo());
487
488 // Make it a property attribute if we can.
489 if (!isIndirectPointerType(*Modified))
490 Property->setPropertyAttributes(
492 }
493 }
494}
495
496/// Process API notes for a variable or property.
497static void ProcessAPINotes(Sema &S, Decl *D,
498 const api_notes::VariableInfo &Info,
499 VersionedInfoMetadata Metadata) {
500 // Type override.
501 applyAPINotesType(S, D, Info.getType(), Metadata);
502
503 // Nullability.
504 if (auto Nullability = Info.getNullability())
505 applyNullability(S, D, *Nullability, Metadata);
506
507 // Handle common entity information.
508 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
509 Metadata);
510}
511
512/// Process API notes for a parameter.
514 const api_notes::ParamInfo &Info,
515 VersionedInfoMetadata Metadata) {
516 // noescape
517 if (auto NoEscape = Info.isNoEscape())
518 handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
519 return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
520 });
521
522 if (auto Lifetimebound = Info.isLifetimebound())
523 handleAPINotedAttribute<LifetimeBoundAttr>(
524 S, D, *Lifetimebound, Metadata, [&] {
525 return new (S.Context)
526 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
527 });
528
529 // Retain count convention
532
533 // Handle common entity information.
534 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
535 Metadata);
536}
537
538/// Process API notes for a global variable.
539static void ProcessAPINotes(Sema &S, VarDecl *D,
541 VersionedInfoMetadata metadata) {
542 // Handle common entity information.
543 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
544 metadata);
545}
546
547/// Process API notes for a C field.
548static void ProcessAPINotes(Sema &S, FieldDecl *D,
549 const api_notes::FieldInfo &Info,
550 VersionedInfoMetadata metadata) {
551 // Handle common entity information.
552 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
553 metadata);
554}
555
556/// Process API notes for an Objective-C property.
558 const api_notes::ObjCPropertyInfo &Info,
559 VersionedInfoMetadata Metadata) {
560 // Handle common entity information.
561 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
562 Metadata);
563
564 if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
565 handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
566 S, D, *AsAccessors, Metadata, [&] {
567 return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
569 });
570 }
571}
572
573namespace {
574typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
575}
576
577/// Process API notes for a function or method.
578static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
579 const api_notes::FunctionInfo &Info,
580 VersionedInfoMetadata Metadata) {
581 // Find the declaration itself.
582 FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
583 Decl *D = FD;
584 ObjCMethodDecl *MD = nullptr;
585 if (!D) {
586 MD = cast<ObjCMethodDecl *>(AnyFunc);
587 D = MD;
588 }
589
590 assert((FD || MD) && "Expecting Function or ObjCMethod");
591
592 // Nullability of return type.
593 if (Info.NullabilityAudited)
594 applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
595
596 // Add [[clang::unsafe_buffer_usage]]
597 if (Info.UnsafeBufferUsage && !D->getAttr<UnsafeBufferUsageAttr>()) {
598 handleAPINotedAttribute<UnsafeBufferUsageAttr>(S, D, true, Metadata, [&]() {
599 return UnsafeBufferUsageAttr::Create(S.getASTContext(), "",
601 });
602 }
603
604 // Parameters.
605 unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
606
607 bool AnyTypeChanged = false;
608 for (unsigned I = 0; I != NumParams; ++I) {
609 ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
610 QualType ParamTypeBefore = Param->getType();
611
612 if (I < Info.Params.size())
613 ProcessAPINotes(S, Param, Info.Params[I], Metadata);
614
615 // Nullability.
616 if (Info.NullabilityAudited)
617 applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
618
619 if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
620 AnyTypeChanged = true;
621 }
622
623 // returns_(un)retained
624 if (!Info.SwiftReturnOwnership.empty())
625 addSwiftAttrIfAbsent(S, D, "returns_" + Info.SwiftReturnOwnership);
626
627 // Result type override.
628 QualType OverriddenResultType;
629 if (Metadata.IsActive && !Info.ResultType.empty() &&
632 Info.ResultType, "<API Notes>", D->getLocation());
633 if (ParsedType.isUsable()) {
634 QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());
635
636 if (MD) {
638 MD->getReturnType(), ResultType)) {
639 auto ResultTypeInfo =
640 S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
641 MD->setReturnType(ResultType);
642 MD->setReturnTypeSourceInfo(ResultTypeInfo);
643 }
645 S, FD->getLocation(), FD->getReturnType(), ResultType)) {
646 OverriddenResultType = ResultType;
647 AnyTypeChanged = true;
648 }
649 }
650 }
651
652 // If the result type or any of the parameter types changed for a function
653 // declaration, we have to rebuild the type.
654 if (FD && AnyTypeChanged) {
655 if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
656 if (OverriddenResultType.isNull())
657 OverriddenResultType = fnProtoType->getReturnType();
658
659 SmallVector<QualType, 4> ParamTypes;
660 for (auto Param : FD->parameters())
661 ParamTypes.push_back(Param->getType());
662
663 FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
664 fnProtoType->getExtProtoInfo()));
665 } else if (!OverriddenResultType.isNull()) {
666 const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
668 OverriddenResultType, FnNoProtoType->getExtInfo()));
669 }
670 }
671
672 // Retain count convention
675
676 // Handle common entity information.
677 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
678 Metadata);
679}
680
681/// Process API notes for a C++ method.
682static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
683 const api_notes::CXXMethodInfo &Info,
684 VersionedInfoMetadata Metadata) {
685 if (Info.This && Info.This->isLifetimebound() &&
687 auto MethodType = Method->getType();
688 auto *attr = ::new (S.Context)
689 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
690 QualType AttributedType =
691 S.Context.getAttributedType(attr, MethodType, MethodType);
692 TypeLocBuilder TLB;
693 TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
694 AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
695 TyLoc.setAttr(attr);
696 Method->setType(AttributedType);
697 Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
698 }
699
700 ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
701}
702
703/// Process API notes for a global function.
706 VersionedInfoMetadata Metadata) {
707 // Handle common function information.
708 ProcessAPINotes(S, FunctionOrMethod(D),
709 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
710}
711
712/// Process API notes for an enumerator.
714 const api_notes::EnumConstantInfo &Info,
715 VersionedInfoMetadata Metadata) {
716 // Handle common information.
717 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
718 Metadata);
719}
720
721/// Process API notes for an Objective-C method.
723 const api_notes::ObjCMethodInfo &Info,
724 VersionedInfoMetadata Metadata) {
725 // Designated initializers.
726 if (Info.DesignatedInit) {
727 handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
728 S, D, true, Metadata, [&] {
729 if (ObjCInterfaceDecl *IFace = D->getClassInterface())
730 IFace->setHasDesignatedInitializers();
731
732 return new (S.Context) ObjCDesignatedInitializerAttr(
734 });
735 }
736
737 // Handle common function information.
738 ProcessAPINotes(S, FunctionOrMethod(D),
739 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
740}
741
742/// Process API notes for a tag.
743static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
744 VersionedInfoMetadata Metadata) {
745 if (auto ImportAs = Info.SwiftImportAs)
746 addSwiftAttrIfAbsent(S, D, "import_" + ImportAs.value());
747
748 if (auto RetainOp = Info.SwiftRetainOp)
749 addSwiftAttrIfAbsent(S, D, "retain:" + RetainOp.value());
750
751 if (auto ReleaseOp = Info.SwiftReleaseOp)
752 addSwiftAttrIfAbsent(S, D, "release:" + ReleaseOp.value());
753 if (auto DestroyOp = Info.SwiftDestroyOp)
754 addSwiftAttrIfAbsent(S, D, "destroy:" + DestroyOp.value());
755 if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
757 S, D, "returned_as_" + DefaultOwnership.value() + "_by_default");
758
759 if (auto Copyable = Info.isSwiftCopyable()) {
760 if (!*Copyable)
761 addSwiftAttrIfAbsent(S, D, "~Copyable");
762 }
763
764 if (auto Escapable = Info.isSwiftEscapable()) {
765 addSwiftAttrIfAbsent(S, D, *Escapable ? "Escapable" : "~Escapable");
766 }
767
768 if (auto Extensibility = Info.EnumExtensibility) {
770 bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
771 handleAPINotedAttribute<EnumExtensibilityAttr>(
772 S, D, ShouldAddAttribute, Metadata, [&] {
773 EnumExtensibilityAttr::Kind kind;
774 switch (*Extensibility) {
775 case EnumExtensibilityKind::None:
776 llvm_unreachable("remove only");
777 case EnumExtensibilityKind::Open:
778 kind = EnumExtensibilityAttr::Open;
779 break;
780 case EnumExtensibilityKind::Closed:
781 kind = EnumExtensibilityAttr::Closed;
782 break;
783 }
784 return new (S.Context)
785 EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
786 });
787 }
788
789 if (auto FlagEnum = Info.isFlagEnum()) {
790 handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
791 return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
792 });
793 }
794
795 // Handle common type information.
796 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
797 Metadata);
798}
799
800/// Process API notes for a typedef.
802 const api_notes::TypedefInfo &Info,
803 VersionedInfoMetadata Metadata) {
804 // swift_wrapper
805 using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
806
807 if (auto SwiftWrapper = Info.SwiftWrapper) {
808 handleAPINotedAttribute<SwiftNewTypeAttr>(
809 S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
810 SwiftNewTypeAttr::NewtypeKind Kind;
811 switch (*SwiftWrapper) {
812 case SwiftWrapperKind::None:
813 llvm_unreachable("Shouldn't build an attribute");
814
815 case SwiftWrapperKind::Struct:
816 Kind = SwiftNewTypeAttr::NK_Struct;
817 break;
818
819 case SwiftWrapperKind::Enum:
820 Kind = SwiftNewTypeAttr::NK_Enum;
821 break;
822 }
823 AttributeCommonInfo SyntaxInfo{
824 SourceRange(),
825 AttributeCommonInfo::AT_SwiftNewType,
826 {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
827 /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
828 return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
829 });
830 }
831
832 // Handle common type information.
833 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
834 Metadata);
835}
836
837/// Process API notes for an Objective-C class or protocol.
839 const api_notes::ContextInfo &Info,
840 VersionedInfoMetadata Metadata) {
841 // Handle common type information.
842 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
843 Metadata);
844}
845
846/// Process API notes for an Objective-C class.
848 const api_notes::ContextInfo &Info,
849 VersionedInfoMetadata Metadata) {
850 if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
851 handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
852 S, D, *AsNonGeneric, Metadata, [&] {
853 return new (S.Context)
854 SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
855 });
856 }
857
858 if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
859 handleAPINotedAttribute<SwiftObjCMembersAttr>(
860 S, D, *ObjcMembers, Metadata, [&] {
861 return new (S.Context)
862 SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
863 });
864 }
865
866 // Handle information common to Objective-C classes and protocols.
867 ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
868 Metadata);
869}
870
871/// If we're applying API notes with an active, non-default version, and the
872/// versioned API notes have a SwiftName but the declaration normally wouldn't
873/// have one, add a removal attribute to make it clear that the new SwiftName
874/// attribute only applies to the active version of \p D, not to all versions.
875///
876/// This must be run \em before processing API notes for \p D, because otherwise
877/// any existing SwiftName attribute will have been packaged up in a
878/// SwiftVersionedAdditionAttr.
879template <typename SpecificInfo>
881 Sema &S, Decl *D,
883 unsigned SliceGroup) {
884 if (D->hasAttr<SwiftNameAttr>())
885 return;
886 if (!Info.getSelected())
887 return;
888
889 // Is the active slice versioned, and does it set a Swift name?
890 VersionTuple SelectedVersion;
891 SpecificInfo SelectedInfoSlice;
892 std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
893 if (SelectedVersion.empty())
894 return;
895 if (SelectedInfoSlice.SwiftName.empty())
896 return;
897
898 // Does the unversioned slice /not/ set a Swift name?
899 for (const auto &VersionAndInfoSlice : Info) {
900 if (!VersionAndInfoSlice.first.empty())
901 continue;
902 if (!VersionAndInfoSlice.second.SwiftName.empty())
903 return;
904 }
905
906 // Then explicitly call that out with a removal attribute.
907 VersionedInfoMetadata DummyFutureMetadata(SelectedVersion, SliceGroup,
908 IsActive_t::Inactive,
909 IsSubstitution_t::Replacement);
910 handleAPINotedAttribute<SwiftNameAttr>(
911 S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
912 llvm_unreachable("should not try to add an attribute here");
913 });
914}
915
916/// Processes all versions of versioned API notes.
917///
918/// Just dispatches to the various ProcessAPINotes functions in this file.
919///
920/// \param SliceGroup Which group the slices in \p Info form. Selection runs
921/// independently per group, so this has to travel with every slice.
922template <typename SpecificDecl, typename SpecificInfo>
924 Sema &S, SpecificDecl *D,
926 unsigned SliceGroup) {
927
929 maybeAttachUnversionedSwiftName(S, D, Info, SliceGroup);
930
931 unsigned Selected = Info.getSelected().value_or(Info.size());
932
933 VersionTuple Version;
934 SpecificInfo InfoSlice;
935 for (unsigned i = 0, e = Info.size(); i != e; ++i) {
936 std::tie(Version, InfoSlice) = Info[i];
937 auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
938 auto Replacement = IsSubstitution_t::Original;
939
940 // When collecting all APINotes as version-independent,
941 // capture all as inactive and defer to the client to select the
942 // right one.
944 Active = IsActive_t::Inactive;
945
946 // Record that this slice exists, independently of whether it goes on to
947 // set any key. A slice that sets nothing still wins selection for the
948 // versions it covers, and winning suppresses every other slice, so a
949 // client recomputing the selection cannot infer the slice set from the
950 // addition and removal wrappers alone.
951 D->addAttr(SwiftVersionedSliceAttr::CreateImplicit(S.Context, Version,
952 SliceGroup));
953 } else if (Active == IsActive_t::Inactive && Version.empty()) {
954 Replacement = IsSubstitution_t::Replacement;
955 Version = Info[Selected].first;
956 }
957
959 S, D, InfoSlice,
960 VersionedInfoMetadata(Version, SliceGroup, Active, Replacement));
961 }
962}
963
964static std::optional<api_notes::Context>
966 if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
967 for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
968 // Retrieve the context ID for the parent namespace of the decl.
969 std::stack<NamespaceDecl *> NamespaceStack;
970 {
971 for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
972 CurrentNamespace =
973 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
974 if (!CurrentNamespace->isInlineNamespace())
975 NamespaceStack.push(CurrentNamespace);
976 }
977 }
978 std::optional<api_notes::ContextID> NamespaceID;
979 while (!NamespaceStack.empty()) {
980 auto CurrentNamespace = NamespaceStack.top();
981 NamespaceStack.pop();
982 NamespaceID =
983 Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
984 if (!NamespaceID)
985 return std::nullopt;
986 }
987 if (NamespaceID)
988 return api_notes::Context(*NamespaceID,
990 }
991 }
992 return std::nullopt;
993}
994
995static std::optional<api_notes::Context>
997 assert(DC && "tag context must not be null");
998 for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
999 // Retrieve the context ID for the parent tag of the decl.
1000 std::stack<TagDecl *> TagStack;
1001 {
1002 for (auto CurrentTag = DC; CurrentTag;
1003 CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
1004 TagStack.push(CurrentTag);
1005 }
1006 assert(!TagStack.empty());
1007 std::optional<api_notes::Context> Ctx =
1008 UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
1009 while (!TagStack.empty()) {
1010 auto CurrentTag = TagStack.top();
1011 TagStack.pop();
1012 auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
1013 if (!CtxID)
1014 return std::nullopt;
1016 }
1017 return Ctx;
1018 }
1019 return std::nullopt;
1020}
1021
1022namespace clang {
1025
1027 return Parameters == Other.Parameters;
1028 }
1029
1031 return !(*this == Other);
1032 }
1033};
1034
1037 std::optional<APINotesParameterSelector> Desugared;
1038};
1039} // namespace clang
1040
1041static PrintingPolicy
1043 PrintingPolicy Policy(Context.getLangOpts());
1044 Policy.PrintAsCanonical = false;
1045 Policy.FullyQualifiedName = false;
1046 Policy.SuppressScope = false;
1047 Policy.UsePreferredNames = false;
1048 Policy.MSVCFormatting = false;
1049 Policy.SplitTemplateClosers = false;
1050 Policy.IncludeNewlines = false;
1051 return Policy;
1052}
1053
1054// Print the APINotes selector spelling for one parameter. The source-spelled
1055// selector is tried first. The desugared spelling is only a permissive
1056// fallback.
1058 QualType ParamType, const ASTContext &Context, const PrintingPolicy &Policy,
1059 bool Desugar) {
1060 if (Desugar)
1061 ParamType = ParamType.getDesugaredType(Context);
1062
1063 ParamType.removeLocalConst();
1064 ParamType.removeLocalVolatile();
1065 ParamType = ParamType.stripNullability(Context);
1066
1067 return ParamType.getAsString(Policy);
1068}
1069
1070static std::optional<APINotesParameterSelectorCandidates>
1072 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
1073 if (!FPT)
1074 return std::nullopt;
1075
1077 APINotesParameterSelector Desugared;
1078 Candidates.Source.Parameters.reserve(FPT->getNumParams());
1079 Desugared.Parameters.reserve(FPT->getNumParams());
1080
1081 const PrintingPolicy Policy =
1083 for (QualType ParamType : FPT->param_types()) {
1084 Candidates.Source.Parameters.push_back(
1085 getAPINotesParameterSelectorSpelling(ParamType, S.Context, Policy,
1086 /*Desugar=*/false));
1088 ParamType, S.Context, Policy, /*Desugar=*/true));
1089 }
1090
1091 if (Candidates.Source != Desugared)
1092 Candidates.Desugared = std::move(Desugared);
1093
1094 return Candidates;
1095}
1096
1099 api_notes::APINotesReader &Reader) {
1100 auto [StateIt, Inserted] = Readers.try_emplace(&Reader);
1101 APINotesSelectorDiagnosticReaderState &State = StateIt->second;
1102 if (!Inserted)
1103 return State;
1104
1107 State.addSelectors(Selectors);
1108 return State;
1109}
1110
1115 std::make_unique<APINotesSelectorDiagnosticState>();
1116
1117 return S.APINotesSelectorDiagnostics->getOrCreateReaderState(*Reader);
1118}
1119
1121 llvm::function_ref<std::optional<api_notes::APINotesFunctionSelectorKey>(
1123 GetSelectorKey,
1124 const APINotesParameterSelectorCandidates &Candidates) {
1125 if (auto Key = GetSelectorKey(Candidates.Source.Parameters))
1126 markUsed(*Key);
1127 if (Candidates.Desugared) {
1128 if (auto Key = GetSelectorKey(Candidates.Desugared->Parameters))
1129 markUsed(*Key);
1130 }
1131}
1132
1133/// Apply the first exact selector entry found. This preserves source-spelling
1134/// precedence over the desugared fallback and avoids applying multiple exact
1135/// entries for the same declaration.
1136///
1137/// \param SliceGroup Which group the slices from \p LookupExact form. This
1138/// lookup runs its own version selection, so it is a group distinct from the
1139/// broad lookup beside it even though both read the same reader.
1140template <typename SpecificInfo, typename SpecificDecl>
1142 Sema &S, SpecificDecl *D,
1143 const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
1146 LookupExact,
1147 unsigned SliceGroup) {
1148 auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
1149 auto Info = LookupExact(Selector.Parameters);
1150 if (Info.size() == 0)
1151 return false;
1152
1153 ProcessVersionedAPINotes(S, D, Info, SliceGroup);
1154 return true;
1155 };
1156
1157 if (ProcessSelector(ParameterSelectorCandidates.Source))
1158 return;
1159
1160 if (ParameterSelectorCandidates.Desugared)
1161 ProcessSelector(*ParameterSelectorCandidates.Desugared);
1162}
1163
1164/// Process API notes that are associated with this declaration, mapping them
1165/// to attributes as appropriate.
1167 if (!D)
1168 return;
1169 if (!APINotes.hasAPINotes())
1170 return;
1171 auto Readers = APINotes.findAPINotes(D->getLocation());
1172 if (Readers.empty())
1173 return;
1174 // Each lookup below is its own slice group, numbered in the order the
1175 // lookups run, which is the order Sema applies them in. A consumer needs that
1176 // order to resolve two groups whose winners set the same key.
1177 unsigned NextSliceGroup = 0;
1178
1179 auto *DC = D->getDeclContext();
1180 // Globals.
1181 if (DC->isFileContext() || DC->isNamespace() ||
1182 DC->getDeclKind() == Decl::LinkageSpec) {
1183 std::optional<api_notes::Context> APINotesContext =
1185 // Global variables.
1186 if (auto VD = dyn_cast<VarDecl>(D)) {
1187 for (auto Reader : Readers) {
1188 auto Info =
1189 Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
1190 ProcessVersionedAPINotes(*this, VD, Info, NextSliceGroup++);
1191 }
1192
1193 return;
1194 }
1195
1196 // Global functions.
1197 if (auto FD = dyn_cast<FunctionDecl>(D)) {
1198 if (FD->getDeclName().isIdentifier()) {
1199 auto ParameterSelectorCandidates =
1201
1202 for (auto Reader : Readers) {
1203 auto Info =
1204 Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
1205 ProcessVersionedAPINotes(*this, FD, Info, NextSliceGroup++);
1206
1207 if (ParameterSelectorCandidates)
1209 *this, FD, *ParameterSelectorCandidates,
1210 [&](ArrayRef<std::string> Parameters) {
1211 return Reader->lookupGlobalFunction(FD->getName(), Parameters,
1212 APINotesContext);
1213 },
1214 NextSliceGroup++);
1215
1216 if (ParameterSelectorCandidates) {
1217 auto &DiagnosticState =
1219 if (auto BroadKey = Reader->getGlobalFunctionSelectorKey(
1220 FD->getName(), APINotesContext))
1221 DiagnosticState.noteSeenDeclaration(*BroadKey, FD->getName(),
1222 FD->getLocation());
1223 DiagnosticState.markCandidatesUsed(
1224 [&](ArrayRef<std::string> Parameters) {
1225 return Reader->getGlobalFunctionSelectorKey(
1226 FD->getName(), Parameters, APINotesContext);
1227 },
1228 *ParameterSelectorCandidates);
1229 }
1230 }
1231 }
1232
1233 return;
1234 }
1235
1236 // Objective-C classes.
1237 if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
1238 for (auto Reader : Readers) {
1239 auto Info = Reader->lookupObjCClassInfo(Class->getName());
1240 ProcessVersionedAPINotes(*this, Class, Info, NextSliceGroup++);
1241 }
1242
1243 return;
1244 }
1245
1246 // Objective-C protocols.
1247 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
1248 for (auto Reader : Readers) {
1249 auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
1250 ProcessVersionedAPINotes(*this, Protocol, Info, NextSliceGroup++);
1251 }
1252
1253 return;
1254 }
1255
1256 // Tags
1257 if (auto Tag = dyn_cast<TagDecl>(D)) {
1258 // Determine the name of the entity to search for. If this is an
1259 // anonymous tag that gets its linked name from a typedef, look for the
1260 // typedef name. This allows tag-specific information to be added
1261 // to the declaration.
1262 std::string LookupName;
1263 if (auto typedefName = Tag->getTypedefNameForAnonDecl())
1264 LookupName = typedefName->getName().str();
1265 else
1266 LookupName = Tag->getName().str();
1267
1268 // Use the source location to discern if this Tag is an OPTIONS macro.
1269 // For now we would like to limit this trick of looking up the APINote tag
1270 // using the EnumDecl's QualType in the case where the enum is anonymous.
1271 // This is only being used to support APINotes lookup for C++
1272 // NS/CF_OPTIONS when C++-Interop is enabled.
1273 std::string MacroName =
1274 LookupName.empty() && Tag->getOuterLocStart().isMacroID()
1276 Tag->getOuterLocStart(),
1277 Tag->getASTContext().getSourceManager(), LangOpts)
1278 .str()
1279 : "";
1280
1281 if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
1282 (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
1283 MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
1284
1285 clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
1287 T.split(), getASTContext().getPrintingPolicy());
1288 }
1289
1290 for (auto Reader : Readers) {
1291 if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
1292 APINotesContext = UnwindTagContext(ParentTag, APINotes);
1293 auto Info = Reader->lookupTag(LookupName, APINotesContext);
1294 ProcessVersionedAPINotes(*this, Tag, Info, NextSliceGroup++);
1295 }
1296
1297 return;
1298 }
1299
1300 // Typedefs
1301 if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
1302 for (auto Reader : Readers) {
1303 auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
1304 ProcessVersionedAPINotes(*this, Typedef, Info, NextSliceGroup++);
1305 }
1306
1307 return;
1308 }
1309 }
1310
1311 // Enumerators.
1312 if (DC->getRedeclContext()->isFileContext() ||
1313 DC->getRedeclContext()->isExternCContext()) {
1314 if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1315 for (auto Reader : Readers) {
1316 auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1317 ProcessVersionedAPINotes(*this, EnumConstant, Info, NextSliceGroup++);
1318 }
1319
1320 return;
1321 }
1322 }
1323
1324 if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1325 // Location function that looks up an Objective-C context.
1326 auto GetContext = [&](api_notes::APINotesReader *Reader)
1327 -> std::optional<api_notes::ContextID> {
1328 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1329 if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1330 return *Found;
1331
1332 return std::nullopt;
1333 }
1334
1335 if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1336 if (auto Cat = Impl->getCategoryDecl())
1337 ObjCContainer = Cat->getClassInterface();
1338 else
1339 return std::nullopt;
1340 }
1341
1342 if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1343 if (Category->getClassInterface())
1344 ObjCContainer = Category->getClassInterface();
1345 else
1346 return std::nullopt;
1347 }
1348
1349 if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1350 if (Impl->getClassInterface())
1351 ObjCContainer = Impl->getClassInterface();
1352 else
1353 return std::nullopt;
1354 }
1355
1356 if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1357 if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1358 return *Found;
1359
1360 return std::nullopt;
1361 }
1362
1363 return std::nullopt;
1364 };
1365
1366 // Objective-C methods.
1367 if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1368 for (auto Reader : Readers) {
1369 if (auto Context = GetContext(Reader)) {
1370 // Map the selector.
1371 Selector Sel = Method->getSelector();
1372 SmallVector<StringRef, 2> SelPieces;
1373 if (Sel.isUnarySelector()) {
1374 SelPieces.push_back(Sel.getNameForSlot(0));
1375 } else {
1376 for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1377 SelPieces.push_back(Sel.getNameForSlot(i));
1378 }
1379
1380 api_notes::ObjCSelectorRef SelectorRef;
1381 SelectorRef.NumArgs = Sel.getNumArgs();
1382 SelectorRef.Identifiers = SelPieces;
1383
1384 auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1385 Method->isInstanceMethod());
1386 ProcessVersionedAPINotes(*this, Method, Info, NextSliceGroup++);
1387 }
1388 }
1389 }
1390
1391 // Objective-C properties.
1392 if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1393 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1394 if (auto Context = GetContext(Reader)) {
1395 bool isInstanceProperty =
1396 (Property->getPropertyAttributesAsWritten() &
1398 auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1399 isInstanceProperty);
1400 ProcessVersionedAPINotes(*this, Property, Info, NextSliceGroup++);
1401 }
1402 }
1403
1404 return;
1405 }
1406 }
1407
1408 if (auto TagContext = dyn_cast<TagDecl>(DC)) {
1409 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1410 if (!isa<CXXConstructorDecl>(CXXMethod) &&
1411 !isa<CXXDestructorDecl>(CXXMethod) &&
1412 !isa<CXXConversionDecl>(CXXMethod)) {
1413 auto ParameterSelectorCandidates =
1415 for (auto Reader : Readers) {
1416 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1417 std::string MethodName;
1418 if (CXXMethod->isOverloadedOperator())
1419 MethodName =
1420 std::string("operator") +
1421 getOperatorSpelling(CXXMethod->getOverloadedOperator());
1422 else
1423 MethodName = CXXMethod->getName();
1424
1425 auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
1426 ProcessVersionedAPINotes(*this, CXXMethod, Info, NextSliceGroup++);
1427
1428 if (ParameterSelectorCandidates)
1430 *this, CXXMethod, *ParameterSelectorCandidates,
1431 [&](ArrayRef<std::string> Parameters) {
1432 return Reader->lookupCXXMethod(Context->id, MethodName,
1433 Parameters);
1434 },
1435 NextSliceGroup++);
1436
1437 if (ParameterSelectorCandidates) {
1438 auto &DiagnosticState =
1440 if (auto BroadKey =
1441 Reader->getCXXMethodSelectorKey(Context->id, MethodName))
1442 DiagnosticState.noteSeenDeclaration(*BroadKey, MethodName,
1443 CXXMethod->getLocation());
1444 DiagnosticState.markCandidatesUsed(
1445 [&](ArrayRef<std::string> Parameters) {
1446 return Reader->getCXXMethodSelectorKey(
1447 Context->id, MethodName, Parameters);
1448 },
1449 *ParameterSelectorCandidates);
1450 }
1451 }
1452 }
1453 }
1454 }
1455
1456 if (auto Field = dyn_cast<FieldDecl>(D)) {
1457 if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1458 for (auto Reader : Readers) {
1459 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1460 auto Info = Reader->lookupField(Context->id, Field->getName());
1461 ProcessVersionedAPINotes(*this, Field, Info, NextSliceGroup++);
1462 }
1463 }
1464 }
1465 }
1466
1467 if (auto Tag = dyn_cast<TagDecl>(D)) {
1468 for (auto Reader : Readers) {
1469 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1470 auto Info = Reader->lookupTag(Tag->getName(), Context);
1471 ProcessVersionedAPINotes(*this, Tag, Info, NextSliceGroup++);
1472 }
1473 }
1474 }
1475 }
1476}
1477
1479 Sema &S, api_notes::APINotesReader &Reader) const {
1480 for (const auto &Selector : SelectorUsed) {
1481 if (Selector.second)
1482 continue;
1483
1484 auto SeenName =
1485 SeenNames.find(Selector.first.getWithoutParameterSelector());
1486 if (SeenName == SeenNames.end())
1487 continue;
1488
1489 std::optional<SmallVector<std::string, 4>> ParameterSpellings =
1491 if (!ParameterSpellings)
1492 continue;
1493
1494 S.Diag(SeenName->second.Loc, diag::warn_apinotes_message)
1495 << (llvm::Twine("API notes entry for '") + SeenName->second.Name +
1496 "' has unmatched Where.Parameters " +
1497 api_notes::formatAPINotesParameterSelector(*ParameterSpellings))
1498 .str();
1499 }
1500}
1501
1503 for (const auto &ReaderSelectors : Readers)
1504 ReaderSelectors.second.diagnoseUnused(S, *ReaderSelectors.first);
1505}
1506
1509 return;
1510
1511 if (!Diags.isIgnored(diag::warn_apinotes_message, SourceLocation()))
1512 APINotesSelectorDiagnostics->diagnoseUnused(*this);
1514}
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 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 addSwiftAttrIfAbsent(Sema &S, Decl *D, StringRef Attribute)
Add a 'swift_attr' unless D already carries that exact annotation.
static bool checkAPINotesReplacementType(Sema &S, SourceLocation Loc, QualType OrigType, QualType ReplacementType)
Check that the replacement type provided by API notes is reasonable.
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 ProcessVersionedAPINotes(Sema &S, SpecificDecl *D, const api_notes::APINotesReader::VersionedInfo< SpecificInfo > Info, unsigned SliceGroup)
Processes all versions of versioned API notes.
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, unsigned SliceGroup)
If we're applying API notes with an active, non-default version, and the versioned API notes have a S...
static APINotesSelectorDiagnosticReaderState & getAPINotesSelectorDiagnosticState(Sema &S, api_notes::APINotesReader *Reader)
static bool isIndirectPointerType(QualType Type)
Determine whether this is a multi-level pointer type.
static void processExactAPINotes(Sema &S, SpecificDecl *D, const APINotesParameterSelectorCandidates &ParameterSelectorCandidates, llvm::function_ref< api_notes::APINotesReader::VersionedInfo< SpecificInfo >(ArrayRef< std::string >)> LookupExact, unsigned SliceGroup)
Apply the first exact selector entry found.
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:245
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:856
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:930
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:635
ParsedAttr * create(IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope, ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc=SourceLocation())
Definition ParsedAttr.h:748
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:2150
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
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:567
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:3562
Represents a member of a struct/union/class.
Definition Decl.h:3299
Represents a function declaration or definition.
Definition Decl.h:2059
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2932
QualType getReturnType() const
Definition Decl.h:2980
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2905
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3873
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4994
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4612
ExtInfo getExtInfo() const
Definition TypeBase.h:4968
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:954
Represents an ObjC class declaration.
Definition DeclObjC.h:1160
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
unsigned param_size() const
Definition DeclObjC.h:350
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo)
Definition DeclObjC.h:347
param_const_iterator param_begin() const
Definition DeclObjC.h:357
void setReturnType(QualType T)
Definition DeclObjC.h:333
QualType getReturnType() const
Definition DeclObjC.h:332
ObjCInterfaceDecl * getClassInterface()
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:734
Represents a parameter to a function.
Definition Decl.h:1820
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
void removeLocalVolatile()
Definition TypeBase.h:8562
std::string getAsString() const
void * getAsOpaquePtr() const
Definition TypeBase.h:985
void removeLocalConst()
Definition TypeBase.h:8554
QualType stripNullability(const ASTContext &ctx) const
Strip nullability attributes from the given type.
Definition Type.cpp:1833
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:863
ASTContext & Context
Definition Sema.h:1332
SemaObjC & ObjC()
Definition Sema.h:1544
bool captureSwiftVersionIndependentAPINotes()
Whether APINotes should be gathered for all applicable Swift language versions, without being applied...
Definition Sema.h:1699
ASTContext & getASTContext() const
Definition Sema.h:935
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1236
api_notes::APINotesManager APINotes
Definition Sema.h:1336
const LangOptions & LangOpts
Definition Sema.h:1330
SemaSwift & Swift()
Definition Sema.h:1589
std::function< TypeResult(StringRef, StringRef, SourceLocation)> ParseTypeFromStringCallback
Callback to the parser to parse a type expressed as a string.
Definition Sema.h:1387
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:4988
DiagnosticsEngine & Diags
Definition Sema.h:1334
std::unique_ptr< APINotesSelectorDiagnosticState > APINotesSelectorDiagnostics
Definition Sema.h:1338
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.
void DiagnoseUnusedAPINotesSelectors()
Diagnose exact API notes selectors that were not matched by any declaration processed in this transla...
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:3856
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:1879
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9366
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isMemberPointerType() const
Definition TypeBase.h:8764
bool isObjCObjectPointerType() const
Definition TypeBase.h:8862
bool isAnyPointerType() const
Definition TypeBase.h:8691
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3701
void setType(QualType newType)
Definition Decl.h:725
QualType getType() const
Definition Decl.h:724
QualType getType() const
Definition Value.cpp:238
Represents a variable declaration or definition.
Definition Decl.h:933
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.
std::optional< llvm::SmallVector< std::string, 4 > > getParameterSelectorSpellingsForDiagnostics(const APINotesFunctionSelectorKey &Key)
Reconstruct parameter selector strings for a stored exact selector key.
void collectExactFunctionParameterSelectors(llvm::SmallVectorImpl< APINotesFunctionSelectorKey > &Selectors)
Collect exact parameter selector keys stored by this reader.
Describes API notes data for a C++ method.
Definition Types.h:821
std::optional< ParamInfo > This
Definition Types.h:825
Describes API notes data for any entity.
Definition Types.h:72
unsigned UnavailableInSwift
Whether this entity is marked unavailable in Swift.
Definition Types.h:83
unsigned Unavailable
Whether this entity is marked unavailable.
Definition Types.h:79
std::string UnavailableMsg
Message to use when this entity is unavailable.
Definition Types.h:75
std::optional< SwiftSafetyKind > getSwiftSafety() const
Definition Types.h:118
std::optional< bool > isSwiftPrivate() const
Definition Types.h:108
Describes API notes for types.
Definition Types.h:177
std::optional< std::string > getSwiftConformance() const
Definition Types.h:213
const std::optional< std::string > & getSwiftBridge() const
Definition Types.h:192
const std::optional< std::string > & getNSErrorDomain() const
Definition Types.h:200
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
Definition Types.h:253
std::optional< bool > getSwiftImportAsNonGeneric() const
Definition Types.h:297
std::optional< bool > getSwiftObjCMembers() const
Definition Types.h:307
Describes API notes data for an enumerator.
Definition Types.h:839
Describes API notes data for a C/C++ record field.
Definition Types.h:815
API notes for a function or method.
Definition Types.h:633
std::string SwiftReturnOwnership
Ownership convention for return value.
Definition Types.h:670
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:717
std::vector< ParamInfo > Params
The function parameters.
Definition Types.h:673
NullabilityKind getReturnTypeInfo() const
Definition Types.h:715
NullabilityKind getParamTypeInfo(unsigned index) const
Definition Types.h:711
std::string ResultType
The result type of this function, as a C type.
Definition Types.h:667
unsigned UnsafeBufferUsage
Whether the function has the [[clang::unsafe_buffer_usage]] attribute.
Definition Types.h:657
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Definition Types.h:647
Describes API notes data for a global function.
Definition Types.h:809
Describes API notes data for a global variable.
Definition Types.h:803
Describes API notes data for an Objective-C method.
Definition Types.h:762
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition Types.h:766
Describes API notes data for an Objective-C property.
Definition Types.h:475
std::optional< bool > getSwiftImportAsAccessors() const
Definition Types.h:485
Describes a function or method parameter.
Definition Types.h:533
std::optional< bool > isNoEscape() const
Definition Types.h:563
std::optional< bool > isLifetimebound() const
Definition Types.h:571
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:580
Describes API notes data for a tag.
Definition Types.h:845
std::optional< std::string > SwiftReleaseOp
Definition Types.h:864
std::optional< std::string > SwiftRetainOp
Definition Types.h:863
std::optional< std::string > SwiftImportAs
Definition Types.h:862
std::optional< std::string > SwiftDefaultOwnership
Definition Types.h:866
std::optional< EnumExtensibilityKind > EnumExtensibility
Definition Types.h:868
std::optional< std::string > SwiftDestroyOp
Definition Types.h:865
std::optional< bool > isFlagEnum() const
Definition Types.h:875
std::optional< bool > isSwiftCopyable() const
Definition Types.h:885
std::optional< bool > isSwiftEscapable() const
Definition Types.h:894
Describes API notes data for a typedef.
Definition Types.h:956
std::optional< SwiftNewTypeKind > SwiftWrapper
Definition Types.h:958
API notes for a variable/property.
Definition Types.h:426
const std::string & getType() const
Definition Types.h:446
NullabilityKindOrNone getNullability() const
Definition Types.h:438
SwiftNewTypeKind
The kind of a swift_wrapper/swift_newtype.
Definition Types.h:61
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
Definition Types.h:54
std::string formatAPINotesParameterSelector(RangeT &&Parameters)
Definition Types.h:34
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
NullabilityKind
Describes the nullability of a particular type.
Definition Specifiers.h:350
@ Nullable
Values of this type can be null.
Definition Specifiers.h:354
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
Definition Specifiers.h:359
@ NonNull
Values of this type can never be null.
Definition Specifiers.h:352
@ 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:6025
@ Other
Other implicit parameter.
Definition Decl.h:1775
std::optional< APINotesParameterSelector > Desugared
SmallVector< std::string, 4 > Parameters
bool operator==(const APINotesParameterSelector &Other) const
bool operator!=(const APINotesParameterSelector &Other) const
Tracks exact Where.Parameters selectors from one API notes reader.
void markUsed(const api_notes::APINotesFunctionSelectorKey &Key)
void diagnoseUnused(Sema &S, api_notes::APINotesReader &Reader) const
llvm::DenseMap< api_notes::APINotesFunctionSelectorKey, bool > SelectorUsed
Exact Where.Parameters selector keys stored by API notes.
void markCandidatesUsed(llvm::function_ref< std::optional< api_notes::APINotesFunctionSelectorKey >(llvm::ArrayRef< std::string >)> GetSelectorKey, const APINotesParameterSelectorCandidates &Candidates)
llvm::DenseMap< api_notes::APINotesFunctionSelectorKey, APINotesSelectorDiagnosticName > SeenNames
Maps broad/name-only keys to a declaration location/name used for diagnostics.
APINotesSelectorDiagnosticReaderState & getOrCreateReaderState(api_notes::APINotesReader &Reader)
llvm::DenseMap< api_notes::APINotesReader *, APINotesSelectorDiagnosticReaderState > Readers
Describes how types, statements, expressions, and declarations should be printed.
unsigned SplitTemplateClosers
Whether nested templates must be closed like 'a<b<c> >' rather than 'a<b<c>>'.
unsigned SuppressScope
Suppresses printing of scope specifiers.
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition Types.h:1092
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition Types.h:1094