clang 22.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 "CheckExprLifetime.h"
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"
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 {
413 llvm_unreachable("API notes allowed a type on an unknown declaration");
414 }
415 }
416 }
417}
418
420 auto GetModified =
421 [&](class Decl *D, QualType QT,
422 NullabilityKind Nullability) -> std::optional<QualType> {
423 QualType Original = QT;
426 /*OverrideExisting=*/true);
427 return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT)
428 : std::nullopt;
429 };
430
431 if (auto Function = dyn_cast<FunctionDecl>(D)) {
432 if (auto Modified =
433 GetModified(D, Function->getReturnType(), Nullability)) {
434 const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
435 if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType))
436 Function->setType(Context.getFunctionType(
437 *Modified, proto->getParamTypes(), proto->getExtProtoInfo()));
438 else
439 Function->setType(
440 Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo()));
441 }
442 } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
443 if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) {
444 Method->setReturnType(*Modified);
445
446 // Make it a context-sensitive keyword if we can.
447 if (!isIndirectPointerType(*Modified))
448 Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
449 Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
450 }
451 } else if (auto Value = dyn_cast<ValueDecl>(D)) {
452 if (auto Modified = GetModified(D, Value->getType(), Nullability)) {
453 Value->setType(*Modified);
454
455 // Make it a context-sensitive keyword if we can.
456 if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
457 if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified))
458 Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
459 Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
460 }
461 }
462 } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
463 if (auto Modified = GetModified(D, Property->getType(), Nullability)) {
464 Property->setType(*Modified, Property->getTypeSourceInfo());
465
466 // Make it a property attribute if we can.
467 if (!isIndirectPointerType(*Modified))
468 Property->setPropertyAttributes(
470 }
471 }
472}
473
474/// Process API notes for a variable or property.
475static void ProcessAPINotes(Sema &S, Decl *D,
476 const api_notes::VariableInfo &Info,
477 VersionedInfoMetadata Metadata) {
478 // Type override.
479 applyAPINotesType(S, D, Info.getType(), Metadata);
480
481 // Nullability.
482 if (auto Nullability = Info.getNullability())
483 applyNullability(S, D, *Nullability, Metadata);
484
485 // Handle common entity information.
486 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
487 Metadata);
488}
489
490/// Process API notes for a parameter.
492 const api_notes::ParamInfo &Info,
493 VersionedInfoMetadata Metadata) {
494 // noescape
495 if (auto NoEscape = Info.isNoEscape())
496 handleAPINotedAttribute<NoEscapeAttr>(S, D, *NoEscape, Metadata, [&] {
497 return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
498 });
499
500 if (auto Lifetimebound = Info.isLifetimebound())
501 handleAPINotedAttribute<LifetimeBoundAttr>(
502 S, D, *Lifetimebound, Metadata, [&] {
503 return new (S.Context)
504 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
505 });
506
507 // Retain count convention
510
511 // Handle common entity information.
512 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
513 Metadata);
514}
515
516/// Process API notes for a global variable.
517static void ProcessAPINotes(Sema &S, VarDecl *D,
519 VersionedInfoMetadata metadata) {
520 // Handle common entity information.
521 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
522 metadata);
523}
524
525/// Process API notes for a C field.
526static void ProcessAPINotes(Sema &S, FieldDecl *D,
527 const api_notes::FieldInfo &Info,
528 VersionedInfoMetadata metadata) {
529 // Handle common entity information.
530 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
531 metadata);
532}
533
534/// Process API notes for an Objective-C property.
536 const api_notes::ObjCPropertyInfo &Info,
537 VersionedInfoMetadata Metadata) {
538 // Handle common entity information.
539 ProcessAPINotes(S, D, static_cast<const api_notes::VariableInfo &>(Info),
540 Metadata);
541
542 if (auto AsAccessors = Info.getSwiftImportAsAccessors()) {
543 handleAPINotedAttribute<SwiftImportPropertyAsAccessorsAttr>(
544 S, D, *AsAccessors, Metadata, [&] {
545 return new (S.Context) SwiftImportPropertyAsAccessorsAttr(
547 });
548 }
549}
550
551namespace {
552typedef llvm::PointerUnion<FunctionDecl *, ObjCMethodDecl *> FunctionOrMethod;
553}
554
555/// Process API notes for a function or method.
556static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
557 const api_notes::FunctionInfo &Info,
558 VersionedInfoMetadata Metadata) {
559 // Find the declaration itself.
560 FunctionDecl *FD = dyn_cast<FunctionDecl *>(AnyFunc);
561 Decl *D = FD;
562 ObjCMethodDecl *MD = nullptr;
563 if (!D) {
564 MD = cast<ObjCMethodDecl *>(AnyFunc);
565 D = MD;
566 }
567
568 assert((FD || MD) && "Expecting Function or ObjCMethod");
569
570 // Nullability of return type.
571 if (Info.NullabilityAudited)
572 applyNullability(S, D, Info.getReturnTypeInfo(), Metadata);
573
574 // Parameters.
575 unsigned NumParams = FD ? FD->getNumParams() : MD->param_size();
576
577 bool AnyTypeChanged = false;
578 for (unsigned I = 0; I != NumParams; ++I) {
579 ParmVarDecl *Param = FD ? FD->getParamDecl(I) : MD->param_begin()[I];
580 QualType ParamTypeBefore = Param->getType();
581
582 if (I < Info.Params.size())
583 ProcessAPINotes(S, Param, Info.Params[I], Metadata);
584
585 // Nullability.
586 if (Info.NullabilityAudited)
587 applyNullability(S, Param, Info.getParamTypeInfo(I), Metadata);
588
589 if (ParamTypeBefore.getAsOpaquePtr() != Param->getType().getAsOpaquePtr())
590 AnyTypeChanged = true;
591 }
592
593 // returns_(un)retained
594 if (!Info.SwiftReturnOwnership.empty())
595 D->addAttr(SwiftAttrAttr::Create(S.Context,
596 "returns_" + Info.SwiftReturnOwnership));
597
598 // Result type override.
599 QualType OverriddenResultType;
600 if (Metadata.IsActive && !Info.ResultType.empty() &&
603 Info.ResultType, "<API Notes>", D->getLocation());
604 if (ParsedType.isUsable()) {
605 QualType ResultType = Sema::GetTypeFromParser(ParsedType.get());
606
607 if (MD) {
609 MD->getReturnType(), ResultType)) {
610 auto ResultTypeInfo =
611 S.Context.getTrivialTypeSourceInfo(ResultType, D->getLocation());
612 MD->setReturnType(ResultType);
613 MD->setReturnTypeSourceInfo(ResultTypeInfo);
614 }
616 S, FD->getLocation(), FD->getReturnType(), ResultType)) {
617 OverriddenResultType = ResultType;
618 AnyTypeChanged = true;
619 }
620 }
621 }
622
623 // If the result type or any of the parameter types changed for a function
624 // declaration, we have to rebuild the type.
625 if (FD && AnyTypeChanged) {
626 if (const auto *fnProtoType = FD->getType()->getAs<FunctionProtoType>()) {
627 if (OverriddenResultType.isNull())
628 OverriddenResultType = fnProtoType->getReturnType();
629
630 SmallVector<QualType, 4> ParamTypes;
631 for (auto Param : FD->parameters())
632 ParamTypes.push_back(Param->getType());
633
634 FD->setType(S.Context.getFunctionType(OverriddenResultType, ParamTypes,
635 fnProtoType->getExtProtoInfo()));
636 } else if (!OverriddenResultType.isNull()) {
637 const auto *FnNoProtoType = FD->getType()->castAs<FunctionNoProtoType>();
639 OverriddenResultType, FnNoProtoType->getExtInfo()));
640 }
641 }
642
643 // Retain count convention
646
647 // Handle common entity information.
648 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
649 Metadata);
650}
651
652/// Process API notes for a C++ method.
653static void ProcessAPINotes(Sema &S, CXXMethodDecl *Method,
654 const api_notes::CXXMethodInfo &Info,
655 VersionedInfoMetadata Metadata) {
656 if (Info.This && Info.This->isLifetimebound() &&
658 auto MethodType = Method->getType();
659 auto *attr = ::new (S.Context)
660 LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
661 QualType AttributedType =
662 S.Context.getAttributedType(attr, MethodType, MethodType);
663 TypeLocBuilder TLB;
664 TLB.pushFullCopy(Method->getTypeSourceInfo()->getTypeLoc());
665 AttributedTypeLoc TyLoc = TLB.push<AttributedTypeLoc>(AttributedType);
666 TyLoc.setAttr(attr);
667 Method->setType(AttributedType);
668 Method->setTypeSourceInfo(TLB.getTypeSourceInfo(S.Context, AttributedType));
669 }
670
671 ProcessAPINotes(S, (FunctionOrMethod)Method, Info, Metadata);
672}
673
674/// Process API notes for a global function.
677 VersionedInfoMetadata Metadata) {
678 // Handle common function information.
679 ProcessAPINotes(S, FunctionOrMethod(D),
680 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
681}
682
683/// Process API notes for an enumerator.
685 const api_notes::EnumConstantInfo &Info,
686 VersionedInfoMetadata Metadata) {
687 // Handle common information.
688 ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
689 Metadata);
690}
691
692/// Process API notes for an Objective-C method.
694 const api_notes::ObjCMethodInfo &Info,
695 VersionedInfoMetadata Metadata) {
696 // Designated initializers.
697 if (Info.DesignatedInit) {
698 handleAPINotedAttribute<ObjCDesignatedInitializerAttr>(
699 S, D, true, Metadata, [&] {
700 if (ObjCInterfaceDecl *IFace = D->getClassInterface())
701 IFace->setHasDesignatedInitializers();
702
703 return new (S.Context) ObjCDesignatedInitializerAttr(
705 });
706 }
707
708 // Handle common function information.
709 ProcessAPINotes(S, FunctionOrMethod(D),
710 static_cast<const api_notes::FunctionInfo &>(Info), Metadata);
711}
712
713/// Process API notes for a tag.
714static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
715 VersionedInfoMetadata Metadata) {
716 if (auto ImportAs = Info.SwiftImportAs)
717 D->addAttr(SwiftAttrAttr::Create(S.Context, "import_" + ImportAs.value()));
718
719 if (auto RetainOp = Info.SwiftRetainOp)
720 D->addAttr(SwiftAttrAttr::Create(S.Context, "retain:" + RetainOp.value()));
721
722 if (auto ReleaseOp = Info.SwiftReleaseOp)
723 D->addAttr(
724 SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
725 if (auto DestroyOp = Info.SwiftDestroyOp)
726 D->addAttr(
727 SwiftAttrAttr::Create(S.Context, "destroy:" + DestroyOp.value()));
728 if (auto DefaultOwnership = Info.SwiftDefaultOwnership)
729 D->addAttr(SwiftAttrAttr::Create(
730 S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
731
732 if (auto Copyable = Info.isSwiftCopyable()) {
733 if (!*Copyable)
734 D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));
735 }
736
737 if (auto Escapable = Info.isSwiftEscapable()) {
738 D->addAttr(SwiftAttrAttr::Create(S.Context,
739 *Escapable ? "Escapable" : "~Escapable"));
740 }
741
742 if (auto Extensibility = Info.EnumExtensibility) {
744 bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None);
745 handleAPINotedAttribute<EnumExtensibilityAttr>(
746 S, D, ShouldAddAttribute, Metadata, [&] {
747 EnumExtensibilityAttr::Kind kind;
748 switch (*Extensibility) {
749 case EnumExtensibilityKind::None:
750 llvm_unreachable("remove only");
751 case EnumExtensibilityKind::Open:
752 kind = EnumExtensibilityAttr::Open;
753 break;
754 case EnumExtensibilityKind::Closed:
755 kind = EnumExtensibilityAttr::Closed;
756 break;
757 }
758 return new (S.Context)
759 EnumExtensibilityAttr(S.Context, getPlaceholderAttrInfo(), kind);
760 });
761 }
762
763 if (auto FlagEnum = Info.isFlagEnum()) {
764 handleAPINotedAttribute<FlagEnumAttr>(S, D, *FlagEnum, Metadata, [&] {
765 return new (S.Context) FlagEnumAttr(S.Context, getPlaceholderAttrInfo());
766 });
767 }
768
769 // Handle common type information.
770 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
771 Metadata);
772}
773
774/// Process API notes for a typedef.
776 const api_notes::TypedefInfo &Info,
777 VersionedInfoMetadata Metadata) {
778 // swift_wrapper
779 using SwiftWrapperKind = api_notes::SwiftNewTypeKind;
780
781 if (auto SwiftWrapper = Info.SwiftWrapper) {
782 handleAPINotedAttribute<SwiftNewTypeAttr>(
783 S, D, *SwiftWrapper != SwiftWrapperKind::None, Metadata, [&] {
784 SwiftNewTypeAttr::NewtypeKind Kind;
785 switch (*SwiftWrapper) {
786 case SwiftWrapperKind::None:
787 llvm_unreachable("Shouldn't build an attribute");
788
789 case SwiftWrapperKind::Struct:
790 Kind = SwiftNewTypeAttr::NK_Struct;
791 break;
792
793 case SwiftWrapperKind::Enum:
794 Kind = SwiftNewTypeAttr::NK_Enum;
795 break;
796 }
797 AttributeCommonInfo SyntaxInfo{
798 SourceRange(),
799 AttributeCommonInfo::AT_SwiftNewType,
800 {AttributeCommonInfo::AS_GNU, SwiftNewTypeAttr::GNU_swift_wrapper,
801 /*IsAlignas*/ false, /*IsRegularKeywordAttribute*/ false}};
802 return new (S.Context) SwiftNewTypeAttr(S.Context, SyntaxInfo, Kind);
803 });
804 }
805
806 // Handle common type information.
807 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
808 Metadata);
809}
810
811/// Process API notes for an Objective-C class or protocol.
813 const api_notes::ContextInfo &Info,
814 VersionedInfoMetadata Metadata) {
815 // Handle common type information.
816 ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(Info),
817 Metadata);
818}
819
820/// Process API notes for an Objective-C class.
822 const api_notes::ContextInfo &Info,
823 VersionedInfoMetadata Metadata) {
824 if (auto AsNonGeneric = Info.getSwiftImportAsNonGeneric()) {
825 handleAPINotedAttribute<SwiftImportAsNonGenericAttr>(
826 S, D, *AsNonGeneric, Metadata, [&] {
827 return new (S.Context)
828 SwiftImportAsNonGenericAttr(S.Context, getPlaceholderAttrInfo());
829 });
830 }
831
832 if (auto ObjcMembers = Info.getSwiftObjCMembers()) {
833 handleAPINotedAttribute<SwiftObjCMembersAttr>(
834 S, D, *ObjcMembers, Metadata, [&] {
835 return new (S.Context)
836 SwiftObjCMembersAttr(S.Context, getPlaceholderAttrInfo());
837 });
838 }
839
840 // Handle information common to Objective-C classes and protocols.
841 ProcessAPINotes(S, static_cast<clang::ObjCContainerDecl *>(D), Info,
842 Metadata);
843}
844
845/// If we're applying API notes with an active, non-default version, and the
846/// versioned API notes have a SwiftName but the declaration normally wouldn't
847/// have one, add a removal attribute to make it clear that the new SwiftName
848/// attribute only applies to the active version of \p D, not to all versions.
849///
850/// This must be run \em before processing API notes for \p D, because otherwise
851/// any existing SwiftName attribute will have been packaged up in a
852/// SwiftVersionedAdditionAttr.
853template <typename SpecificInfo>
855 Sema &S, Decl *D,
857 if (D->hasAttr<SwiftNameAttr>())
858 return;
859 if (!Info.getSelected())
860 return;
861
862 // Is the active slice versioned, and does it set a Swift name?
863 VersionTuple SelectedVersion;
864 SpecificInfo SelectedInfoSlice;
865 std::tie(SelectedVersion, SelectedInfoSlice) = Info[*Info.getSelected()];
866 if (SelectedVersion.empty())
867 return;
868 if (SelectedInfoSlice.SwiftName.empty())
869 return;
870
871 // Does the unversioned slice /not/ set a Swift name?
872 for (const auto &VersionAndInfoSlice : Info) {
873 if (!VersionAndInfoSlice.first.empty())
874 continue;
875 if (!VersionAndInfoSlice.second.SwiftName.empty())
876 return;
877 }
878
879 // Then explicitly call that out with a removal attribute.
880 VersionedInfoMetadata DummyFutureMetadata(
881 SelectedVersion, IsActive_t::Inactive, IsSubstitution_t::Replacement);
882 handleAPINotedAttribute<SwiftNameAttr>(
883 S, D, /*add*/ false, DummyFutureMetadata, []() -> SwiftNameAttr * {
884 llvm_unreachable("should not try to add an attribute here");
885 });
886}
887
888/// Processes all versions of versioned API notes.
889///
890/// Just dispatches to the various ProcessAPINotes functions in this file.
891template <typename SpecificDecl, typename SpecificInfo>
893 Sema &S, SpecificDecl *D,
895
898
899 unsigned Selected = Info.getSelected().value_or(Info.size());
900
901 VersionTuple Version;
902 SpecificInfo InfoSlice;
903 for (unsigned i = 0, e = Info.size(); i != e; ++i) {
904 std::tie(Version, InfoSlice) = Info[i];
905 auto Active = (i == Selected) ? IsActive_t::Active : IsActive_t::Inactive;
906 auto Replacement = IsSubstitution_t::Original;
907
908 // When collection all APINotes as version-independent,
909 // capture all as inactive and defer to the client select the
910 // right one.
912 Active = IsActive_t::Inactive;
913 Replacement = IsSubstitution_t::Original;
914 } else if (Active == IsActive_t::Inactive && Version.empty()) {
915 Replacement = IsSubstitution_t::Replacement;
916 Version = Info[Selected].first;
917 }
918
919 ProcessAPINotes(S, D, InfoSlice,
920 VersionedInfoMetadata(Version, Active, Replacement));
921 }
922}
923
924static std::optional<api_notes::Context>
926 if (auto NamespaceContext = dyn_cast<NamespaceDecl>(DC)) {
927 for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) {
928 // Retrieve the context ID for the parent namespace of the decl.
929 std::stack<NamespaceDecl *> NamespaceStack;
930 {
931 for (auto CurrentNamespace = NamespaceContext; CurrentNamespace;
932 CurrentNamespace =
933 dyn_cast<NamespaceDecl>(CurrentNamespace->getParent())) {
934 if (!CurrentNamespace->isInlineNamespace())
935 NamespaceStack.push(CurrentNamespace);
936 }
937 }
938 std::optional<api_notes::ContextID> NamespaceID;
939 while (!NamespaceStack.empty()) {
940 auto CurrentNamespace = NamespaceStack.top();
941 NamespaceStack.pop();
942 NamespaceID =
943 Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID);
944 if (!NamespaceID)
945 return std::nullopt;
946 }
947 if (NamespaceID)
948 return api_notes::Context(*NamespaceID,
950 }
951 }
952 return std::nullopt;
953}
954
955static std::optional<api_notes::Context>
957 assert(DC && "tag context must not be null");
958 for (auto Reader : APINotes.findAPINotes(DC->getLocation())) {
959 // Retrieve the context ID for the parent tag of the decl.
960 std::stack<TagDecl *> TagStack;
961 {
962 for (auto CurrentTag = DC; CurrentTag;
963 CurrentTag = dyn_cast<TagDecl>(CurrentTag->getParent()))
964 TagStack.push(CurrentTag);
965 }
966 assert(!TagStack.empty());
967 std::optional<api_notes::Context> Ctx =
968 UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes);
969 while (!TagStack.empty()) {
970 auto CurrentTag = TagStack.top();
971 TagStack.pop();
972 auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx);
973 if (!CtxID)
974 return std::nullopt;
976 }
977 return Ctx;
978 }
979 return std::nullopt;
980}
981
982/// Process API notes that are associated with this declaration, mapping them
983/// to attributes as appropriate.
985 if (!D)
986 return;
987
988 auto *DC = D->getDeclContext();
989 // Globals.
990 if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
991 DC->isExternCXXContext()) {
992 std::optional<api_notes::Context> APINotesContext =
994 // Global variables.
995 if (auto VD = dyn_cast<VarDecl>(D)) {
996 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
997 auto Info =
998 Reader->lookupGlobalVariable(VD->getName(), APINotesContext);
999 ProcessVersionedAPINotes(*this, VD, Info);
1000 }
1001
1002 return;
1003 }
1004
1005 // Global functions.
1006 if (auto FD = dyn_cast<FunctionDecl>(D)) {
1007 if (FD->getDeclName().isIdentifier()) {
1008 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1009 auto Info =
1010 Reader->lookupGlobalFunction(FD->getName(), APINotesContext);
1011 ProcessVersionedAPINotes(*this, FD, Info);
1012 }
1013 }
1014
1015 return;
1016 }
1017
1018 // Objective-C classes.
1019 if (auto Class = dyn_cast<ObjCInterfaceDecl>(D)) {
1020 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1021 auto Info = Reader->lookupObjCClassInfo(Class->getName());
1022 ProcessVersionedAPINotes(*this, Class, Info);
1023 }
1024
1025 return;
1026 }
1027
1028 // Objective-C protocols.
1029 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(D)) {
1030 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1031 auto Info = Reader->lookupObjCProtocolInfo(Protocol->getName());
1032 ProcessVersionedAPINotes(*this, Protocol, Info);
1033 }
1034
1035 return;
1036 }
1037
1038 // Tags
1039 if (auto Tag = dyn_cast<TagDecl>(D)) {
1040 // Determine the name of the entity to search for. If this is an
1041 // anonymous tag that gets its linked name from a typedef, look for the
1042 // typedef name. This allows tag-specific information to be added
1043 // to the declaration.
1044 std::string LookupName;
1045 if (auto typedefName = Tag->getTypedefNameForAnonDecl())
1046 LookupName = typedefName->getName().str();
1047 else
1048 LookupName = Tag->getName().str();
1049
1050 // Use the source location to discern if this Tag is an OPTIONS macro.
1051 // For now we would like to limit this trick of looking up the APINote tag
1052 // using the EnumDecl's QualType in the case where the enum is anonymous.
1053 // This is only being used to support APINotes lookup for C++
1054 // NS/CF_OPTIONS when C++-Interop is enabled.
1055 std::string MacroName =
1056 LookupName.empty() && Tag->getOuterLocStart().isMacroID()
1058 Tag->getOuterLocStart(),
1059 Tag->getASTContext().getSourceManager(), LangOpts)
1060 .str()
1061 : "";
1062
1063 if (LookupName.empty() && isa<clang::EnumDecl>(Tag) &&
1064 (MacroName == "CF_OPTIONS" || MacroName == "NS_OPTIONS" ||
1065 MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS")) {
1066
1067 clang::QualType T = llvm::cast<clang::EnumDecl>(Tag)->getIntegerType();
1069 T.split(), getASTContext().getPrintingPolicy());
1070 }
1071
1072 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1073 if (auto ParentTag = dyn_cast<TagDecl>(Tag->getDeclContext()))
1074 APINotesContext = UnwindTagContext(ParentTag, APINotes);
1075 auto Info = Reader->lookupTag(LookupName, APINotesContext);
1076 ProcessVersionedAPINotes(*this, Tag, Info);
1077 }
1078
1079 return;
1080 }
1081
1082 // Typedefs
1083 if (auto Typedef = dyn_cast<TypedefNameDecl>(D)) {
1084 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1085 auto Info = Reader->lookupTypedef(Typedef->getName(), APINotesContext);
1086 ProcessVersionedAPINotes(*this, Typedef, Info);
1087 }
1088
1089 return;
1090 }
1091 }
1092
1093 // Enumerators.
1094 if (DC->getRedeclContext()->isFileContext() ||
1095 DC->getRedeclContext()->isExternCContext()) {
1096 if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
1097 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1098 auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
1099 ProcessVersionedAPINotes(*this, EnumConstant, Info);
1100 }
1101
1102 return;
1103 }
1104 }
1105
1106 if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
1107 // Location function that looks up an Objective-C context.
1108 auto GetContext = [&](api_notes::APINotesReader *Reader)
1109 -> std::optional<api_notes::ContextID> {
1110 if (auto Protocol = dyn_cast<ObjCProtocolDecl>(ObjCContainer)) {
1111 if (auto Found = Reader->lookupObjCProtocolID(Protocol->getName()))
1112 return *Found;
1113
1114 return std::nullopt;
1115 }
1116
1117 if (auto Impl = dyn_cast<ObjCCategoryImplDecl>(ObjCContainer)) {
1118 if (auto Cat = Impl->getCategoryDecl())
1119 ObjCContainer = Cat->getClassInterface();
1120 else
1121 return std::nullopt;
1122 }
1123
1124 if (auto Category = dyn_cast<ObjCCategoryDecl>(ObjCContainer)) {
1125 if (Category->getClassInterface())
1126 ObjCContainer = Category->getClassInterface();
1127 else
1128 return std::nullopt;
1129 }
1130
1131 if (auto Impl = dyn_cast<ObjCImplDecl>(ObjCContainer)) {
1132 if (Impl->getClassInterface())
1133 ObjCContainer = Impl->getClassInterface();
1134 else
1135 return std::nullopt;
1136 }
1137
1138 if (auto Class = dyn_cast<ObjCInterfaceDecl>(ObjCContainer)) {
1139 if (auto Found = Reader->lookupObjCClassID(Class->getName()))
1140 return *Found;
1141
1142 return std::nullopt;
1143 }
1144
1145 return std::nullopt;
1146 };
1147
1148 // Objective-C methods.
1149 if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
1150 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1151 if (auto Context = GetContext(Reader)) {
1152 // Map the selector.
1153 Selector Sel = Method->getSelector();
1154 SmallVector<StringRef, 2> SelPieces;
1155 if (Sel.isUnarySelector()) {
1156 SelPieces.push_back(Sel.getNameForSlot(0));
1157 } else {
1158 for (unsigned i = 0, n = Sel.getNumArgs(); i != n; ++i)
1159 SelPieces.push_back(Sel.getNameForSlot(i));
1160 }
1161
1162 api_notes::ObjCSelectorRef SelectorRef;
1163 SelectorRef.NumArgs = Sel.getNumArgs();
1164 SelectorRef.Identifiers = SelPieces;
1165
1166 auto Info = Reader->lookupObjCMethod(*Context, SelectorRef,
1167 Method->isInstanceMethod());
1168 ProcessVersionedAPINotes(*this, Method, Info);
1169 }
1170 }
1171 }
1172
1173 // Objective-C properties.
1174 if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
1175 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1176 if (auto Context = GetContext(Reader)) {
1177 bool isInstanceProperty =
1178 (Property->getPropertyAttributesAsWritten() &
1180 auto Info = Reader->lookupObjCProperty(*Context, Property->getName(),
1181 isInstanceProperty);
1182 ProcessVersionedAPINotes(*this, Property, Info);
1183 }
1184 }
1185
1186 return;
1187 }
1188 }
1189
1190 if (auto TagContext = dyn_cast<TagDecl>(DC)) {
1191 if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
1192 if (!isa<CXXConstructorDecl>(CXXMethod) &&
1193 !isa<CXXDestructorDecl>(CXXMethod) &&
1194 !isa<CXXConversionDecl>(CXXMethod) &&
1195 !CXXMethod->isOverloadedOperator()) {
1196 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1197 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1198 auto Info =
1199 Reader->lookupCXXMethod(Context->id, CXXMethod->getName());
1200 ProcessVersionedAPINotes(*this, CXXMethod, Info);
1201 }
1202 }
1203 }
1204 }
1205
1206 if (auto Field = dyn_cast<FieldDecl>(D)) {
1207 if (!Field->isUnnamedBitField() && !Field->isAnonymousStructOrUnion()) {
1208 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1209 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1210 auto Info = Reader->lookupField(Context->id, Field->getName());
1211 ProcessVersionedAPINotes(*this, Field, Info);
1212 }
1213 }
1214 }
1215 }
1216
1217 if (auto Tag = dyn_cast<TagDecl>(D)) {
1218 for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
1219 if (auto Context = UnwindTagContext(TagContext, APINotes)) {
1220 auto Info = Reader->lookupTag(Tag->getName(), Context);
1221 ProcessVersionedAPINotes(*this, Tag, Info);
1222 }
1223 }
1224 }
1225 }
1226}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
FormatToken * Next
The next token in the unwrapped line.
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:188
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:737
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:811
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:44
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:1017
void setAttr(const Attr *A)
Definition TypeLoc.h:1043
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
attr_iterator attr_end() const
Definition DeclBase.h:542
AttrVec::const_iterator attr_iterator
Definition DeclBase.h:532
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:439
DeclContext * getDeclContext()
Definition DeclBase.h:448
attr_range attrs() const
Definition DeclBase.h:535
AttrVec & getAttrs()
Definition DeclBase.h:524
bool hasAttr() const
Definition DeclBase.h:577
An instance of this object exists for each enum constant that is defined.
Definition Decl.h:3420
Represents a member of a struct/union/class.
Definition Decl.h:3157
Represents a function declaration or definition.
Definition Decl.h:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2794
QualType getReturnType() const
Definition Decl.h:2842
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2771
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3767
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4842
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5264
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4460
ExtInfo getExtInfo() const
Definition TypeBase.h:4816
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:1056
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:1789
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, bool DeferHint=false)
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:854
ASTContext & Context
Definition Sema.h:1283
SemaObjC & ObjC()
Definition Sema.h:1490
bool captureSwiftVersionIndependentAPINotes()
Whether APINotes should be gathered for all applicable Swift language versions, without being applied...
Definition Sema.h:1641
ASTContext & getASTContext() const
Definition Sema.h:925
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1191
api_notes::APINotesManager APINotes
Definition Sema.h:1287
const LangOptions & LangOpts
Definition Sema.h:1281
SemaSwift & Swift()
Definition Sema.h:1535
std::function< TypeResult(StringRef, StringRef, SourceLocation)> ParseTypeFromStringCallback
Callback to the parser to parse a type expressed as a string.
Definition Sema.h:1338
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:4793
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:3714
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:1833
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9165
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isMemberPointerType() const
Definition TypeBase.h:8603
bool isObjCObjectPointerType() const
Definition TypeBase.h:8691
bool isAnyPointerType() const
Definition TypeBase.h:8530
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9098
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3559
void setType(QualType newType)
Definition Decl.h:723
QualType getType() const
Definition Decl.h:722
QualType getType() const
Definition Value.cpp:237
Represents a variable declaration or definition.
Definition Decl.h:925
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:734
std::optional< ParamInfo > This
Definition Types.h:738
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:285
std::optional< bool > getSwiftObjCMembers() const
Definition Types.h:295
Describes API notes data for an enumerator.
Definition Types.h:752
Describes API notes data for a C/C++ record field.
Definition Types.h:728
API notes for a function or method.
Definition Types.h:551
std::string SwiftReturnOwnership
Ownership convention for return value.
Definition Types.h:584
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:631
std::vector< ParamInfo > Params
The function parameters.
Definition Types.h:587
NullabilityKind getReturnTypeInfo() const
Definition Types.h:629
NullabilityKind getParamTypeInfo(unsigned index) const
Definition Types.h:625
std::string ResultType
The result type of this function, as a C type.
Definition Types.h:581
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Definition Types.h:565
Describes API notes data for a global function.
Definition Types.h:722
Describes API notes data for a global variable.
Definition Types.h:716
Describes API notes data for an Objective-C method.
Definition Types.h:675
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition Types.h:679
Describes API notes data for an Objective-C property.
Definition Types.h:399
std::optional< bool > getSwiftImportAsAccessors() const
Definition Types.h:409
Describes a function or method parameter.
Definition Types.h:457
std::optional< bool > isNoEscape() const
Definition Types.h:485
std::optional< bool > isLifetimebound() const
Definition Types.h:493
std::optional< RetainCountConventionKind > getRetainCountConvention() const
Definition Types.h:502
Describes API notes data for a tag.
Definition Types.h:758
std::optional< std::string > SwiftReleaseOp
Definition Types.h:777
std::optional< std::string > SwiftRetainOp
Definition Types.h:776
std::optional< std::string > SwiftImportAs
Definition Types.h:775
std::optional< std::string > SwiftDefaultOwnership
Definition Types.h:779
std::optional< EnumExtensibilityKind > EnumExtensibility
Definition Types.h:781
std::optional< std::string > SwiftDestroyOp
Definition Types.h:778
std::optional< bool > isFlagEnum() const
Definition Types.h:788
std::optional< bool > isSwiftCopyable() const
Definition Types.h:798
std::optional< bool > isSwiftEscapable() const
Definition Types.h:807
Describes API notes data for a typedef.
Definition Types.h:869
std::optional< SwiftNewTypeKind > SwiftWrapper
Definition Types.h:871
API notes for a variable/property.
Definition Types.h:342
std::optional< NullabilityKind > getNullability() const
Definition Types.h:358
const std::string & getType() const
Definition Types.h:369
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:348
@ Nullable
Values of this type can be null.
Definition Specifiers.h:352
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
Definition Specifiers.h:357
@ NonNull
Values of this type can never be null.
Definition Specifiers.h:350
@ Property
The type of a property.
Definition TypeBase.h:911
const FunctionProtoType * T
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:5874
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition Types.h:928
llvm::ArrayRef< llvm::StringRef > Identifiers
Definition Types.h:930