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