1//===------ SemaSwift.cpp ------ Swift language-specific routines ---------===//
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 semantic analysis functions specific to Swift.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Sema/SemaSwift.h"
14#include "clang/AST/DeclBase.h"
15#include "clang/Basic/AttributeCommonInfo.h"
16#include "clang/Basic/DiagnosticSema.h"
17#include "clang/Basic/Specifiers.h"
18#include "clang/Sema/Attr.h"
19#include "clang/Sema/ParsedAttr.h"
20#include "clang/Sema/Sema.h"
21#include "clang/Sema/SemaObjC.h"
22
23namespace clang {
24SemaSwift::SemaSwift(Sema &S) : SemaBase(S) {}
25
26SwiftNameAttr *SemaSwift::mergeNameAttr(Decl *D, const SwiftNameAttr &SNA,
27 StringRef Name) {
28 if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
29 if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
30 Diag(Loc: PrevSNA->getLocation(), DiagID: diag::err_attributes_are_not_compatible)
31 << PrevSNA << &SNA
32 << (PrevSNA->isRegularKeywordAttribute() ||
33 SNA.isRegularKeywordAttribute());
34 Diag(Loc: SNA.getLoc(), DiagID: diag::note_conflicting_attribute);
35 }
36
37 D->dropAttr<SwiftNameAttr>();
38 }
39 return ::new (getASTContext()) SwiftNameAttr(getASTContext(), SNA, Name);
40}
41
42/// Pointer-like types in the default address space.
43static bool isValidSwiftContextType(QualType Ty) {
44 if (!Ty->hasPointerRepresentation())
45 return Ty->isDependentType();
46 return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
47}
48
49/// Pointers and references in the default address space.
50static bool isValidSwiftIndirectResultType(QualType Ty) {
51 if (const auto *PtrType = Ty->getAs<PointerType>()) {
52 Ty = PtrType->getPointeeType();
53 } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
54 Ty = RefType->getPointeeType();
55 } else {
56 return Ty->isDependentType();
57 }
58 return Ty.getAddressSpace() == LangAS::Default;
59}
60
61/// Pointers and references to pointers in the default address space.
62static bool isValidSwiftErrorResultType(QualType Ty) {
63 if (const auto *PtrType = Ty->getAs<PointerType>()) {
64 Ty = PtrType->getPointeeType();
65 } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
66 Ty = RefType->getPointeeType();
67 } else {
68 return Ty->isDependentType();
69 }
70 if (!Ty.getQualifiers().empty())
71 return false;
72 return isValidSwiftContextType(Ty);
73}
74
75void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) {
76 // Make sure that there is a string literal as the annotation's single
77 // argument.
78 StringRef Str;
79 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str))
80 return;
81
82 D->addAttr(A: ::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str));
83}
84
85void SemaSwift::handleBridge(Decl *D, const ParsedAttr &AL) {
86 // Make sure that there is a string literal as the annotation's single
87 // argument.
88 StringRef BT;
89 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str&: BT))
90 return;
91
92 // Warn about duplicate attributes if they have different arguments, but drop
93 // any duplicate attributes regardless.
94 if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
95 if (Other->getSwiftType() != BT)
96 Diag(Loc: AL.getLoc(), DiagID: diag::warn_duplicate_attribute) << AL;
97 return;
98 }
99
100 D->addAttr(A: ::new (getASTContext()) SwiftBridgeAttr(getASTContext(), AL, BT));
101}
102
103static bool isErrorParameter(Sema &S, QualType QT) {
104 const auto *PT = QT->getAs<PointerType>();
105 if (!PT)
106 return false;
107
108 QualType Pointee = PT->getPointeeType();
109
110 // Check for NSError**.
111 if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
112 if (const auto *ID = OPT->getInterfaceDecl())
113 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent())
114 return true;
115
116 // Check for CFError**.
117 if (const auto *PT = Pointee->getAs<PointerType>())
118 if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
119 if (S.ObjC().isCFError(D: RT->getDecl()))
120 return true;
121
122 return false;
123}
124
125void SemaSwift::handleError(Decl *D, const ParsedAttr &AL) {
126 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
127 for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
128 if (isErrorParameter(S, QT: getFunctionOrMethodParamType(D, Idx: I)))
129 return true;
130 }
131
132 S.Diag(Loc: AL.getLoc(), DiagID: diag::err_attr_swift_error_no_error_parameter)
133 << AL << isa<ObjCMethodDecl>(Val: D);
134 return false;
135 };
136
137 auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
138 // - C, ObjC, and block pointers are definitely okay.
139 // - References are definitely not okay.
140 // - nullptr_t is weird, but acceptable.
141 QualType RT = getFunctionOrMethodResultType(D);
142 if (RT->hasPointerRepresentation() && !RT->isReferenceType())
143 return true;
144
145 S.Diag(Loc: AL.getLoc(), DiagID: diag::err_attr_swift_error_return_type)
146 << AL << AL.getArgAsIdent(Arg: 0)->Ident->getName() << isa<ObjCMethodDecl>(Val: D)
147 << /*pointer*/ 1;
148 return false;
149 };
150
151 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
152 QualType RT = getFunctionOrMethodResultType(D);
153 if (RT->isIntegralType(Ctx: S.Context))
154 return true;
155
156 S.Diag(Loc: AL.getLoc(), DiagID: diag::err_attr_swift_error_return_type)
157 << AL << AL.getArgAsIdent(Arg: 0)->Ident->getName() << isa<ObjCMethodDecl>(Val: D)
158 << /*integral*/ 0;
159 return false;
160 };
161
162 if (D->isInvalidDecl())
163 return;
164
165 IdentifierLoc *Loc = AL.getArgAsIdent(Arg: 0);
166 SwiftErrorAttr::ConventionKind Convention;
167 if (!SwiftErrorAttr::ConvertStrToConventionKind(Val: Loc->Ident->getName(),
168 Out&: Convention)) {
169 Diag(Loc: AL.getLoc(), DiagID: diag::warn_attribute_type_not_supported)
170 << AL << Loc->Ident;
171 return;
172 }
173
174 switch (Convention) {
175 case SwiftErrorAttr::None:
176 // No additional validation required.
177 break;
178
179 case SwiftErrorAttr::NonNullError:
180 if (!hasErrorParameter(SemaRef, D, AL))
181 return;
182 break;
183
184 case SwiftErrorAttr::NullResult:
185 if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))
186 return;
187 break;
188
189 case SwiftErrorAttr::NonZeroResult:
190 case SwiftErrorAttr::ZeroResult:
191 if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))
192 return;
193 break;
194 }
195
196 D->addAttr(A: ::new (getASTContext())
197 SwiftErrorAttr(getASTContext(), AL, Convention));
198}
199
200static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
201 const SwiftAsyncErrorAttr *ErrorAttr,
202 const SwiftAsyncAttr *AsyncAttr) {
203 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
204 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
205 S.Diag(Loc: AsyncAttr->getLocation(),
206 DiagID: diag::err_swift_async_error_without_swift_async)
207 << AsyncAttr << isa<ObjCMethodDecl>(Val: D);
208 }
209 return;
210 }
211
212 const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
213 D, Idx: AsyncAttr->getCompletionHandlerIndex().getASTIndex());
214 // handleSwiftAsyncAttr already verified the type is correct, so no need to
215 // double-check it here.
216 const auto *FuncTy = HandlerParam->getType()
217 ->castAs<BlockPointerType>()
218 ->getPointeeType()
219 ->getAs<FunctionProtoType>();
220 ArrayRef<QualType> BlockParams;
221 if (FuncTy)
222 BlockParams = FuncTy->getParamTypes();
223
224 switch (ErrorAttr->getConvention()) {
225 case SwiftAsyncErrorAttr::ZeroArgument:
226 case SwiftAsyncErrorAttr::NonZeroArgument: {
227 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
228 if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
229 S.Diag(Loc: ErrorAttr->getLocation(),
230 DiagID: diag::err_attribute_argument_out_of_bounds)
231 << ErrorAttr << 2;
232 return;
233 }
234 QualType ErrorParam = BlockParams[ParamIdx - 1];
235 if (!ErrorParam->isIntegralType(Ctx: S.Context)) {
236 StringRef ConvStr =
237 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
238 ? "zero_argument"
239 : "nonzero_argument";
240 S.Diag(Loc: ErrorAttr->getLocation(), DiagID: diag::err_swift_async_error_non_integral)
241 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
242 return;
243 }
244 break;
245 }
246 case SwiftAsyncErrorAttr::NonNullError: {
247 bool AnyErrorParams = false;
248 for (QualType Param : BlockParams) {
249 // Check for NSError *.
250 if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
251 if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
252 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) {
253 AnyErrorParams = true;
254 break;
255 }
256 }
257 }
258 // Check for CFError *.
259 if (const auto *PtrTy = Param->getAs<PointerType>()) {
260 if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
261 if (S.ObjC().isCFError(D: RT->getDecl())) {
262 AnyErrorParams = true;
263 break;
264 }
265 }
266 }
267 }
268
269 if (!AnyErrorParams) {
270 S.Diag(Loc: ErrorAttr->getLocation(),
271 DiagID: diag::err_swift_async_error_no_error_parameter)
272 << ErrorAttr << isa<ObjCMethodDecl>(Val: D);
273 return;
274 }
275 break;
276 }
277 case SwiftAsyncErrorAttr::None:
278 break;
279 }
280}
281
282void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) {
283 IdentifierLoc *IDLoc = AL.getArgAsIdent(Arg: 0);
284 SwiftAsyncErrorAttr::ConventionKind ConvKind;
285 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(Val: IDLoc->Ident->getName(),
286 Out&: ConvKind)) {
287 Diag(Loc: AL.getLoc(), DiagID: diag::warn_attribute_type_not_supported)
288 << AL << IDLoc->Ident;
289 return;
290 }
291
292 uint32_t ParamIdx = 0;
293 switch (ConvKind) {
294 case SwiftAsyncErrorAttr::ZeroArgument:
295 case SwiftAsyncErrorAttr::NonZeroArgument: {
296 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 2))
297 return;
298
299 Expr *IdxExpr = AL.getArgAsExpr(Arg: 1);
300 if (!SemaRef.checkUInt32Argument(AI: AL, Expr: IdxExpr, Val&: ParamIdx))
301 return;
302 break;
303 }
304 case SwiftAsyncErrorAttr::NonNullError:
305 case SwiftAsyncErrorAttr::None: {
306 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 1))
307 return;
308 break;
309 }
310 }
311
312 auto *ErrorAttr = ::new (getASTContext())
313 SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx);
314 D->addAttr(A: ErrorAttr);
315
316 if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
317 checkSwiftAsyncErrorBlock(S&: SemaRef, D, ErrorAttr, AsyncAttr);
318}
319
320// For a function, this will validate a compound Swift name, e.g.
321// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
322// the function will output the number of parameter names, and whether this is a
323// single-arg initializer.
324//
325// For a type, enum constant, property, or variable declaration, this will
326// validate either a simple identifier, or a qualified
327// <code>context.identifier</code> name.
328static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
329 SourceLocation Loc, StringRef Name,
330 unsigned &SwiftParamCount,
331 bool &IsSingleParamInit) {
332 SwiftParamCount = 0;
333 IsSingleParamInit = false;
334
335 // Check whether this will be mapped to a getter or setter of a property.
336 bool IsGetter = false, IsSetter = false;
337 if (Name.consume_front(Prefix: "getter:"))
338 IsGetter = true;
339 else if (Name.consume_front(Prefix: "setter:"))
340 IsSetter = true;
341
342 if (Name.back() != ')') {
343 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_function) << AL;
344 return false;
345 }
346
347 bool IsMember = false;
348 StringRef ContextName, BaseName, Parameters;
349
350 std::tie(args&: BaseName, args&: Parameters) = Name.split(Separator: '(');
351
352 // Split at the first '.', if it exists, which separates the context name
353 // from the base name.
354 std::tie(args&: ContextName, args&: BaseName) = BaseName.split(Separator: '.');
355 if (BaseName.empty()) {
356 BaseName = ContextName;
357 ContextName = StringRef();
358 } else if (ContextName.empty() || !isValidAsciiIdentifier(S: ContextName)) {
359 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_invalid_identifier)
360 << AL << /*context*/ 1;
361 return false;
362 } else {
363 IsMember = true;
364 }
365
366 if (!isValidAsciiIdentifier(S: BaseName) || BaseName == "_") {
367 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_invalid_identifier)
368 << AL << /*basename*/ 0;
369 return false;
370 }
371
372 bool IsSubscript = BaseName == "subscript";
373 // A subscript accessor must be a getter or setter.
374 if (IsSubscript && !IsGetter && !IsSetter) {
375 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_subscript_invalid_parameter)
376 << AL << /* getter or setter */ 0;
377 return false;
378 }
379
380 if (Parameters.empty()) {
381 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_missing_parameters) << AL;
382 return false;
383 }
384
385 assert(Parameters.back() == ')' && "expected ')'");
386 Parameters = Parameters.drop_back(); // ')'
387
388 if (Parameters.empty()) {
389 // Setters and subscripts must have at least one parameter.
390 if (IsSubscript) {
391 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_subscript_invalid_parameter)
392 << AL << /* have at least one parameter */ 1;
393 return false;
394 }
395
396 if (IsSetter) {
397 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_setter_parameters) << AL;
398 return false;
399 }
400
401 return true;
402 }
403
404 if (Parameters.back() != ':') {
405 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_function) << AL;
406 return false;
407 }
408
409 StringRef CurrentParam;
410 std::optional<unsigned> SelfLocation;
411 unsigned NewValueCount = 0;
412 std::optional<unsigned> NewValueLocation;
413 do {
414 std::tie(args&: CurrentParam, args&: Parameters) = Parameters.split(Separator: ':');
415
416 if (!isValidAsciiIdentifier(S: CurrentParam)) {
417 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_invalid_identifier)
418 << AL << /*parameter*/ 2;
419 return false;
420 }
421
422 if (IsMember && CurrentParam == "self") {
423 // "self" indicates the "self" argument for a member.
424
425 // More than one "self"?
426 if (SelfLocation) {
427 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_multiple_selfs) << AL;
428 return false;
429 }
430
431 // The "self" location is the current parameter.
432 SelfLocation = SwiftParamCount;
433 } else if (CurrentParam == "newValue") {
434 // "newValue" indicates the "newValue" argument for a setter.
435
436 // There should only be one 'newValue', but it's only significant for
437 // subscript accessors, so don't error right away.
438 ++NewValueCount;
439
440 NewValueLocation = SwiftParamCount;
441 }
442
443 ++SwiftParamCount;
444 } while (!Parameters.empty());
445
446 // Only instance subscripts are currently supported.
447 if (IsSubscript && !SelfLocation) {
448 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_subscript_invalid_parameter)
449 << AL << /*have a 'self:' parameter*/ 2;
450 return false;
451 }
452
453 IsSingleParamInit =
454 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
455
456 // Check the number of parameters for a getter/setter.
457 if (IsGetter || IsSetter) {
458 // Setters have one parameter for the new value.
459 unsigned NumExpectedParams = IsGetter ? 0 : 1;
460 unsigned ParamDiag = IsGetter
461 ? diag::warn_attr_swift_name_getter_parameters
462 : diag::warn_attr_swift_name_setter_parameters;
463
464 // Instance methods have one parameter for "self".
465 if (SelfLocation)
466 ++NumExpectedParams;
467
468 // Subscripts may have additional parameters beyond the expected params for
469 // the index.
470 if (IsSubscript) {
471 if (SwiftParamCount < NumExpectedParams) {
472 S.Diag(Loc, DiagID: ParamDiag) << AL;
473 return false;
474 }
475
476 // A subscript setter must explicitly label its newValue parameter to
477 // distinguish it from index parameters.
478 if (IsSetter) {
479 if (!NewValueLocation) {
480 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_subscript_setter_no_newValue)
481 << AL;
482 return false;
483 }
484 if (NewValueCount > 1) {
485 S.Diag(Loc,
486 DiagID: diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
487 << AL;
488 return false;
489 }
490 } else {
491 // Subscript getters should have no 'newValue:' parameter.
492 if (NewValueLocation) {
493 S.Diag(Loc, DiagID: diag::warn_attr_swift_name_subscript_getter_newValue)
494 << AL;
495 return false;
496 }
497 }
498 } else {
499 // Property accessors must have exactly the number of expected params.
500 if (SwiftParamCount != NumExpectedParams) {
501 S.Diag(Loc, DiagID: ParamDiag) << AL;
502 return false;
503 }
504 }
505 }
506
507 return true;
508}
509
510bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
511 const ParsedAttr &AL, bool IsAsync) {
512 if (isa<ObjCMethodDecl>(Val: D) || isa<FunctionDecl>(Val: D)) {
513 ArrayRef<ParmVarDecl *> Params;
514 unsigned ParamCount;
515
516 if (const auto *Method = dyn_cast<ObjCMethodDecl>(Val: D)) {
517 ParamCount = Method->getSelector().getNumArgs();
518 Params = Method->parameters().slice(N: 0, M: ParamCount);
519 } else {
520 const auto *F = cast<FunctionDecl>(Val: D);
521
522 ParamCount = F->getNumParams();
523 Params = F->parameters();
524
525 if (!F->hasWrittenPrototype()) {
526 Diag(Loc, DiagID: diag::warn_attribute_wrong_decl_type)
527 << AL << AL.isRegularKeywordAttribute()
528 << ExpectedFunctionWithProtoType;
529 return false;
530 }
531 }
532
533 // The async name drops the last callback parameter.
534 if (IsAsync) {
535 if (ParamCount == 0) {
536 Diag(Loc, DiagID: diag::warn_attr_swift_name_decl_missing_params)
537 << AL << isa<ObjCMethodDecl>(Val: D);
538 return false;
539 }
540 ParamCount -= 1;
541 }
542
543 unsigned SwiftParamCount;
544 bool IsSingleParamInit;
545 if (!validateSwiftFunctionName(S&: SemaRef, AL, Loc, Name, SwiftParamCount,
546 IsSingleParamInit))
547 return false;
548
549 bool ParamCountValid;
550 if (SwiftParamCount == ParamCount) {
551 ParamCountValid = true;
552 } else if (SwiftParamCount > ParamCount) {
553 ParamCountValid = IsSingleParamInit && ParamCount == 0;
554 } else {
555 // We have fewer Swift parameters than Objective-C parameters, but that
556 // might be because we've transformed some of them. Check for potential
557 // "out" parameters and err on the side of not warning.
558 unsigned MaybeOutParamCount =
559 llvm::count_if(Range&: Params, P: [](const ParmVarDecl *Param) -> bool {
560 QualType ParamTy = Param->getType();
561 if (ParamTy->isReferenceType() || ParamTy->isPointerType())
562 return !ParamTy->getPointeeType().isConstQualified();
563 return false;
564 });
565
566 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
567 }
568
569 if (!ParamCountValid) {
570 Diag(Loc, DiagID: diag::warn_attr_swift_name_num_params)
571 << (SwiftParamCount > ParamCount) << AL << ParamCount
572 << SwiftParamCount;
573 return false;
574 }
575 } else if ((isa<EnumConstantDecl>(Val: D) || isa<ObjCProtocolDecl>(Val: D) ||
576 isa<ObjCInterfaceDecl>(Val: D) || isa<ObjCPropertyDecl>(Val: D) ||
577 isa<VarDecl>(Val: D) || isa<TypedefNameDecl>(Val: D) || isa<TagDecl>(Val: D) ||
578 isa<IndirectFieldDecl>(Val: D) || isa<FieldDecl>(Val: D)) &&
579 !IsAsync) {
580 StringRef ContextName, BaseName;
581
582 std::tie(args&: ContextName, args&: BaseName) = Name.split(Separator: '.');
583 if (BaseName.empty()) {
584 BaseName = ContextName;
585 ContextName = StringRef();
586 } else if (!isValidAsciiIdentifier(S: ContextName)) {
587 Diag(Loc, DiagID: diag::warn_attr_swift_name_invalid_identifier)
588 << AL << /*context*/ 1;
589 return false;
590 }
591
592 if (!isValidAsciiIdentifier(S: BaseName)) {
593 Diag(Loc, DiagID: diag::warn_attr_swift_name_invalid_identifier)
594 << AL << /*basename*/ 0;
595 return false;
596 }
597 } else {
598 Diag(Loc, DiagID: diag::warn_attr_swift_name_decl_kind) << AL;
599 return false;
600 }
601 return true;
602}
603
604void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) {
605 StringRef Name;
606 SourceLocation Loc;
607 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str&: Name, ArgLocation: &Loc))
608 return;
609
610 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false))
611 return;
612
613 D->addAttr(A: ::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name));
614}
615
616void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) {
617 StringRef Name;
618 SourceLocation Loc;
619 if (!SemaRef.checkStringLiteralArgumentAttr(Attr: AL, ArgNum: 0, Str&: Name, ArgLocation: &Loc))
620 return;
621
622 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true))
623 return;
624
625 D->addAttr(A: ::new (getASTContext())
626 SwiftAsyncNameAttr(getASTContext(), AL, Name));
627}
628
629void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) {
630 // Make sure that there is an identifier as the annotation's single argument.
631 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 1))
632 return;
633
634 if (!AL.isArgIdent(Arg: 0)) {
635 Diag(Loc: AL.getLoc(), DiagID: diag::err_attribute_argument_type)
636 << AL << AANT_ArgumentIdentifier;
637 return;
638 }
639
640 SwiftNewTypeAttr::NewtypeKind Kind;
641 IdentifierInfo *II = AL.getArgAsIdent(Arg: 0)->Ident;
642 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(Val: II->getName(), Out&: Kind)) {
643 Diag(Loc: AL.getLoc(), DiagID: diag::warn_attribute_type_not_supported) << AL << II;
644 return;
645 }
646
647 if (!isa<TypedefNameDecl>(Val: D)) {
648 Diag(Loc: AL.getLoc(), DiagID: diag::warn_attribute_wrong_decl_type_str)
649 << AL << AL.isRegularKeywordAttribute() << "typedefs";
650 return;
651 }
652
653 D->addAttr(A: ::new (getASTContext())
654 SwiftNewTypeAttr(getASTContext(), AL, Kind));
655}
656
657void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) {
658 if (!AL.isArgIdent(Arg: 0)) {
659 Diag(Loc: AL.getLoc(), DiagID: diag::err_attribute_argument_n_type)
660 << AL << 1 << AANT_ArgumentIdentifier;
661 return;
662 }
663
664 SwiftAsyncAttr::Kind Kind;
665 IdentifierInfo *II = AL.getArgAsIdent(Arg: 0)->Ident;
666 if (!SwiftAsyncAttr::ConvertStrToKind(Val: II->getName(), Out&: Kind)) {
667 Diag(Loc: AL.getLoc(), DiagID: diag::err_swift_async_no_access) << AL << II;
668 return;
669 }
670
671 ParamIdx Idx;
672 if (Kind == SwiftAsyncAttr::None) {
673 // If this is 'none', then there shouldn't be any additional arguments.
674 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 1))
675 return;
676 } else {
677 // Non-none swift_async requires a completion handler index argument.
678 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 2))
679 return;
680
681 Expr *HandlerIdx = AL.getArgAsExpr(Arg: 1);
682 if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AI: AL, AttrArgNum: 2, IdxExpr: HandlerIdx, Idx))
683 return;
684
685 const ParmVarDecl *CompletionBlock =
686 getFunctionOrMethodParam(D, Idx: Idx.getASTIndex());
687 QualType CompletionBlockType = CompletionBlock->getType();
688 if (!CompletionBlockType->isBlockPointerType()) {
689 Diag(Loc: CompletionBlock->getLocation(), DiagID: diag::err_swift_async_bad_block_type)
690 << CompletionBlock->getType();
691 return;
692 }
693 QualType BlockTy =
694 CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
695 if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
696 Diag(Loc: CompletionBlock->getLocation(), DiagID: diag::err_swift_async_bad_block_type)
697 << CompletionBlock->getType();
698 return;
699 }
700 }
701
702 auto *AsyncAttr =
703 ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx);
704 D->addAttr(A: AsyncAttr);
705
706 if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
707 checkSwiftAsyncErrorBlock(S&: SemaRef, D, ErrorAttr, AsyncAttr);
708}
709
710void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
711 ParameterABI abi) {
712 ASTContext &Context = getASTContext();
713 QualType type = cast<ParmVarDecl>(Val: D)->getType();
714
715 if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
716 if (existingAttr->getABI() != abi) {
717 Diag(Loc: CI.getLoc(), DiagID: diag::err_attributes_are_not_compatible)
718 << getParameterABISpelling(kind: abi) << existingAttr
719 << (CI.isRegularKeywordAttribute() ||
720 existingAttr->isRegularKeywordAttribute());
721 Diag(Loc: existingAttr->getLocation(), DiagID: diag::note_conflicting_attribute);
722 return;
723 }
724 }
725
726 switch (abi) {
727 case ParameterABI::Ordinary:
728 llvm_unreachable("explicit attribute for ordinary parameter ABI?");
729
730 case ParameterABI::SwiftContext:
731 if (!isValidSwiftContextType(Ty: type)) {
732 Diag(Loc: CI.getLoc(), DiagID: diag::err_swift_abi_parameter_wrong_type)
733 << getParameterABISpelling(kind: abi) << /*pointer to pointer */ 0 << type;
734 }
735 D->addAttr(A: ::new (Context) SwiftContextAttr(Context, CI));
736 return;
737
738 case ParameterABI::SwiftAsyncContext:
739 if (!isValidSwiftContextType(Ty: type)) {
740 Diag(Loc: CI.getLoc(), DiagID: diag::err_swift_abi_parameter_wrong_type)
741 << getParameterABISpelling(kind: abi) << /*pointer to pointer */ 0 << type;
742 }
743 D->addAttr(A: ::new (Context) SwiftAsyncContextAttr(Context, CI));
744 return;
745
746 case ParameterABI::SwiftErrorResult:
747 if (!isValidSwiftErrorResultType(Ty: type)) {
748 Diag(Loc: CI.getLoc(), DiagID: diag::err_swift_abi_parameter_wrong_type)
749 << getParameterABISpelling(kind: abi) << /*pointer to pointer */ 1 << type;
750 }
751 D->addAttr(A: ::new (Context) SwiftErrorResultAttr(Context, CI));
752 return;
753
754 case ParameterABI::SwiftIndirectResult:
755 if (!isValidSwiftIndirectResultType(Ty: type)) {
756 Diag(Loc: CI.getLoc(), DiagID: diag::err_swift_abi_parameter_wrong_type)
757 << getParameterABISpelling(kind: abi) << /*pointer*/ 0 << type;
758 }
759 D->addAttr(A: ::new (Context) SwiftIndirectResultAttr(Context, CI));
760 return;
761 }
762 llvm_unreachable("bad parameter ABI attribute");
763}
764
765} // namespace clang
766