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
250static void ProcessAPINotes(Sema &S, Decl *D,
251 const api_notes::CommonEntityInfo &Info,
252 VersionedInfoMetadata Metadata) {
253 // Availability
254 if (Info.Unavailable) {
255 handleAPINotedAttribute<UnavailableAttr>(S, D, true, Metadata, [&] {
256 return new (S.Context)
257 UnavailableAttr(S.Context, getPlaceholderAttrInfo(),
259 });
260 }
261
262 if (Info.UnavailableInSwift) {
263 handleAPINotedAttribute<AvailabilityAttr>(
264 S, D, true, Metadata,
265 [&] {
266 return new (S.Context) AvailabilityAttr(
268 &S.Context.Idents.get("swift"), VersionTuple(), VersionTuple(),
269 VersionTuple(),
270 /*Unavailable=*/true,
272 /*Strict=*/false,
273 /*Replacement=*/StringRef(),
274 /*Priority=*/Sema::AP_Explicit,
275 /*Environment=*/nullptr);
276 },
277 [](const Decl *D) {
278 return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
279 if (const auto *AA = dyn_cast<AvailabilityAttr>(next))
280 if (const auto *II = AA->getPlatform())
281 return II->isStr("swift");
282 return false;
283 });
284 });
285 }
286
287 // swift_private
288 if (auto SwiftPrivate = Info.isSwiftPrivate()) {
289 handleAPINotedAttribute<SwiftPrivateAttr>(
290 S, D, *SwiftPrivate, Metadata, [&] {
291 return new (S.Context)
292 SwiftPrivateAttr(S.Context, getPlaceholderAttrInfo());
293 });
294 }
295
296 // swift_safety
297 if (auto SafetyKind = Info.getSwiftSafety()) {
299 handleAPINotedAttribute<SwiftAttrAttr>(
300 S, D, Addition, Metadata,
301 [&] {
302 return SwiftAttrAttr::Create(
304 ? "safe"
305 : "unsafe");
306 },
307 [](const Decl *D) {
308 return llvm::find_if(D->attrs(), [](const Attr *attr) {
309 if (const auto *swiftAttr = dyn_cast<SwiftAttrAttr>(attr)) {
310 if (swiftAttr->getAttribute() == "safe" ||
311 swiftAttr->getAttribute() == "unsafe")
312 return true;
313 }
314 return false;
315 });
316 });
317 }
318
319 // swift_name
320 if (!Info.SwiftName.empty()) {
321 handleAPINotedAttribute<SwiftNameAttr>(
322 S, D, true, Metadata, [&]() -> SwiftNameAttr * {
323 AttributeFactory AF{};
324 AttributePool AP{AF};
325 auto &C = S.getASTContext();
326 ParsedAttr *SNA = AP.create(
327 &C.Idents.get("swift_name"), SourceRange(), AttributeScopeInfo(),
328 nullptr, nullptr, nullptr, ParsedAttr::Form::GNU());
329
330 if (!S.Swift().DiagnoseName(D, Info.SwiftName, D->getLocation(), *SNA,
331 /*IsAsync=*/false))
332 return nullptr;
333
334 return new (S.Context)
335 SwiftNameAttr(S.Context, getPlaceholderAttrInfo(),
336 ASTAllocateString(S.Context, Info.SwiftName));
337 });
338 }
339}
340
341static void ProcessAPINotes(Sema &S, Decl *D,
342 const api_notes::CommonTypeInfo &Info,
343 VersionedInfoMetadata Metadata) {
344 // swift_bridge
345 if (auto SwiftBridge = Info.getSwiftBridge()) {
346 handleAPINotedAttribute<SwiftBridgeAttr>(
347 S, D, !SwiftBridge->empty(), Metadata, [&] {
348 return new (S.Context)
349 SwiftBridgeAttr(S.Context, getPlaceholderAttrInfo(),
350 ASTAllocateString(S.Context, *SwiftBridge));
351 });
352 }
353
354 // ns_error_domain
355 if (auto NSErrorDomain = Info.getNSErrorDomain()) {
356 handleAPINotedAttribute<NSErrorDomainAttr>(
357 S, D, !NSErrorDomain->empty(), Metadata, [&] {
358 return new (S.Context)
359 NSErrorDomainAttr(S.Context, getPlaceholderAttrInfo(),
360 &S.Context.Idents.get(*NSErrorDomain));
361 });
362 }
363
364 if (auto ConformsTo = Info.getSwiftConformance())
365 D->addAttr(
366 SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
367
368 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
369 Metadata);
370}
371
372/// Check that the replacement type provided by API notes is reasonable.
373///
374/// This is a very weak form of ABI check.
376 QualType OrigType,
377 QualType ReplacementType) {
378 if (S.Context.getTypeSize(OrigType) !=
379 S.Context.getTypeSize(ReplacementType)) {
380 S.Diag(Loc, diag::err_incompatible_replacement_type)
381 << ReplacementType << OrigType;
382 return true;
383 }
384
385 return false;
386}
387
388void Sema::ApplyAPINotesType(Decl *D, StringRef TypeString) {
389 if (!TypeString.empty() && ParseTypeFromStringCallback) {
390 auto ParsedType = ParseTypeFromStringCallback(TypeString, "<API Notes>",
391 D->getLocation());
392 if (ParsedType.isUsable()) {
394 auto TypeInfo = Context.getTrivialTypeSourceInfo(Type, D->getLocation());
395 if (auto Var = dyn_cast<VarDecl>(D)) {
396 // Make adjustments to parameter types.
397 if (isa<ParmVarDecl>(Var)) {
399 Type, D->getLocation(), TypeInfo);
400 Type = Context.getAdjustedParameterType(Type);
401 }
402
403 if (!checkAPINotesReplacementType(*this, Var->getLocation(),
404 Var->getType(), Type)) {
405 Var->setType(Type);
406 Var->setTypeSourceInfo(TypeInfo);
407 }
408 } else if (auto property = dyn_cast<ObjCPropertyDecl>(D)) {
409 if (!checkAPINotesReplacementType(*this, property->getLocation(),
410 property->getType(), Type)) {
411 property->setType(Type, TypeInfo);
412 }
413 } else if (auto field = dyn_cast<FieldDecl>(D)) {
414 if (!checkAPINotesReplacementType(*this, field->getLocation(),
415 field->getType(), Type)) {
416 field->setType(Type);
417 field->setTypeSourceInfo(TypeInfo);
418 }
419 } else {
420 llvm_unreachable("API notes allowed a type on an unknown declaration");
421 }
422 }
423 }
424}
425
427 auto GetModified =
428 [&](class Decl *D, QualType QT,
429 NullabilityKind Nullability) -> std::optional<QualType> {
430 QualType Original = QT;
433 /*OverrideExisting=*/true);
434 return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
435 : std::nullopt;
436 };
437
438 if (auto Function = dyn_cast<FunctionDecl>(D)) {
439 if (auto Modified =
440 GetModified(D, Function->getReturnType(), Nullability)) {
441 const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
442 if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
443 Function->setType(Context.getFunctionType(
444 *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
445 else
446 Function->setType(
447 Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
448 }
449 } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
450 if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
451 Method->setReturnType(*Modified);
452
453 // Make it a context-sensitive keyword if we can.
454 if (!isIndirectPointerType(*Modified))
455 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
456 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
457 }
458 } else if (auto Value = dyn_cast<ValueDecl>(D)) {
459 if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
460 Value->setType(*Modified);
461
462 // Make it a context-sensitive keyword if we can.
463 if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
464 if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
465 Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
466 Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
467 }
468 }
469 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
470 if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
471 Property->setType(*Modified, Property->getTypeSourceInfo());
472
473 // Make it a property attribute if we can.
474 if (!isIndirectPointerType(*Modified))
475 Property->setPropertyAttributes(
477 }
478 }
479}
480
481/// Process API notes for a variable or property.
482static void ProcessAPINotes(Sema &S, Decl *D,
483 const api_notes::VariableInfo &Info,
484 VersionedInfoMetadata Metadata) {
485 // Type override.
486 applyAPINotesType(S, D, Info.getType(), Metadata);
487
488 // Nullability.
489 if (auto Nullability = Info.getNullability())
490 applyNullability(S, D, *Nullability, Metadata);
491
492 // Handle common entity information.
493 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
494 Metadata);
495}
496
497/// Process API notes for a parameter.
499 const api_notes::ParamInfo &Info,
500 VersionedInfoMetadata Metadata) {
501 // noescape
502 if (auto NoEscape = Info.isNoEscape())
503 handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
504 return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
505 });
506
507 if (auto Lifetimebound = Info.isLifetimebound())
508 handleAPINotedAttribute<LifetimeBoundAttr>(
509 S, D, *Lifetimebound, Metadata, [&] {
510 return new (S.Context)
511 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
512 });
513
514 // Retain count convention
517
518 // Handle common entity information.
519 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
520 Metadata);
521}
522
523/// Process API notes for a global variable.
524static void ProcessAPINotes(Sema &S, VarDecl *D,
526 VersionedInfoMetadata metadata) {
527 // Handle common entity information.
528 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
529 metadata);
530}
531
532/// Process API notes for a C field.
533static void ProcessAPINotes(Sema &S, FieldDecl *D,
534 const api_notes::FieldInfo &Info,
535 VersionedInfoMetadata metadata) {
536 // Handle common entity information.
537 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
538 metadata);
539}
540
541/// Process API notes for an Objective-C property.
543 const api_notes::ObjCPropertyInfo &Info,
544 VersionedInfoMetadata Metadata) {
545 // Handle common entity information.
546 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
547 Metadata);
548
549 if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
550 handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
551 S, D, *AsAccessors, Metadata, [&] {
552 return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
554 });
555 }
556}
557
558namespace {
559typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
560}
561
562/// Process API notes for a function or method.
563static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
564 const api_notes::FunctionInfo &Info,
565 VersionedInfoMetadata Metadata) {
566 // Find the declaration itself.
567 FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
568 Decl *D = FD;
569 ObjCMethodDecl *MD = nullptr;
570 if (!D) {
571 MD = cast<ObjCMethodDecl *>(AnyFunc);
572 D = MD;
573 }
574
575 assert((FD || MD) && "Expecting Function or ObjCMethod");
576
577 // Nullability of return type.
578 if (Info.NullabilityAudited)
579 applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
580
581 // Add [[clang::unsafe_buffer_usage]]
582 if (Info.UnsafeBufferUsage && !D->getAttr<UnsafeBufferUsageAttr>()) {
583 handleAPINotedAttribute<UnsafeBufferUsageAttr>(S, D, true, Metadata, [&]() {
584 return UnsafeBufferUsageAttr::Create(S.getASTContext(),
586 });
587 }
588
589 // Parameters.
590 unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
591
592 bool AnyTypeChanged = false;
593 for (unsigned I = 0; I != NumParams; ++I) {
594 ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
595 QualType ParamTypeBefore = Param->getType();
596
597 if (I < Info.Params.size())
598 ProcessAPINotes(S, Param, Info.Params[I], Metadata);
599
600 // Nullability.
601 if (Info.NullabilityAudited)
602 applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
603
604 if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
605 AnyTypeChanged = true;
606 }
607
608 // returns_(un)retained
609 if (!Info.SwiftReturnOwnership.empty())
610 D->addAttr(SwiftAttrAttr::Create(S.Context,
611 "returns_" + Info.SwiftReturnOwnership));
612
613 // Result type override.
614 QualType OverriddenResultType;
615 if (Metadata.IsActive && !Info.ResultType.empty() &&
618 Info.ResultType, "<API Notes>", D->getLocation());
619 if (ParsedType.isUsable()) {
620 QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());
621
622 if (MD) {
624 MD->getReturnType(), ResultType)) {
625 auto ResultTypeInfo =
626 S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
627 MD->setReturnType(ResultType);
628 MD->setReturnTypeSourceInfo(ResultTypeInfo);
629 }
631 S, FD->getLocation(), FD->getReturnType(), ResultType)) {
632 OverriddenResultType = ResultType;
633 AnyTypeChanged = true;
634 }
635 }
636 }
637
638 // If the result type or any of the parameter types changed for a function
639 // declaration, we have to rebuild the type.
640 if (FD && AnyTypeChanged) {
641 if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
642 if (OverriddenResultType.isNull())
643 OverriddenResultType = fnProtoType->getReturnType();
644
645 SmallVector<QualType, 4> ParamTypes;
646 for (auto Param : FD->parameters())
647 ParamTypes.push_back(Param->getType());
648
649 FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
650 fnProtoType->getExtProtoInfo()));
651 } else if (!OverriddenResultType.isNull()) {
652 const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
654 OverriddenResultType, FnNoProtoType->getExtInfo()));
655 }
656 }
657
658 // Retain count convention
661
662 // Handle common entity information.
663 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
664 Metadata);
665}
666
667/// Process API notes for a C++ method.
668static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
669 const api_notes::CXXMethodInfo &Info,
670 VersionedInfoMetadata Metadata) {
671 if (Info.This && Info.This->isLifetimebound() &&
673 auto MethodType = Method->getType();
674 auto *attr = ::new (S.Context)
675 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
676 QualType AttributedType =
677 S.Context.getAttributedType(attr, MethodType, MethodType);
678 TypeLocBuilder TLB;
679 TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
680 AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
681 TyLoc.setAttr(attr);
682 Method->setType(AttributedType);
683 Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
684 }
685
686 ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
687}
688
689/// Process API notes for a global function.
692 VersionedInfoMetadata Metadata) {
693 // Handle common function information.
694 ProcessAPINotes(S, FunctionOrMethod(D),
695 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
696}
697
698/// Process API notes for an enumerator.
700 const api_notes::EnumConstantInfo &Info,
701 VersionedInfoMetadata Metadata) {
702 // Handle common information.
703 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
704 Metadata);
705}
706
707/// Process API notes for an Objective-C method.
709 const api_notes::ObjCMethodInfo &Info,
710 VersionedInfoMetadata Metadata) {
711 // Designated initializers.
712 if (Info.DesignatedInit) {
713 handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
714 S, D, true, Metadata, [&] {
715 if (ObjCInterfaceDecl *IFace = D->getClassInterface())
716 IFace->setHasDesignatedInitializers();
717
718 return new (S.Context) ObjCDesignatedInitializerAttr(
720 });
721 }
722
723 // Handle common function information.
724 ProcessAPINotes(S, FunctionOrMethod(D),
725 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
726}
727
728static void addSwiftAttrIfAbsent(Sema &S, Decl *D, StringRef Attribute) {
729 for (const auto *A : D->specific_attrs<SwiftAttrAttr>())
730 if (A->getAttribute() == Attribute)
731 return;
732
733 D->addAttr(SwiftAttrAttr::Create(S.Context, Attribute));
734}
735
736/// Process API notes for a tag.
737static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
738 VersionedInfoMetadata Metadata) {
739 if (auto ImportAs = Info.SwiftImportAs)
740 D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));
741
742 if (auto RetainOp = Info.SwiftRetainOp)
743 D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));
744
745 if (auto ReleaseOp = Info.SwiftReleaseOp)
746 D->addAttr(
747 SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
748 if (auto DestroyOp = Info.SwiftDestroyOp)
749 D->addAttr(
750 SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
751 if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
752 D->addAttr(SwiftAttrAttr::Create(
753 S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
754
755 if (auto Copyable = Info.isSwiftCopyable()) {
756 if (!*Copyable)
757 addSwiftAttrIfAbsent(S, D, "~Copyable");
758 }
759
760 if (auto Escapable = Info.isSwiftEscapable()) {
761 addSwiftAttrIfAbsent(S, D, *Escapable ? "Escapable" : "~Escapable");
762 }
763
764 if (auto Extensibility = Info.EnumExtensibility) {
766 bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
767 handleAPINotedAttribute<EnumExtensibilityAttr>(
768 S, D, ShouldAddAttribute, Metadata, [&] {
769 EnumExtensibilityAttr::Kind kind;
770 switch (*Extensibility) {
771 case EnumExtensibilityKind::None:
772 llvm_unreachable("remove only");
773 case EnumExtensibilityKind::Open:
774 kind = EnumExtensibilityAttr::Open;
775 break;
776 case EnumExtensibilityKind::Closed:
777 kind = EnumExtensibilityAttr::Closed;
778 break;
779 }
780 return new (S.Context)
781 EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
782 });
783 }
784
785 if (auto FlagEnum = Info.isFlagEnum()) {
786 handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
787 return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
788 });
789 }
790
791 // Handle common type information.
792 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
793 Metadata);
794}
795
796/// Process API notes for a typedef.
798 const api_notes::TypedefInfo &Info,
799 VersionedInfoMetadata Metadata) {
800 // swift_wrapper
801 using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
802
803 if (auto SwiftWrapper = Info.SwiftWrapper) {
804 handleAPINotedAttribute<SwiftNewTypeAttr>(
805 S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
806 SwiftNewTypeAttr::NewtypeKind Kind;
807 switch (*SwiftWrapper) {
808 case SwiftWrapperKind::None:
809 llvm_unreachable("Shouldn't build an attribute");
810
811 case SwiftWrapperKind::Struct:
812 Kind = SwiftNewTypeAttr::NK_Struct;
813 break;
814
815 case SwiftWrapperKind::Enum:
816 Kind = SwiftNewTypeAttr::NK_Enum;
817 break;
818 }
819 AttributeCommonInfo SyntaxInfo{
820 SourceRange(),
821 AttributeCommonInfo::AT_SwiftNewType,
822 {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
823 /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
824 return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
825 });
826 }
827
828 // Handle common type information.
829 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
830 Metadata);
831}
832
833/// Process API notes for an Objective-C class or protocol.
835 const api_notes::ContextInfo &Info,
836 VersionedInfoMetadata Metadata) {
837 // Handle common type information.
838 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
839 Metadata);
840}
841
842/// Process API notes for an Objective-C class.
844 const api_notes::ContextInfo &Info,
845 VersionedInfoMetadata Metadata) {
846 if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
847 handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
848 S, D, *AsNonGeneric, Metadata, [&] {
849 return new (S.Context)
850 SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
851 });
852 }
853
854 if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
855 handleAPINotedAttribute<SwiftObjCMembersAttr>(
856 S, D, *ObjcMembers, Metadata, [&] {
857 return new (S.Context)
858 SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
859 });
860 }
861
862 // Handle information common to Objective-C classes and protocols.
863 ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
864 Metadata);
865}
866
867/// If we're applying API notes with an active, non-default version, and the
868/// versioned API notes have a SwiftName but the declaration normally wouldn't
869/// have one, add a removal attribute to make it clear that the new SwiftName
870/// attribute only applies to the active version of \p D, not to all versions.
871///
872/// This must be run \em before processing API notes for \p D, because otherwise
873/// any existing SwiftName attribute will have been packaged up in a
874/// SwiftVersionedAdditionAttr.
875template <typename SpecificInfo>
877 Sema &S, Decl *D,
879 if (D->hasAttr<SwiftNameAttr>())
880 return;
881 if (!Info.getSelected())
882 return;
883
884 // Is the active slice versioned, and does it set a Swift name?
885 VersionTuple SelectedVersion;
886 SpecificInfo SelectedInfoSlice;
887 std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
888 if (SelectedVersion.empty())
889 return;
890 if (SelectedInfoSlice.SwiftName.empty())
891 return;
892
893 // Does the unversioned slice /not/ set a Swift name?
894 for (const auto &VersionAndInfoSlice : Info) {
895 if (!VersionAndInfoSlice.first.empty())
896 continue;
897 if (!VersionAndInfoSlice.second.SwiftName.empty())
898 return;
899 }
900
901 // Then explicitly call that out with a removal attribute.
902 VersionedInfoMetadata DummyFutureMetadata(
903 SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
904 handleAPINotedAttribute<SwiftNameAttr>(
905 S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
906 llvm_unreachable("should not try to add an attribute here");
907 });
908}
909
910/// Processes all versions of versioned API notes.
911///
912/// Just dispatches to the various ProcessAPINotes functions in this file.
913template <typename SpecificDecl, typename SpecificInfo>
915 Sema &S, SpecificDecl *D,
917
920
921 unsigned Selected = Info.getSelected().value_or(Info.size());
922
923 VersionTuple Version;
924 SpecificInfo InfoSlice;
925 for (unsigned i = 0, e = Info.size(); i != e; ++i) {
926 std::tie(Version, InfoSlice) = Info[i];
927 auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
928 auto Replacement = IsSubstitution_t::Original;
929
930 // When collecting all APINotes as version-independent,
931 // capture all as inactive and defer to the client to select the
932 // right one.
934 Active = IsActive_t::Inactive;
935 Replacement = IsSubstitution_t::Original;
936 } else if (Active == IsActive_t::Inactive && Version.empty()) {
937 Replacement = IsSubstitution_t::Replacement;
938 Version = Info[Selected].first;
939 }
940
941 ProcessAPINotes(S, D, InfoSlice,
942 VersionedInfoMetadata(Version, Active, Replacement));
943 }
944}
945
946static std::optional<api_notes::Context>
948 if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
949 for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
950 // Retrieve the context ID for the parent namespace of the decl.
951 std::stack<NamespaceDecl *> NamespaceStack;
952 {
953 for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
954 CurrentNamespace =
955 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
956 if (!CurrentNamespace->isInlineNamespace())
957 NamespaceStack.push(CurrentNamespace);
958 }
959 }
960 std::optional<api_notes::ContextID> NamespaceID;
961 while (!NamespaceStack.empty()) {
962 auto CurrentNamespace = NamespaceStack.top();
963 NamespaceStack.pop();
964 NamespaceID =
965 Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
966 if (!NamespaceID)
967 return std::nullopt;
968 }
969 if (NamespaceID)
970 return api_notes::Context(*NamespaceID,
972 }
973 }
974 return std::nullopt;
975}
976
977static std::optional<api_notes::Context>
979 assert(DC && "tag context must not be null");
980 for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
981 // Retrieve the context ID for the parent tag of the decl.
982 std::stack<TagDecl *> TagStack;
983 {
984 for (auto CurrentTag = DC; CurrentTag;
985 CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
986 TagStack.push(CurrentTag);
987 }
988 assert(!TagStack.empty());
989 std::optional<api_notes::Context> Ctx =
990 UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
991 while (!TagStack.empty()) {
992 auto CurrentTag = TagStack.top();
993 TagStack.pop();
994 auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
995 if (!CtxID)
996 return std::nullopt;
998 }
999 return Ctx;
1000 }
1001 return std::nullopt;
1002}
1003
1004namespace clang {
1007
1009 return Parameters == Other.Parameters;
1010 }
1011
1013 return !(*this == Other);
1014 }
1015};
1016
1019 std::optional<APINotesParameterSelector> Desugared;
1020};
1021} // namespace clang
1022
1023static PrintingPolicy
1025 PrintingPolicy Policy(Context.getLangOpts());
1026 Policy.PrintAsCanonical = false;
1027 Policy.FullyQualifiedName = false;
1028 Policy.SuppressScope = false;
1029 Policy.UsePreferredNames = false;
1030 Policy.MSVCFormatting = false;
1031 Policy.SplitTemplateClosers = false;
1032 Policy.IncludeNewlines = false;
1033 return Policy;
1034}
1035
1036// Print the APINotes selector spelling for one parameter. The source-spelled
1037// selector is tried first. The desugared spelling is only a permissive
1038// fallback.
1040 QualType ParamType, const ASTContext &Context, const PrintingPolicy &Policy,
1041 bool Desugar) {
1042 if (Desugar)
1043 ParamType = ParamType.getDesugaredType(Context);
1044
1045 ParamType.removeLocalConst();
1046 ParamType.removeLocalVolatile();
1047 ParamType = ParamType.stripNullability(Context);
1048
1049 return ParamType.getAsString(Policy);
1050}
1051
1052static std::optional<APINotesParameterSelectorCandidates>
1054 const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
1055 if (!FPT)
1056 return std::nullopt;
1057
1059 APINotesParameterSelector Desugared;
1060 Candidates.Source.Parameters.reserve(FPT->getNumParams());
1061 Desugared.Parameters.reserve(FPT->getNumParams());
1062
1063 const PrintingPolicy Policy =
1065 for (QualType ParamType : FPT->param_types()) {
1066 Candidates.Source.Parameters.push_back(
1067 getAPINotesParameterSelectorSpelling(ParamType, S.Context, Policy,
1068 /*Desugar=*/false));
1070 ParamType, S.Context, Policy, /*Desugar=*/true));
1071 }
1072
1073 if (Candidates.Source != Desugared)
1074 Candidates.Desugared = std::move(Desugared);
1075
1076 return Candidates;
1077}
1078
1081 api_notes::APINotesReader &Reader) {
1082 auto [StateIt, Inserted] = Readers.try_emplace(&Reader);
1083 APINotesSelectorDiagnosticReaderState &State = StateIt->second;
1084 if (!Inserted)
1085 return State;
1086
1089 State.addSelectors(Selectors);
1090 return State;
1091}
1092
1097 std::make_unique<APINotesSelectorDiagnosticState>();
1098
1099 return S.APINotesSelectorDiagnostics->getOrCreateReaderState(*Reader);
1100}
1101
1103 llvm::function_ref<std::optional<api_notes::APINotesFunctionSelectorKey>(
1105 GetSelectorKey,
1106 const APINotesParameterSelectorCandidates &Candidates) {
1107 if (auto Key = GetSelectorKey(Candidates.Source.Parameters))
1108 markUsed(*Key);
1109 if (Candidates.Desugared) {
1110 if (auto Key = GetSelectorKey(Candidates.Desugared->Parameters))
1111 markUsed(*Key);
1112 }
1113}
1114
1115// Apply the first exact selector entry found. This preserves source-spelling
1116// precedence over the desugared fallback and avoids applying multiple exact
1117// entries for the same declaration.
1118template <typename SpecificInfo, typename SpecificDecl>
1120 Sema &S, SpecificDecl *D,
1121 const APINotesParameterSelectorCandidates &ParameterSelectorCandidates,
1124 LookupExact) {
1125 auto ProcessSelector = [&](const APINotesParameterSelector &Selector) {
1126 auto Info = LookupExact(Selector.Parameters);
1127 if (Info.size() == 0)
1128 return false;
1129
1130 ProcessVersionedAPINotes(S, D, Info);
1131 return true;
1132 };
1133
1134 if (ProcessSelector(ParameterSelectorCandidates.Source))
1135 return;
1136
1137 if (ParameterSelectorCandidates.Desugared)
1138 ProcessSelector(*ParameterSelectorCandidates.Desugared);
1139}
1140
1141/// Process API notes that are associated with this declaration, mapping them
1142/// to attributes as appropriate.
1144 if (!D)
1145 return;
1146 if (!APINotes.hasAPINotes())
1147 return;
1148 auto Readers = APINotes.findAPINotes(D->getLocation());
1149 if (Readers.empty())
1150 return;
1151
1152 auto *DC = D->getDeclContext();
1153 // Globals.
1154 if (DC->isFileContext() || DC->isNamespace() ||
1155 DC->getDeclKind() == Decl::LinkageSpec) {
1156 std::optional<api_notes::Context> APINotesContext =
1158 // Global variables.
1159 if (auto VD = dyn_cast<VarDecl>(D)) {
1160 for (auto Reader : Readers) {
1161 auto Info =
1162 Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
1163 ProcessVersionedAPINotes(*this, VD, Info);
1164 }
1165
1166 return;
1167 }
1168
1169 // Global functions.
1170 if (auto FD = dyn_cast<FunctionDecl>(D)) {
1171 if (FD->getDeclName().isIdentifier()) {
1172 auto ParameterSelectorCandidates =
1174
1175 for (auto Reader : Readers) {
1176 auto Info =
1177 Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
1178 ProcessVersionedAPINotes(*this, FD, Info);
1179
1180 if (ParameterSelectorCandidates)
1182 *this, FD, *ParameterSelectorCandidates,
1183 [&](ArrayRef<std::string> Parameters) {
1184 return Reader->lookupGlobalFunction(FD->getName(), Parameters,
1185 APINotesContext);
1186 });
1187
1188 if (ParameterSelectorCandidates) {
1189 auto &DiagnosticState =
1191 if (auto BroadKey = Reader->getGlobalFunctionSelectorKey(
1192 FD->getName(), APINotesContext))
1193 DiagnosticState.noteSeenDeclaration(*BroadKey, FD->getName(),
1194 FD->getLocation());
1195 DiagnosticState.markCandidatesUsed(
1196 [&](ArrayRef<std::string> Parameters) {
1197 return Reader->getGlobalFunctionSelectorKey(
1198 FD->getName(), Parameters, APINotesContext);
1199 },
1200 *ParameterSelectorCandidates);
1201 }
1202 }
1203 }
1204
1205 return;
1206 }
1207
1208 // Objective-C classes.
1209 if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
1210 for (auto Reader : Readers) {
1211 auto Info = Reader->lookupObjCClassInfo(Class->getName());
1212 ProcessVersionedAPINotes(*this, Class, Info);
1213 }
1214
1215 return;
1216 }
1217
1218 // Objective-C protocols.
1219 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
1220 for (auto Reader : Readers) {
1221 auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
1222 ProcessVersionedAPINotes(*this, Protocol, Info);
1223 }
1224
1225 return;
1226 }
1227
1228 // Tags
1229 if (auto Tag = dyn_cast<TagDecl>(D)) {
1230 // Determine the name of the entity to search for. If this is an
1231 // anonymous tag that gets its linked name from a typedef, look for the
1232 // typedef name. This allows tag-specific information to be added
1233 // to the declaration.
1234 std::string LookupName;
1235 if (auto typedefName = Tag->getTypedefNameForAnonDecl())
1236 LookupName = typedefName->getName().str();
1237 else
1238 LookupName = Tag->getName().str();
1239
1240 // Use the source location to discern if this Tag is an OPTIONS macro.
1241 // For now we would like to limit this trick of looking up the APINote tag
1242 // using the EnumDecl's QualType in the case where the enum is anonymous.
1243 // This is only being used to support APINotes lookup for C++
1244 // NS/CF_OPTIONS when C++-Interop is enabled.
1245 std::string MacroName =
1246 LookupName.empty() && Tag->getOuterLocStart().isMacroID()
1248 Tag->getOuterLocStart(),
1249 Tag->getASTContext().getSourceManager(), LangOpts)
1250 .str()
1251 : "";
1252
1253 if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
1254 (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
1255 MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
1256
1257 clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
1259 T.split(), getASTContext().getPrintingPolicy());
1260 }
1261
1262 for (auto Reader : Readers) {
1263 if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
1264 APINotesContext = UnwindTagContext(ParentTag, APINotes);
1265 auto Info = Reader->lookupTag(LookupName, APINotesContext);
1266 ProcessVersionedAPINotes(*this, Tag, Info);
1267 }
1268
1269 return;
1270 }
1271
1272 // Typedefs
1273 if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
1274 for (auto Reader : Readers) {
1275 auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
1276 ProcessVersionedAPINotes(*this, Typedef, Info);
1277 }
1278
1279 return;
1280 }
1281 }
1282
1283 // Enumerators.
1284 if (DC->getRedeclContext()->isFileContext() ||
1285 DC->getRedeclContext()->isExternCContext()) {
1286 if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1287 for (auto Reader : Readers) {
1288 auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1289 ProcessVersionedAPINotes(*this, EnumConstant, Info);
1290 }
1291
1292 return;
1293 }
1294 }
1295
1296 if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1297 // Location function that looks up an Objective-C context.
1298 auto GetContext = [&](api_notes::APINotesReader *Reader)
1299 -> std::optional<api_notes::ContextID> {
1300 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1301 if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1302 return *Found;
1303
1304 return std::nullopt;
1305 }
1306
1307 if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1308 if (auto Cat = Impl->getCategoryDecl())
1309 ObjCContainer = Cat->getClassInterface();
1310 else
1311 return std::nullopt;
1312 }
1313
1314 if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1315 if (Category->getClassInterface())
1316 ObjCContainer = Category->getClassInterface();
1317 else
1318 return std::nullopt;
1319 }
1320
1321 if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1322 if (Impl->getClassInterface())
1323 ObjCContainer = Impl->getClassInterface();
1324 else
1325 return std::nullopt;
1326 }
1327
1328 if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1329 if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1330 return *Found;
1331
1332 return std::nullopt;
1333 }
1334
1335 return std::nullopt;
1336 };
1337
1338 // Objective-C methods.
1339 if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1340 for (auto Reader : Readers) {
1341 if (auto Context = GetContext(Reader)) {
1342 // Map the selector.
1343 Selector Sel = Method->getSelector();
1344 SmallVector<StringRef, 2> SelPieces;
1345 if (Sel.isUnarySelector()) {
1346 SelPieces.push_back(Sel.getNameForSlot(0));
1347 } else {
1348 for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1349 SelPieces.push_back(Sel.getNameForSlot(i));
1350 }
1351
1352 api_notes::ObjCSelectorRef SelectorRef;
1353 SelectorRef.NumArgs = Sel.getNumArgs();
1354 SelectorRef.Identifiers = SelPieces;
1355
1356 auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1357 Method->isInstanceMethod());
1358 ProcessVersionedAPINotes(*this, Method, Info);
1359 }
1360 }
1361 }
1362
1363 // Objective-C properties.
1364 if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1365 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1366 if (auto Context = GetContext(Reader)) {
1367 bool isInstanceProperty =
1368 (Property->getPropertyAttributesAsWritten() &
1370 auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1371 isInstanceProperty);
1372 ProcessVersionedAPINotes(*this, Property, Info);
1373 }
1374 }
1375
1376 return;
1377 }
1378 }
1379
1380 if (auto TagContext = dyn_cast<TagDecl>(DC)) {
1381 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1382 if (!isa<CXXConstructorDecl>(CXXMethod) &&
1383 !isa<CXXDestructorDecl>(CXXMethod) &&
1384 !isa<CXXConversionDecl>(CXXMethod)) {
1385 auto ParameterSelectorCandidates =
1387 for (auto Reader : Readers) {
1388 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1389 std::string MethodName;
1390 if (CXXMethod->isOverloadedOperator())
1391 MethodName =
1392 std::string("operator") +
1393 getOperatorSpelling(CXXMethod->getOverloadedOperator());
1394 else
1395 MethodName = CXXMethod->getName();
1396
1397 auto Info = Reader->lookupCXXMethod(Context->id, MethodName);
1398 ProcessVersionedAPINotes(*this, CXXMethod, Info);
1399
1400 if (ParameterSelectorCandidates)
1402 *this, CXXMethod, *ParameterSelectorCandidates,
1403 [&](ArrayRef<std::string> Parameters) {
1404 return Reader->lookupCXXMethod(Context->id, MethodName,
1405 Parameters);
1406 });
1407
1408 if (ParameterSelectorCandidates) {
1409 auto &DiagnosticState =
1411 if (auto BroadKey =
1412 Reader->getCXXMethodSelectorKey(Context->id, MethodName))
1413 DiagnosticState.noteSeenDeclaration(*BroadKey, MethodName,
1414 CXXMethod->getLocation());
1415 DiagnosticState.markCandidatesUsed(
1416 [&](ArrayRef<std::string> Parameters) {
1417 return Reader->getCXXMethodSelectorKey(
1418 Context->id, MethodName, Parameters);
1419 },
1420 *ParameterSelectorCandidates);
1421 }
1422 }
1423 }
1424 }
1425 }
1426
1427 if (auto Field = dyn_cast<FieldDecl>(D)) {
1428 if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1429 for (auto Reader : Readers) {
1430 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1431 auto Info = Reader->lookupField(Context->id, Field->getName());
1432 ProcessVersionedAPINotes(*this, Field, Info);
1433 }
1434 }
1435 }
1436 }
1437
1438 if (auto Tag = dyn_cast<TagDecl>(D)) {
1439 for (auto Reader : Readers) {
1440 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1441 auto Info = Reader->lookupTag(Tag->getName(), Context);
1442 ProcessVersionedAPINotes(*this, Tag, Info);
1443 }
1444 }
1445 }
1446 }
1447}
1448
1450 Sema &S, api_notes::APINotesReader &Reader) const {
1451 for (const auto &Selector : SelectorUsed) {
1452 if (Selector.second)
1453 continue;
1454
1455 auto SeenName =
1456 SeenNames.find(Selector.first.getWithoutParameterSelector());
1457 if (SeenName == SeenNames.end())
1458 continue;
1459
1460 std::optional<SmallVector<std::string, 4>> ParameterSpellings =
1462 if (!ParameterSpellings)
1463 continue;
1464
1465 S.Diag(SeenName->second.Loc, diag::warn_apinotes_message)
1466 << (llvm::Twine("API notes entry for '") + SeenName->second.Name +
1467 "' has unmatched Where.Parameters " +
1468 api_notes::formatAPINotesParameterSelector(*ParameterSpellings))
1469 .str();
1470 }
1471}
1472
1474 for (const auto &ReaderSelectors : Readers)
1475 ReaderSelectors.second.diagnoseUnused(S, *ReaderSelectors.first);
1476}
1477
1480 return;
1481
1482 if (!Diags.isIgnored(diag::warn_apinotes_message, SourceLocation()))
1483 APINotesSelectorDiagnostics->diagnoseUnused(*this);
1485}
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)
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:223
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType, QualType equivalentType, const Attr *attr=nullptr) const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
IdentifierTable & Idents
Definition ASTContext.h:823
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:897
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Attr - This represents one attribute.
Definition Attr.h:46
A factory, from which one makes pools, from which one creates individual attributes which are dealloc...
Definition ParsedAttr.h:622
ParsedAttr * create(IdentifierInfo *attrName, SourceRange attrRange, AttributeScopeInfo scope, ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form, SourceLocation ellipsisLoc=SourceLocation())
Definition ParsedAttr.h:735
Type source information for an attributed type.
Definition TypeLoc.h:1008
void setAttr(const Attr *A)
Definition TypeLoc.h:1034
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
void addAttr(Attr *A)
attr_iterator attr_end() const
Definition DeclBase.h:550
AttrVec::const_iterator attr_iterator
Definition DeclBase.h:540
ObjCDeclQualifier
ObjCDeclQualifier - 'Qualifiers' written next to the return and parameter types in method declaration...
Definition DeclBase.h:198
@ OBJC_TQ_CSNullability
The nullability qualifier is set when the nullability of the result or parameter was expressed via a ...
Definition DeclBase.h:210
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:3557
Represents a member of a struct/union/class.
Definition Decl.h:3294
Represents a function declaration or definition.
Definition Decl.h:2058
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2927
QualType getReturnType() const
Definition Decl.h:2975
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2904
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3869
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4999
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4617
ExtInfo getExtInfo() const
Definition TypeBase.h:4973
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:1819
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
Definition TypeBase.h:1312
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
void removeLocalVolatile()
Definition TypeBase.h:8620
std::string getAsString() const
void * getAsOpaquePtr() const
Definition TypeBase.h:985
void removeLocalConst()
Definition TypeBase.h:8612
QualType stripNullability(const ASTContext &ctx) const
Strip nullability attributes from the given type.
Definition Type.cpp:1737
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:864
ASTContext & Context
Definition Sema.h:1305
SemaObjC & ObjC()
Definition Sema.h:1517
bool captureSwiftVersionIndependentAPINotes()
Whether APINotes should be gathered for all applicable Swift language versions, without being applied...
Definition Sema.h:1672
ASTContext & getASTContext() const
Definition Sema.h:936
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1209
api_notes::APINotesManager APINotes
Definition Sema.h:1309
const LangOptions & LangOpts
Definition Sema.h:1303
SemaSwift & Swift()
Definition Sema.h:1562
std::function< TypeResult(StringRef, StringRef, SourceLocation)> ParseTypeFromStringCallback
Callback to the parser to parse a type expressed as a string.
Definition Sema.h:1360
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:4875
DiagnosticsEngine & Diags
Definition Sema.h:1307
std::unique_ptr< APINotesSelectorDiagnosticState > APINotesSelectorDiagnostics
Definition Sema.h:1311
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:3851
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:9407
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isMemberPointerType() const
Definition TypeBase.h:8822
bool isObjCObjectPointerType() const
Definition TypeBase.h:8920
bool isAnyPointerType() const
Definition TypeBase.h:8749
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3696
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
QualType getType() const
Definition Value.cpp:238
Represents a variable declaration or definition.
Definition Decl.h:932
The API notes manager helps find API notes associated with declarations.
llvm::SmallVector< APINotesReader *, 2 > findAPINotes(SourceLocation Loc)
Find the API notes readers that correspond to the given source location.
Captures the completed versioned information for a particular part of API notes, including both unver...
unsigned size() const
Return the number of versioned results we know about.
std::optional< unsigned > getSelected() const
Retrieve the selected index in the result set.
A class that reads API notes data from a binary file that was written by the APINotesWriter.
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:6031
@ Other
Other implicit parameter.
Definition Decl.h:1774
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 FullyQualifiedName
When true, print the fully qualified name of function declarations.
unsigned MSVCFormatting
Use whitespace and punctuation like MSVC does.
unsigned SplitTemplateClosers
Whether nested templates must be closed like 'a<b<c> >' rather than 'a<b<c>>'.
unsigned UsePreferredNames
Whether to use C++ template preferred_name attributes when printing templates.
unsigned SuppressScope
Suppresses printing of scope specifiers.
unsigned IncludeNewlines
When true, include newlines after statements like "break", etc.
unsigned PrintAsCanonical
Whether to print entities as written or canonically.
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition Types.h:1092
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition Types.h:1094