clang 22.0.0git
SemaSwift.cpp
Go to the documentation of this file.
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
14#include "clang/AST/DeclBase.h"
18#include "clang/Sema/Attr.h"
20#include "clang/Sema/Sema.h"
21#include "clang/Sema/SemaObjC.h"
22
23namespace clang {
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(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
31 << PrevSNA << &SNA
32 << (PrevSNA->isRegularKeywordAttribute() ||
33 SNA.isRegularKeywordAttribute());
34 Diag(SNA.getLoc(), 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.
44 if (!Ty->hasPointerRepresentation())
45 return Ty->isDependentType();
47}
48
49/// Pointers and references in the default address space.
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.
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(ContextNameComponents, '.');
79 return all_of(ContextNameComponents, [&](StringRef Component) {
80 return isValidAsciiIdentifier(Component);
81 });
82}
83
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(AL, 0, Str)) {
92 AL.setInvalid();
93 return;
94 }
95
96 D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str));
97}
98
100 // Make sure that there is a string literal as the annotation's single
101 // argument.
102 StringRef 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(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
111 return;
112 }
113
114 D->addAttr(::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 (auto *RD = PT->getPointeeType()->getAsRecordDecl();
133 RD && S.ObjC().isCFError(RD))
134 return true;
135
136 return false;
137}
138
140 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
141 for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
143 return true;
144 }
145
146 S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
147 << AL << isa<ObjCMethodDecl>(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.
156 if (RT->hasPointerRepresentation() && !RT->isReferenceType())
157 return true;
158
159 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
160 << AL << AL.getArgAsIdent(0)->getIdentifierInfo()->getName()
161 << isa<ObjCMethodDecl>(D) << /*pointer*/ 1;
162 return false;
163 };
164
165 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
167 if (RT->isIntegralType(S.Context))
168 return true;
169
170 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
171 << AL << AL.getArgAsIdent(0)->getIdentifierInfo()->getName()
172 << isa<ObjCMethodDecl>(D) << /*integral*/ 0;
173 return false;
174 };
175
176 if (D->isInvalidDecl())
177 return;
178
180 SwiftErrorAttr::ConventionKind Convention;
181 if (!SwiftErrorAttr::ConvertStrToConventionKind(
182 Loc->getIdentifierInfo()->getName(), Convention)) {
183 Diag(AL.getLoc(), 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(::new (getASTContext())
211 SwiftErrorAttr(getASTContext(), AL, Convention));
212}
213
215 const SwiftAsyncErrorAttr *ErrorAttr,
216 const SwiftAsyncAttr *AsyncAttr) {
217 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
218 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
219 S.Diag(AsyncAttr->getLocation(),
220 diag::err_swift_async_error_without_swift_async)
221 << AsyncAttr << isa<ObjCMethodDecl>(D);
222 }
223 return;
224 }
225
226 const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
227 D, 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()
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(ErrorAttr->getLocation(),
244 diag::err_attribute_argument_out_of_bounds)
245 << ErrorAttr << 2;
246 return;
247 }
248 QualType ErrorParam = BlockParams[ParamIdx - 1];
249 if (!ErrorParam->isIntegralType(S.Context)) {
250 StringRef ConvStr =
251 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
252 ? "zero_argument"
253 : "nonzero_argument";
254 S.Diag(ErrorAttr->getLocation(), 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 (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl();
275 RD && S.ObjC().isCFError(RD)) {
276 AnyErrorParams = true;
277 break;
278 }
279 }
280 }
281
282 if (!AnyErrorParams) {
283 S.Diag(ErrorAttr->getLocation(),
284 diag::err_swift_async_error_no_error_parameter)
285 << ErrorAttr << isa<ObjCMethodDecl>(D);
286 return;
287 }
288 break;
289 }
290 case SwiftAsyncErrorAttr::None:
291 break;
292 }
293}
294
296 IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
297 SwiftAsyncErrorAttr::ConventionKind ConvKind;
298 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(
299 IDLoc->getIdentifierInfo()->getName(), ConvKind)) {
300 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
301 << AL << IDLoc->getIdentifierInfo();
302 return;
303 }
304
305 uint32_t ParamIdx = 0;
306 switch (ConvKind) {
307 case SwiftAsyncErrorAttr::ZeroArgument:
308 case SwiftAsyncErrorAttr::NonZeroArgument: {
309 if (!AL.checkExactlyNumArgs(SemaRef, 2))
310 return;
311
312 Expr *IdxExpr = AL.getArgAsExpr(1);
313 if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx))
314 return;
315 break;
316 }
317 case SwiftAsyncErrorAttr::NonNullError:
318 case SwiftAsyncErrorAttr::None: {
319 if (!AL.checkExactlyNumArgs(SemaRef, 1))
320 return;
321 break;
322 }
323 }
324
325 auto *ErrorAttr = ::new (getASTContext())
326 SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx);
327 D->addAttr(ErrorAttr);
328
329 if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
330 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
331}
332
333// For a function, this will validate a compound Swift name, e.g.
334// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
335// the function will output the number of parameter names, and whether this is a
336// single-arg initializer.
337//
338// For a type, enum constant, property, or variable declaration, this will
339// validate either a simple identifier, or a qualified
340// <code>context.identifier</code> name.
341static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
342 SourceLocation Loc, StringRef Name,
343 unsigned &SwiftParamCount,
344 bool &IsSingleParamInit) {
345 SwiftParamCount = 0;
346 IsSingleParamInit = false;
347
348 // Check whether this will be mapped to a getter or setter of a property.
349 bool IsGetter = false, IsSetter = false;
350 if (Name.consume_front("getter:"))
351 IsGetter = true;
352 else if (Name.consume_front("setter:"))
353 IsSetter = true;
354
355 if (Name.back() != ')') {
356 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
357 return false;
358 }
359
360 bool IsMember = false;
361 StringRef ContextName, BaseName, Parameters;
362
363 std::tie(BaseName, Parameters) = Name.split('(');
364
365 // Split at the first '.', if it exists, which separates the context name
366 // from the base name.
367 std::tie(ContextName, BaseName) = BaseName.rsplit('.');
368 if (BaseName.empty()) {
369 BaseName = ContextName;
370 ContextName = StringRef();
371 } else if (ContextName.empty() || !isValidSwiftContextName(ContextName)) {
372 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
373 << AL << /*context*/ 1;
374 return false;
375 } else {
376 IsMember = true;
377 }
378
379 if (!isValidAsciiIdentifier(BaseName) || BaseName == "_") {
380 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
381 << AL << /*basename*/ 0;
382 return false;
383 }
384
385 bool IsSubscript = BaseName == "subscript";
386 // A subscript accessor must be a getter or setter.
387 if (IsSubscript && !IsGetter && !IsSetter) {
388 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
389 << AL << /* getter or setter */ 0;
390 return false;
391 }
392
393 if (Parameters.empty()) {
394 S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
395 return false;
396 }
397
398 assert(Parameters.back() == ')' && "expected ')'");
399 Parameters = Parameters.drop_back(); // ')'
400
401 if (Parameters.empty()) {
402 // Setters and subscripts must have at least one parameter.
403 if (IsSubscript) {
404 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
405 << AL << /* have at least one parameter */ 1;
406 return false;
407 }
408
409 if (IsSetter) {
410 S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
411 return false;
412 }
413
414 return true;
415 }
416
417 if (Parameters.back() != ':') {
418 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
419 return false;
420 }
421
422 StringRef CurrentParam;
423 std::optional<unsigned> SelfLocation;
424 unsigned NewValueCount = 0;
425 std::optional<unsigned> NewValueLocation;
426 do {
427 std::tie(CurrentParam, Parameters) = Parameters.split(':');
428
429 if (!isValidAsciiIdentifier(CurrentParam)) {
430 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
431 << AL << /*parameter*/ 2;
432 return false;
433 }
434
435 if (IsMember && CurrentParam == "self") {
436 // "self" indicates the "self" argument for a member.
437
438 // More than one "self"?
439 if (SelfLocation) {
440 S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
441 return false;
442 }
443
444 // The "self" location is the current parameter.
445 SelfLocation = SwiftParamCount;
446 } else if (CurrentParam == "newValue") {
447 // "newValue" indicates the "newValue" argument for a setter.
448
449 // There should only be one 'newValue', but it's only significant for
450 // subscript accessors, so don't error right away.
451 ++NewValueCount;
452
453 NewValueLocation = SwiftParamCount;
454 }
455
456 ++SwiftParamCount;
457 } while (!Parameters.empty());
458
459 // Only instance subscripts are currently supported.
460 if (IsSubscript && !SelfLocation) {
461 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
462 << AL << /*have a 'self:' parameter*/ 2;
463 return false;
464 }
465
466 IsSingleParamInit =
467 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
468
469 // Check the number of parameters for a getter/setter.
470 if (IsGetter || IsSetter) {
471 // Setters have one parameter for the new value.
472 unsigned NumExpectedParams = IsGetter ? 0 : 1;
473 unsigned ParamDiag = IsGetter
474 ? diag::warn_attr_swift_name_getter_parameters
475 : diag::warn_attr_swift_name_setter_parameters;
476
477 // Instance methods have one parameter for "self".
478 if (SelfLocation)
479 ++NumExpectedParams;
480
481 // Subscripts may have additional parameters beyond the expected params for
482 // the index.
483 if (IsSubscript) {
484 if (SwiftParamCount < NumExpectedParams) {
485 S.Diag(Loc, ParamDiag) << AL;
486 return false;
487 }
488
489 // A subscript setter must explicitly label its newValue parameter to
490 // distinguish it from index parameters.
491 if (IsSetter) {
492 if (!NewValueLocation) {
493 S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
494 << AL;
495 return false;
496 }
497 if (NewValueCount > 1) {
498 S.Diag(Loc,
499 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
500 << AL;
501 return false;
502 }
503 } else {
504 // Subscript getters should have no 'newValue:' parameter.
505 if (NewValueLocation) {
506 S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
507 << AL;
508 return false;
509 }
510 }
511 } else {
512 // Property accessors must have exactly the number of expected params.
513 if (SwiftParamCount != NumExpectedParams) {
514 S.Diag(Loc, ParamDiag) << AL;
515 return false;
516 }
517 }
518 }
519
520 return true;
521}
522
524 const ParsedAttr &AL, bool IsAsync) {
525 if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
527 unsigned ParamCount;
528
529 if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
530 ParamCount = Method->getSelector().getNumArgs();
531 Params = Method->parameters().slice(0, ParamCount);
532 } else {
533 const auto *F = cast<FunctionDecl>(D);
534
535 ParamCount = F->getNumParams();
536 Params = F->parameters();
537
538 if (!F->hasWrittenPrototype()) {
539 Diag(Loc, diag::warn_attribute_wrong_decl_type)
540 << AL << AL.isRegularKeywordAttribute()
542 return false;
543 }
544 }
545
546 // The async name drops the last callback parameter.
547 if (IsAsync) {
548 if (ParamCount == 0) {
549 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
550 << AL << isa<ObjCMethodDecl>(D);
551 return false;
552 }
553 ParamCount -= 1;
554 }
555
556 unsigned SwiftParamCount;
557 bool IsSingleParamInit;
558 if (!validateSwiftFunctionName(SemaRef, AL, Loc, Name, SwiftParamCount,
559 IsSingleParamInit))
560 return false;
561
562 bool ParamCountValid;
563 if (SwiftParamCount == ParamCount) {
564 ParamCountValid = true;
565 } else if (SwiftParamCount > ParamCount) {
566 ParamCountValid = IsSingleParamInit && ParamCount == 0;
567 } else {
568 // We have fewer Swift parameters than Objective-C parameters, but that
569 // might be because we've transformed some of them. Check for potential
570 // "out" parameters and err on the side of not warning.
571 unsigned MaybeOutParamCount =
572 llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {
573 QualType ParamTy = Param->getType();
574 if (ParamTy->isReferenceType() || ParamTy->isPointerType())
575 return !ParamTy->getPointeeType().isConstQualified();
576 return false;
577 });
578
579 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
580 }
581
582 if (!ParamCountValid) {
583 Diag(Loc, diag::warn_attr_swift_name_num_params)
584 << (SwiftParamCount > ParamCount) << AL << ParamCount
585 << SwiftParamCount;
586 return false;
587 }
588 } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
589 isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
590 isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
591 isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
592 !IsAsync) {
593 StringRef ContextName, BaseName;
594
595 std::tie(ContextName, BaseName) = Name.rsplit('.');
596 if (BaseName.empty()) {
597 BaseName = ContextName;
598 ContextName = StringRef();
599 } else if (!isValidSwiftContextName(ContextName)) {
600 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
601 << AL << /*context*/ 1;
602 return false;
603 }
604
605 if (!isValidAsciiIdentifier(BaseName)) {
606 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
607 << AL << /*basename*/ 0;
608 return false;
609 }
610 } else {
611 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
612 return false;
613 }
614 return true;
615}
616
618 StringRef Name;
620 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
621 return;
622
623 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false))
624 return;
625
626 D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name));
627}
628
630 StringRef Name;
632 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
633 return;
634
635 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true))
636 return;
637
638 D->addAttr(::new (getASTContext())
639 SwiftAsyncNameAttr(getASTContext(), AL, Name));
640}
641
643 // Make sure that there is an identifier as the annotation's single argument.
644 if (!AL.checkExactlyNumArgs(SemaRef, 1))
645 return;
646
647 if (!AL.isArgIdent(0)) {
648 Diag(AL.getLoc(), diag::err_attribute_argument_type)
650 return;
651 }
652
653 SwiftNewTypeAttr::NewtypeKind Kind;
655 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
656 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
657 return;
658 }
659
660 if (!isa<TypedefNameDecl>(D)) {
661 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
663 return;
664 }
665
666 D->addAttr(::new (getASTContext())
667 SwiftNewTypeAttr(getASTContext(), AL, Kind));
668}
669
671 if (!AL.isArgIdent(0)) {
672 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
673 << AL << 1 << AANT_ArgumentIdentifier;
674 return;
675 }
676
677 SwiftAsyncAttr::Kind Kind;
679 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
680 Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
681 return;
682 }
683
684 ParamIdx Idx;
685 if (Kind == SwiftAsyncAttr::None) {
686 // If this is 'none', then there shouldn't be any additional arguments.
687 if (!AL.checkExactlyNumArgs(SemaRef, 1))
688 return;
689 } else {
690 // Non-none swift_async requires a completion handler index argument.
691 if (!AL.checkExactlyNumArgs(SemaRef, 2))
692 return;
693
694 Expr *HandlerIdx = AL.getArgAsExpr(1);
695 if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))
696 return;
697
698 const ParmVarDecl *CompletionBlock =
700 QualType CompletionBlockType = CompletionBlock->getType();
701 if (!CompletionBlockType->isBlockPointerType()) {
702 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
703 << CompletionBlock->getType();
704 return;
705 }
706 QualType BlockTy =
707 CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
708 if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
709 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
710 << CompletionBlock->getType();
711 return;
712 }
713 }
714
715 auto *AsyncAttr =
716 ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx);
717 D->addAttr(AsyncAttr);
718
719 if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
720 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
721}
722
724 ParameterABI abi) {
725 ASTContext &Context = getASTContext();
726 QualType type = cast<ParmVarDecl>(D)->getType();
727
728 if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
729 if (existingAttr->getABI() != abi) {
730 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
731 << getParameterABISpelling(abi) << existingAttr
732 << (CI.isRegularKeywordAttribute() ||
733 existingAttr->isRegularKeywordAttribute());
734 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
735 return;
736 }
737 }
738
739 switch (abi) {
742 llvm_unreachable("explicit attribute for non-swift parameter ABI?");
744 llvm_unreachable("explicit attribute for ordinary parameter ABI?");
745
748 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
749 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
750 }
751 D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
752 return;
753
756 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
757 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
758 }
759 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
760 return;
761
764 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
765 << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
766 }
767 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
768 return;
769
772 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
773 << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
774 }
775 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
776 return;
777 }
778 llvm_unreachable("bad parameter ABI attribute");
779}
780
781} // namespace clang
static char ID
Definition: Arena.cpp:183
const Decl * D
enum clang::sema::@1840::IndirectLocalPathEntry::EntryKind Kind
Expr * E
SourceLocation Loc
Definition: SemaObjC.cpp:754
This file declares semantic analysis for Objective-C.
This file declares semantic analysis functions specific to Swift.
Defines various enumerations that describe declaration and type specifiers.
static QualType getPointeeType(const MemRegion *R)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
SourceLocation getLoc() const
Pointer to a block type.
Definition: TypeBase.h:3558
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getLocation() const
Definition: DeclBase.h:439
This represents one expression.
Definition: Expr.h:112
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
QualType getReturnType() const
Definition: TypeBase.h:4818
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
IdentifierInfo * getIdentifierInfo() const
Represents a pointer to an Objective C object.
Definition: TypeBase.h:7961
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Definition: Attr.h:256
unsigned getASTIndex() const
Get the parameter index as it would normally be encoded at the AST level of representation: zero-orig...
Definition: Attr.h:335
A parameter attribute which changes the argument-passing ABI rule for the parameter.
Definition: Attr.h:237
Represents a parameter to a function.
Definition: Decl.h:1789
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:119
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:288
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:389
void setInvalid(bool b=true) const
Definition: ParsedAttr.h:345
bool isArgIdent(unsigned Arg) const
Definition: ParsedAttr.h:385
Expr * getArgAsExpr(unsigned Arg) const
Definition: ParsedAttr.h:383
bool isUsedAsTypeAttr() const
Definition: ParsedAttr.h:359
bool isInvalid() const
Definition: ParsedAttr.h:344
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
A (possibly-)qualified type.
Definition: TypeBase.h:937
LangAS getAddressSpace() const
Return the address space of this type.
Definition: TypeBase.h:8469
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: TypeBase.h:8383
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: TypeBase.h:8416
bool empty() const
Definition: TypeBase.h:647
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
bool isCFError(RecordDecl *D)
Definition: SemaObjC.cpp:1461
IdentifierInfo * getNSErrorIdent()
Retrieve the identifier "NSError".
Definition: SemaObjC.cpp:1265
void handleBridge(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:99
void handleAsyncAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:670
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...
Definition: SemaSwift.cpp:523
void handleAsyncName(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:629
SwiftNameAttr * mergeNameAttr(Decl *D, const SwiftNameAttr &SNA, StringRef Name)
Definition: SemaSwift.cpp:26
void handleNewType(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:642
SemaSwift(Sema &S)
Definition: SemaSwift.cpp:24
void handleError(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:139
void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI abi)
Definition: SemaSwift.cpp:723
void handleAsyncError(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:295
void handleName(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:617
void handleAttrAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaSwift.cpp:84
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis=false, bool CanIndexVariadicArguments=false)
Check if IdxExpr is a valid parameter index for a function or instance method D.
Definition: Sema.h:5099
ASTContext & Context
Definition: Sema.h:1276
SemaObjC & ObjC()
Definition: Sema.h:1483
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition: Sema.h:4819
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isVoidType() const
Definition: TypeBase.h:8936
bool isPointerType() const
Definition: TypeBase.h:8580
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2107
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: TypeBase.h:2800
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
Definition: TypeBase.h:9100
QualType getType() const
Definition: Decl.h:722
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, const SwiftAsyncErrorAttr *ErrorAttr, const SwiftAsyncAttr *AsyncAttr)
Definition: SemaSwift.cpp:214
@ ExpectedFunctionWithProtoType
Definition: ParsedAttr.h:1087
@ ExpectedTypedef
Definition: ParsedAttr.h:1094
static bool isValidSwiftErrorResultType(QualType Ty)
Pointers and references to pointers in the default address space.
Definition: SemaSwift.cpp:62
llvm::StringRef getParameterABISpelling(ParameterABI kind)
QualType getFunctionOrMethodResultType(const Decl *D)
Definition: Attr.h:98
static bool isValidSwiftContextName(StringRef ContextName)
Definition: SemaSwift.cpp:75
const ParmVarDecl * getFunctionOrMethodParam(const Decl *D, unsigned Idx)
Definition: Attr.h:72
static bool isErrorParameter(Sema &S, QualType QT)
Definition: SemaSwift.cpp:117
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
Definition: CharInfo.h:244
static bool isValidSwiftIndirectResultType(QualType Ty)
Pointers and references in the default address space.
Definition: SemaSwift.cpp:50
QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx)
Definition: Attr.h:83
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1067
ParameterABI
Kinds of parameter ABI.
Definition: Specifiers.h:378
@ SwiftAsyncContext
This parameter (which must have pointer type) uses the special Swift asynchronous context-pointer ABI...
@ SwiftErrorResult
This parameter (which must have pointer-to-pointer type) uses the special Swift error-result ABI trea...
@ Ordinary
This parameter uses ordinary ABI rules for its type.
@ SwiftIndirectResult
This parameter (which must have pointer type) is a Swift indirect result parameter.
@ SwiftContext
This parameter (which must have pointer type) uses the special Swift context-pointer ABI treatment.
static bool isValidSwiftContextType(QualType Ty)
Pointer-like types in the default address space.
Definition: SemaSwift.cpp:43
static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, StringRef Name, unsigned &SwiftParamCount, bool &IsSingleParamInit)
Definition: SemaSwift.cpp:341
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition: Attr.h:64
@ Other
Other implicit parameter.