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