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