782 lines · cpp
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-exception6//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(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)31 << PrevSNA << &SNA32 << (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.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(ContextNameComponents, '.');79 return all_of(ContextNameComponents, [&](StringRef Component) {80 return isValidAsciiIdentifier(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 single89 // 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 99void SemaSwift::handleBridge(Decl *D, const ParsedAttr &AL) {100 // Make sure that there is a string literal as the annotation's single101 // argument.102 StringRef BT;103 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT))104 return;105 106 // Warn about duplicate attributes if they have different arguments, but drop107 // 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 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, getFunctionOrMethodParamType(D, 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.155 QualType RT = getFunctionOrMethodResultType(D);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 {166 QualType RT = getFunctionOrMethodResultType(D);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 179 IdentifierLoc *Loc = AL.getArgAsIdent(0);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 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(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 to229 // 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(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::ZeroArgument252 ? "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 295void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) {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>, and335// the function will output the number of parameter names, and whether this is a336// single-arg initializer.337//338// For a type, enum constant, property, or variable declaration, this will339// validate either a simple identifier, or a qualified340// <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.empty() || 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 name366 // 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 for450 // 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 = IsGetter474 ? diag::warn_attr_swift_name_getter_parameters475 : 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 for482 // 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 to490 // 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 523bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,524 const ParsedAttr &AL, bool IsAsync) {525 if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {526 ArrayRef<ParmVarDecl *> Params;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()541 << ExpectedFunctionWithProtoType;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 that569 // might be because we've transformed some of them. Check for potential570 // "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 << ParamCount585 << 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 617void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) {618 StringRef Name;619 SourceLocation Loc;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 629void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) {630 StringRef Name;631 SourceLocation Loc;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 642void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) {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)649 << AL << AANT_ArgumentIdentifier;650 return;651 }652 653 SwiftNewTypeAttr::NewtypeKind Kind;654 IdentifierInfo *II = AL.getArgAsIdent(0)->getIdentifierInfo();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)662 << AL << AL.isRegularKeywordAttribute() << ExpectedTypedef;663 return;664 }665 666 D->addAttr(::new (getASTContext())667 SwiftNewTypeAttr(getASTContext(), AL, Kind));668}669 670void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) {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;678 IdentifierInfo *II = AL.getArgAsIdent(0)->getIdentifierInfo();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 =699 getFunctionOrMethodParam(D, Idx.getASTIndex());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 723void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,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) << existingAttr732 << (CI.isRegularKeywordAttribute() ||733 existingAttr->isRegularKeywordAttribute());734 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);735 return;736 }737 }738 739 switch (abi) {740 case ParameterABI::HLSLOut:741 case ParameterABI::HLSLInOut:742 llvm_unreachable("explicit attribute for non-swift parameter ABI?");743 case ParameterABI::Ordinary:744 llvm_unreachable("explicit attribute for ordinary parameter ABI?");745 746 case ParameterABI::SwiftContext:747 if (!isValidSwiftContextType(type)) {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 754 case ParameterABI::SwiftAsyncContext:755 if (!isValidSwiftContextType(type)) {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 762 case ParameterABI::SwiftErrorResult:763 if (!isValidSwiftErrorResultType(type)) {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 770 case ParameterABI::SwiftIndirectResult:771 if (!isValidSwiftIndirectResultType(type)) {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 clang782