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