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 23 namespace clang { 24 SemaSwift::SemaSwift(Sema &S) : SemaBase(S) {} 25 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); 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. 43 static 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. 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(); 57 } 58 return Ty.getAddressSpace() == LangAS::Default; 59 } 60 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(); 69 } 70 if (!Ty.getQualifiers().empty()) 71 return false; 72 return isValidSwiftContextType(Ty); 73 } 74 75 static 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 84 void 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(AL, 0, Str)) { 92 AL.setInvalid(); 93 return; 94 } 95 96 D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str)); 97 } 98 99 void 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(AL, 0, 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 117 static 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(RT->getDecl())) 134 return true; 135 136 return false; 137 } 138 139 void 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 214 static 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 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(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 (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { 275 if (S.ObjC().isCFError(RT->getDecl())) { 276 AnyErrorParams = true; 277 break; 278 } 279 } 280 } 281 } 282 283 if (!AnyErrorParams) { 284 S.Diag(ErrorAttr->getLocation(), 285 diag::err_swift_async_error_no_error_parameter) 286 << ErrorAttr << isa<ObjCMethodDecl>(D); 287 return; 288 } 289 break; 290 } 291 case SwiftAsyncErrorAttr::None: 292 break; 293 } 294 } 295 296 void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) { 297 IdentifierLoc *IDLoc = AL.getArgAsIdent(0); 298 SwiftAsyncErrorAttr::ConventionKind ConvKind; 299 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind( 300 IDLoc->getIdentifierInfo()->getName(), ConvKind)) { 301 Diag(AL.getLoc(), 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(SemaRef, 2)) 311 return; 312 313 Expr *IdxExpr = AL.getArgAsExpr(1); 314 if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx)) 315 return; 316 break; 317 } 318 case SwiftAsyncErrorAttr::NonNullError: 319 case SwiftAsyncErrorAttr::None: { 320 if (!AL.checkExactlyNumArgs(SemaRef, 1)) 321 return; 322 break; 323 } 324 } 325 326 auto *ErrorAttr = ::new (getASTContext()) 327 SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx); 328 D->addAttr(ErrorAttr); 329 330 if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>()) 331 checkSwiftAsyncErrorBlock(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. 342 static 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("getter:")) 352 IsGetter = true; 353 else if (Name.consume_front("setter:")) 354 IsSetter = true; 355 356 if (Name.back() != ')') { 357 S.Diag(Loc, 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(BaseName, Parameters) = Name.split('('); 365 366 // Split at the first '.', if it exists, which separates the context name 367 // from the base name. 368 std::tie(ContextName, BaseName) = BaseName.rsplit('.'); 369 if (BaseName.empty()) { 370 BaseName = ContextName; 371 ContextName = StringRef(); 372 } else if (ContextName.empty() || !isValidSwiftContextName(ContextName)) { 373 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 374 << AL << /*context*/ 1; 375 return false; 376 } else { 377 IsMember = true; 378 } 379 380 if (!isValidAsciiIdentifier(BaseName) || BaseName == "_") { 381 S.Diag(Loc, 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, 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, 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, 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, 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, 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(CurrentParam, Parameters) = Parameters.split(':'); 429 430 if (!isValidAsciiIdentifier(CurrentParam)) { 431 S.Diag(Loc, 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, 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, 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, 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, diag::warn_attr_swift_name_subscript_setter_no_newValue) 495 << AL; 496 return false; 497 } 498 if (NewValueCount > 1) { 499 S.Diag(Loc, 500 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, 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, ParamDiag) << AL; 516 return false; 517 } 518 } 519 } 520 521 return true; 522 } 523 524 bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc, 525 const ParsedAttr &AL, bool IsAsync) { 526 if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { 527 ArrayRef<ParmVarDecl *> Params; 528 unsigned ParamCount; 529 530 if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) { 531 ParamCount = Method->getSelector().getNumArgs(); 532 Params = Method->parameters().slice(0, ParamCount); 533 } else { 534 const auto *F = cast<FunctionDecl>(D); 535 536 ParamCount = F->getNumParams(); 537 Params = F->parameters(); 538 539 if (!F->hasWrittenPrototype()) { 540 Diag(Loc, 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, diag::warn_attr_swift_name_decl_missing_params) 551 << AL << isa<ObjCMethodDecl>(D); 552 return false; 553 } 554 ParamCount -= 1; 555 } 556 557 unsigned SwiftParamCount; 558 bool IsSingleParamInit; 559 if (!validateSwiftFunctionName(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(Params, [](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, diag::warn_attr_swift_name_num_params) 585 << (SwiftParamCount > ParamCount) << AL << ParamCount 586 << SwiftParamCount; 587 return false; 588 } 589 } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) || 590 isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) || 591 isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) || 592 isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) && 593 !IsAsync) { 594 StringRef ContextName, BaseName; 595 596 std::tie(ContextName, BaseName) = Name.rsplit('.'); 597 if (BaseName.empty()) { 598 BaseName = ContextName; 599 ContextName = StringRef(); 600 } else if (!isValidSwiftContextName(ContextName)) { 601 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 602 << AL << /*context*/ 1; 603 return false; 604 } 605 606 if (!isValidAsciiIdentifier(BaseName)) { 607 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 608 << AL << /*basename*/ 0; 609 return false; 610 } 611 } else { 612 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL; 613 return false; 614 } 615 return true; 616 } 617 618 void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) { 619 StringRef Name; 620 SourceLocation Loc; 621 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) 622 return; 623 624 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false)) 625 return; 626 627 D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name)); 628 } 629 630 void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) { 631 StringRef Name; 632 SourceLocation Loc; 633 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) 634 return; 635 636 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true)) 637 return; 638 639 D->addAttr(::new (getASTContext()) 640 SwiftAsyncNameAttr(getASTContext(), AL, Name)); 641 } 642 643 void 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(SemaRef, 1)) 646 return; 647 648 if (!AL.isArgIdent(0)) { 649 Diag(AL.getLoc(), diag::err_attribute_argument_type) 650 << AL << AANT_ArgumentIdentifier; 651 return; 652 } 653 654 SwiftNewTypeAttr::NewtypeKind Kind; 655 IdentifierInfo *II = AL.getArgAsIdent(0)->getIdentifierInfo(); 656 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) { 657 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 658 return; 659 } 660 661 if (!isa<TypedefNameDecl>(D)) { 662 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 663 << AL << AL.isRegularKeywordAttribute() << ExpectedTypedef; 664 return; 665 } 666 667 D->addAttr(::new (getASTContext()) 668 SwiftNewTypeAttr(getASTContext(), AL, Kind)); 669 } 670 671 void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) { 672 if (!AL.isArgIdent(0)) { 673 Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 674 << AL << 1 << AANT_ArgumentIdentifier; 675 return; 676 } 677 678 SwiftAsyncAttr::Kind Kind; 679 IdentifierInfo *II = AL.getArgAsIdent(0)->getIdentifierInfo(); 680 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) { 681 Diag(AL.getLoc(), 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(SemaRef, 1)) 689 return; 690 } else { 691 // Non-none swift_async requires a completion handler index argument. 692 if (!AL.checkExactlyNumArgs(SemaRef, 2)) 693 return; 694 695 Expr *HandlerIdx = AL.getArgAsExpr(1); 696 if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx)) 697 return; 698 699 const ParmVarDecl *CompletionBlock = 700 getFunctionOrMethodParam(D, Idx.getASTIndex()); 701 QualType CompletionBlockType = CompletionBlock->getType(); 702 if (!CompletionBlockType->isBlockPointerType()) { 703 Diag(CompletionBlock->getLocation(), 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(CompletionBlock->getLocation(), 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(AsyncAttr); 719 720 if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>()) 721 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr); 722 } 723 724 void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, 725 ParameterABI abi) { 726 ASTContext &Context = getASTContext(); 727 QualType type = cast<ParmVarDecl>(D)->getType(); 728 729 if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { 730 if (existingAttr->getABI() != abi) { 731 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible) 732 << getParameterABISpelling(abi) << existingAttr 733 << (CI.isRegularKeywordAttribute() || 734 existingAttr->isRegularKeywordAttribute()); 735 Diag(existingAttr->getLocation(), 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(type)) { 749 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 750 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; 751 } 752 D->addAttr(::new (Context) SwiftContextAttr(Context, CI)); 753 return; 754 755 case ParameterABI::SwiftAsyncContext: 756 if (!isValidSwiftContextType(type)) { 757 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 758 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; 759 } 760 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI)); 761 return; 762 763 case ParameterABI::SwiftErrorResult: 764 if (!isValidSwiftErrorResultType(type)) { 765 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 766 << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type; 767 } 768 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI)); 769 return; 770 771 case ParameterABI::SwiftIndirectResult: 772 if (!isValidSwiftIndirectResultType(type)) { 773 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 774 << getParameterABISpelling(abi) << /*pointer*/ 0 << type; 775 } 776 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI)); 777 return; 778 } 779 llvm_unreachable("bad parameter ABI attribute"); 780 } 781 782 } // namespace clang 783