[libc] Switch to using the generic `<gpuintrin.h>` implementations (#121810)
[llvm-project.git] / clang / lib / Sema / SemaSwift.cpp
blob24fdfb8e57dc3434dd3a94d0a9e1309444cf9bb7
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.
11 //===----------------------------------------------------------------------===//
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"
23 namespace clang {
24 SemaSwift::SemaSwift(Sema &S) : SemaBase(S) {}
26 SwiftNameAttr *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);
37 D->dropAttr<SwiftNameAttr>();
39 return ::new (getASTContext()) SwiftNameAttr(getASTContext(), SNA, Name);
42 /// Pointer-like types in the default address space.
43 static bool isValidSwiftContextType(QualType Ty) {
44 if (!Ty->hasPointerRepresentation())
45 return Ty->isDependentType();
46 return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
49 /// Pointers and references in the default address space.
50 static 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();
58 return Ty.getAddressSpace() == LangAS::Default;
61 /// Pointers and references to pointers in the default address space.
62 static 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();
70 if (!Ty.getQualifiers().empty())
71 return false;
72 return isValidSwiftContextType(Ty);
75 void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) {
76 if (AL.isInvalid() || AL.isUsedAsTypeAttr())
77 return;
79 // Make sure that there is a string literal as the annotation's single
80 // argument.
81 StringRef Str;
82 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str)) {
83 AL.setInvalid();
84 return;
87 D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str));
90 void SemaSwift::handleBridge(Decl *D, const ParsedAttr &AL) {
91 // Make sure that there is a string literal as the annotation's single
92 // argument.
93 StringRef BT;
94 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT))
95 return;
97 // Warn about duplicate attributes if they have different arguments, but drop
98 // any duplicate attributes regardless.
99 if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
100 if (Other->getSwiftType() != BT)
101 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
102 return;
105 D->addAttr(::new (getASTContext()) SwiftBridgeAttr(getASTContext(), AL, BT));
108 static bool isErrorParameter(Sema &S, QualType QT) {
109 const auto *PT = QT->getAs<PointerType>();
110 if (!PT)
111 return false;
113 QualType Pointee = PT->getPointeeType();
115 // Check for NSError**.
116 if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
117 if (const auto *ID = OPT->getInterfaceDecl())
118 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent())
119 return true;
121 // Check for CFError**.
122 if (const auto *PT = Pointee->getAs<PointerType>())
123 if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
124 if (S.ObjC().isCFError(RT->getDecl()))
125 return true;
127 return false;
130 void SemaSwift::handleError(Decl *D, const ParsedAttr &AL) {
131 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
132 for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
133 if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
134 return true;
137 S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
138 << AL << isa<ObjCMethodDecl>(D);
139 return false;
142 auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
143 // - C, ObjC, and block pointers are definitely okay.
144 // - References are definitely not okay.
145 // - nullptr_t is weird, but acceptable.
146 QualType RT = getFunctionOrMethodResultType(D);
147 if (RT->hasPointerRepresentation() && !RT->isReferenceType())
148 return true;
150 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
151 << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
152 << /*pointer*/ 1;
153 return false;
156 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
157 QualType RT = getFunctionOrMethodResultType(D);
158 if (RT->isIntegralType(S.Context))
159 return true;
161 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
162 << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
163 << /*integral*/ 0;
164 return false;
167 if (D->isInvalidDecl())
168 return;
170 IdentifierLoc *Loc = AL.getArgAsIdent(0);
171 SwiftErrorAttr::ConventionKind Convention;
172 if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
173 Convention)) {
174 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
175 << AL << Loc->Ident;
176 return;
179 switch (Convention) {
180 case SwiftErrorAttr::None:
181 // No additional validation required.
182 break;
184 case SwiftErrorAttr::NonNullError:
185 if (!hasErrorParameter(SemaRef, D, AL))
186 return;
187 break;
189 case SwiftErrorAttr::NullResult:
190 if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))
191 return;
192 break;
194 case SwiftErrorAttr::NonZeroResult:
195 case SwiftErrorAttr::ZeroResult:
196 if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))
197 return;
198 break;
201 D->addAttr(::new (getASTContext())
202 SwiftErrorAttr(getASTContext(), AL, Convention));
205 static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
206 const SwiftAsyncErrorAttr *ErrorAttr,
207 const SwiftAsyncAttr *AsyncAttr) {
208 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
209 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
210 S.Diag(AsyncAttr->getLocation(),
211 diag::err_swift_async_error_without_swift_async)
212 << AsyncAttr << isa<ObjCMethodDecl>(D);
214 return;
217 const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
218 D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
219 // handleSwiftAsyncAttr already verified the type is correct, so no need to
220 // double-check it here.
221 const auto *FuncTy = HandlerParam->getType()
222 ->castAs<BlockPointerType>()
223 ->getPointeeType()
224 ->getAs<FunctionProtoType>();
225 ArrayRef<QualType> BlockParams;
226 if (FuncTy)
227 BlockParams = FuncTy->getParamTypes();
229 switch (ErrorAttr->getConvention()) {
230 case SwiftAsyncErrorAttr::ZeroArgument:
231 case SwiftAsyncErrorAttr::NonZeroArgument: {
232 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
233 if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
234 S.Diag(ErrorAttr->getLocation(),
235 diag::err_attribute_argument_out_of_bounds)
236 << ErrorAttr << 2;
237 return;
239 QualType ErrorParam = BlockParams[ParamIdx - 1];
240 if (!ErrorParam->isIntegralType(S.Context)) {
241 StringRef ConvStr =
242 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
243 ? "zero_argument"
244 : "nonzero_argument";
245 S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
246 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
247 return;
249 break;
251 case SwiftAsyncErrorAttr::NonNullError: {
252 bool AnyErrorParams = false;
253 for (QualType Param : BlockParams) {
254 // Check for NSError *.
255 if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
256 if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
257 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) {
258 AnyErrorParams = true;
259 break;
263 // Check for CFError *.
264 if (const auto *PtrTy = Param->getAs<PointerType>()) {
265 if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
266 if (S.ObjC().isCFError(RT->getDecl())) {
267 AnyErrorParams = true;
268 break;
274 if (!AnyErrorParams) {
275 S.Diag(ErrorAttr->getLocation(),
276 diag::err_swift_async_error_no_error_parameter)
277 << ErrorAttr << isa<ObjCMethodDecl>(D);
278 return;
280 break;
282 case SwiftAsyncErrorAttr::None:
283 break;
287 void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) {
288 IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
289 SwiftAsyncErrorAttr::ConventionKind ConvKind;
290 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),
291 ConvKind)) {
292 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
293 << AL << IDLoc->Ident;
294 return;
297 uint32_t ParamIdx = 0;
298 switch (ConvKind) {
299 case SwiftAsyncErrorAttr::ZeroArgument:
300 case SwiftAsyncErrorAttr::NonZeroArgument: {
301 if (!AL.checkExactlyNumArgs(SemaRef, 2))
302 return;
304 Expr *IdxExpr = AL.getArgAsExpr(1);
305 if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx))
306 return;
307 break;
309 case SwiftAsyncErrorAttr::NonNullError:
310 case SwiftAsyncErrorAttr::None: {
311 if (!AL.checkExactlyNumArgs(SemaRef, 1))
312 return;
313 break;
317 auto *ErrorAttr = ::new (getASTContext())
318 SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx);
319 D->addAttr(ErrorAttr);
321 if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
322 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
325 // For a function, this will validate a compound Swift name, e.g.
326 // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
327 // the function will output the number of parameter names, and whether this is a
328 // single-arg initializer.
330 // For a type, enum constant, property, or variable declaration, this will
331 // validate either a simple identifier, or a qualified
332 // <code>context.identifier</code> name.
333 static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
334 SourceLocation Loc, StringRef Name,
335 unsigned &SwiftParamCount,
336 bool &IsSingleParamInit) {
337 SwiftParamCount = 0;
338 IsSingleParamInit = false;
340 // Check whether this will be mapped to a getter or setter of a property.
341 bool IsGetter = false, IsSetter = false;
342 if (Name.consume_front("getter:"))
343 IsGetter = true;
344 else if (Name.consume_front("setter:"))
345 IsSetter = true;
347 if (Name.back() != ')') {
348 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
349 return false;
352 bool IsMember = false;
353 StringRef ContextName, BaseName, Parameters;
355 std::tie(BaseName, Parameters) = Name.split('(');
357 // Split at the first '.', if it exists, which separates the context name
358 // from the base name.
359 std::tie(ContextName, BaseName) = BaseName.split('.');
360 if (BaseName.empty()) {
361 BaseName = ContextName;
362 ContextName = StringRef();
363 } else if (ContextName.empty() || !isValidAsciiIdentifier(ContextName)) {
364 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
365 << AL << /*context*/ 1;
366 return false;
367 } else {
368 IsMember = true;
371 if (!isValidAsciiIdentifier(BaseName) || BaseName == "_") {
372 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
373 << AL << /*basename*/ 0;
374 return false;
377 bool IsSubscript = BaseName == "subscript";
378 // A subscript accessor must be a getter or setter.
379 if (IsSubscript && !IsGetter && !IsSetter) {
380 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
381 << AL << /* getter or setter */ 0;
382 return false;
385 if (Parameters.empty()) {
386 S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
387 return false;
390 assert(Parameters.back() == ')' && "expected ')'");
391 Parameters = Parameters.drop_back(); // ')'
393 if (Parameters.empty()) {
394 // Setters and subscripts must have at least one parameter.
395 if (IsSubscript) {
396 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
397 << AL << /* have at least one parameter */ 1;
398 return false;
401 if (IsSetter) {
402 S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
403 return false;
406 return true;
409 if (Parameters.back() != ':') {
410 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
411 return false;
414 StringRef CurrentParam;
415 std::optional<unsigned> SelfLocation;
416 unsigned NewValueCount = 0;
417 std::optional<unsigned> NewValueLocation;
418 do {
419 std::tie(CurrentParam, Parameters) = Parameters.split(':');
421 if (!isValidAsciiIdentifier(CurrentParam)) {
422 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
423 << AL << /*parameter*/ 2;
424 return false;
427 if (IsMember && CurrentParam == "self") {
428 // "self" indicates the "self" argument for a member.
430 // More than one "self"?
431 if (SelfLocation) {
432 S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
433 return false;
436 // The "self" location is the current parameter.
437 SelfLocation = SwiftParamCount;
438 } else if (CurrentParam == "newValue") {
439 // "newValue" indicates the "newValue" argument for a setter.
441 // There should only be one 'newValue', but it's only significant for
442 // subscript accessors, so don't error right away.
443 ++NewValueCount;
445 NewValueLocation = SwiftParamCount;
448 ++SwiftParamCount;
449 } while (!Parameters.empty());
451 // Only instance subscripts are currently supported.
452 if (IsSubscript && !SelfLocation) {
453 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
454 << AL << /*have a 'self:' parameter*/ 2;
455 return false;
458 IsSingleParamInit =
459 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
461 // Check the number of parameters for a getter/setter.
462 if (IsGetter || IsSetter) {
463 // Setters have one parameter for the new value.
464 unsigned NumExpectedParams = IsGetter ? 0 : 1;
465 unsigned ParamDiag = IsGetter
466 ? diag::warn_attr_swift_name_getter_parameters
467 : diag::warn_attr_swift_name_setter_parameters;
469 // Instance methods have one parameter for "self".
470 if (SelfLocation)
471 ++NumExpectedParams;
473 // Subscripts may have additional parameters beyond the expected params for
474 // the index.
475 if (IsSubscript) {
476 if (SwiftParamCount < NumExpectedParams) {
477 S.Diag(Loc, ParamDiag) << AL;
478 return false;
481 // A subscript setter must explicitly label its newValue parameter to
482 // distinguish it from index parameters.
483 if (IsSetter) {
484 if (!NewValueLocation) {
485 S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
486 << AL;
487 return false;
489 if (NewValueCount > 1) {
490 S.Diag(Loc,
491 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
492 << AL;
493 return false;
495 } else {
496 // Subscript getters should have no 'newValue:' parameter.
497 if (NewValueLocation) {
498 S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
499 << AL;
500 return false;
503 } else {
504 // Property accessors must have exactly the number of expected params.
505 if (SwiftParamCount != NumExpectedParams) {
506 S.Diag(Loc, ParamDiag) << AL;
507 return false;
512 return true;
515 bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
516 const ParsedAttr &AL, bool IsAsync) {
517 if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
518 ArrayRef<ParmVarDecl *> Params;
519 unsigned ParamCount;
521 if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
522 ParamCount = Method->getSelector().getNumArgs();
523 Params = Method->parameters().slice(0, ParamCount);
524 } else {
525 const auto *F = cast<FunctionDecl>(D);
527 ParamCount = F->getNumParams();
528 Params = F->parameters();
530 if (!F->hasWrittenPrototype()) {
531 Diag(Loc, diag::warn_attribute_wrong_decl_type)
532 << AL << AL.isRegularKeywordAttribute()
533 << ExpectedFunctionWithProtoType;
534 return false;
538 // The async name drops the last callback parameter.
539 if (IsAsync) {
540 if (ParamCount == 0) {
541 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
542 << AL << isa<ObjCMethodDecl>(D);
543 return false;
545 ParamCount -= 1;
548 unsigned SwiftParamCount;
549 bool IsSingleParamInit;
550 if (!validateSwiftFunctionName(SemaRef, AL, Loc, Name, SwiftParamCount,
551 IsSingleParamInit))
552 return false;
554 bool ParamCountValid;
555 if (SwiftParamCount == ParamCount) {
556 ParamCountValid = true;
557 } else if (SwiftParamCount > ParamCount) {
558 ParamCountValid = IsSingleParamInit && ParamCount == 0;
559 } else {
560 // We have fewer Swift parameters than Objective-C parameters, but that
561 // might be because we've transformed some of them. Check for potential
562 // "out" parameters and err on the side of not warning.
563 unsigned MaybeOutParamCount =
564 llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {
565 QualType ParamTy = Param->getType();
566 if (ParamTy->isReferenceType() || ParamTy->isPointerType())
567 return !ParamTy->getPointeeType().isConstQualified();
568 return false;
571 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
574 if (!ParamCountValid) {
575 Diag(Loc, diag::warn_attr_swift_name_num_params)
576 << (SwiftParamCount > ParamCount) << AL << ParamCount
577 << SwiftParamCount;
578 return false;
580 } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
581 isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
582 isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
583 isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
584 !IsAsync) {
585 StringRef ContextName, BaseName;
587 std::tie(ContextName, BaseName) = Name.split('.');
588 if (BaseName.empty()) {
589 BaseName = ContextName;
590 ContextName = StringRef();
591 } else if (!isValidAsciiIdentifier(ContextName)) {
592 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
593 << AL << /*context*/ 1;
594 return false;
597 if (!isValidAsciiIdentifier(BaseName)) {
598 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
599 << AL << /*basename*/ 0;
600 return false;
602 } else {
603 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
604 return false;
606 return true;
609 void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) {
610 StringRef Name;
611 SourceLocation Loc;
612 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
613 return;
615 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false))
616 return;
618 D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name));
621 void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) {
622 StringRef Name;
623 SourceLocation Loc;
624 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
625 return;
627 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true))
628 return;
630 D->addAttr(::new (getASTContext())
631 SwiftAsyncNameAttr(getASTContext(), AL, Name));
634 void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) {
635 // Make sure that there is an identifier as the annotation's single argument.
636 if (!AL.checkExactlyNumArgs(SemaRef, 1))
637 return;
639 if (!AL.isArgIdent(0)) {
640 Diag(AL.getLoc(), diag::err_attribute_argument_type)
641 << AL << AANT_ArgumentIdentifier;
642 return;
645 SwiftNewTypeAttr::NewtypeKind Kind;
646 IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
647 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
648 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
649 return;
652 if (!isa<TypedefNameDecl>(D)) {
653 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
654 << AL << AL.isRegularKeywordAttribute() << "typedefs";
655 return;
658 D->addAttr(::new (getASTContext())
659 SwiftNewTypeAttr(getASTContext(), AL, Kind));
662 void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) {
663 if (!AL.isArgIdent(0)) {
664 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
665 << AL << 1 << AANT_ArgumentIdentifier;
666 return;
669 SwiftAsyncAttr::Kind Kind;
670 IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
671 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
672 Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
673 return;
676 ParamIdx Idx;
677 if (Kind == SwiftAsyncAttr::None) {
678 // If this is 'none', then there shouldn't be any additional arguments.
679 if (!AL.checkExactlyNumArgs(SemaRef, 1))
680 return;
681 } else {
682 // Non-none swift_async requires a completion handler index argument.
683 if (!AL.checkExactlyNumArgs(SemaRef, 2))
684 return;
686 Expr *HandlerIdx = AL.getArgAsExpr(1);
687 if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))
688 return;
690 const ParmVarDecl *CompletionBlock =
691 getFunctionOrMethodParam(D, Idx.getASTIndex());
692 QualType CompletionBlockType = CompletionBlock->getType();
693 if (!CompletionBlockType->isBlockPointerType()) {
694 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
695 << CompletionBlock->getType();
696 return;
698 QualType BlockTy =
699 CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
700 if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
701 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
702 << CompletionBlock->getType();
703 return;
707 auto *AsyncAttr =
708 ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx);
709 D->addAttr(AsyncAttr);
711 if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
712 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
715 void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
716 ParameterABI abi) {
717 ASTContext &Context = getASTContext();
718 QualType type = cast<ParmVarDecl>(D)->getType();
720 if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
721 if (existingAttr->getABI() != abi) {
722 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
723 << getParameterABISpelling(abi) << existingAttr
724 << (CI.isRegularKeywordAttribute() ||
725 existingAttr->isRegularKeywordAttribute());
726 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
727 return;
731 switch (abi) {
732 case ParameterABI::HLSLOut:
733 case ParameterABI::HLSLInOut:
734 llvm_unreachable("explicit attribute for non-swift parameter ABI?");
735 case ParameterABI::Ordinary:
736 llvm_unreachable("explicit attribute for ordinary parameter ABI?");
738 case ParameterABI::SwiftContext:
739 if (!isValidSwiftContextType(type)) {
740 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
741 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
743 D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
744 return;
746 case ParameterABI::SwiftAsyncContext:
747 if (!isValidSwiftContextType(type)) {
748 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
749 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
751 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
752 return;
754 case ParameterABI::SwiftErrorResult:
755 if (!isValidSwiftErrorResultType(type)) {
756 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
757 << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
759 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
760 return;
762 case ParameterABI::SwiftIndirectResult:
763 if (!isValidSwiftIndirectResultType(type)) {
764 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
765 << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
767 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
768 return;
770 llvm_unreachable("bad parameter ABI attribute");
773 } // namespace clang