16b755b0cSVlad Serebrennikov //===------ SemaSwift.cpp ------ Swift language-specific routines ---------===// 26b755b0cSVlad Serebrennikov // 36b755b0cSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46b755b0cSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information. 56b755b0cSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66b755b0cSVlad Serebrennikov // 76b755b0cSVlad Serebrennikov //===----------------------------------------------------------------------===// 86b755b0cSVlad Serebrennikov // 96b755b0cSVlad Serebrennikov // This file implements semantic analysis functions specific to Swift. 106b755b0cSVlad Serebrennikov // 116b755b0cSVlad Serebrennikov //===----------------------------------------------------------------------===// 126b755b0cSVlad Serebrennikov 136b755b0cSVlad Serebrennikov #include "clang/Sema/SemaSwift.h" 146b755b0cSVlad Serebrennikov #include "clang/AST/DeclBase.h" 156b755b0cSVlad Serebrennikov #include "clang/Basic/AttributeCommonInfo.h" 166b755b0cSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h" 176b755b0cSVlad Serebrennikov #include "clang/Basic/Specifiers.h" 186b755b0cSVlad Serebrennikov #include "clang/Sema/Attr.h" 196b755b0cSVlad Serebrennikov #include "clang/Sema/ParsedAttr.h" 206b755b0cSVlad Serebrennikov #include "clang/Sema/Sema.h" 216b755b0cSVlad Serebrennikov #include "clang/Sema/SemaObjC.h" 226b755b0cSVlad Serebrennikov 236b755b0cSVlad Serebrennikov namespace clang { 246b755b0cSVlad Serebrennikov SemaSwift::SemaSwift(Sema &S) : SemaBase(S) {} 256b755b0cSVlad Serebrennikov 266b755b0cSVlad Serebrennikov SwiftNameAttr *SemaSwift::mergeNameAttr(Decl *D, const SwiftNameAttr &SNA, 276b755b0cSVlad Serebrennikov StringRef Name) { 286b755b0cSVlad Serebrennikov if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) { 296b755b0cSVlad Serebrennikov if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) { 306b755b0cSVlad Serebrennikov Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible) 316b755b0cSVlad Serebrennikov << PrevSNA << &SNA 326b755b0cSVlad Serebrennikov << (PrevSNA->isRegularKeywordAttribute() || 336b755b0cSVlad Serebrennikov SNA.isRegularKeywordAttribute()); 346b755b0cSVlad Serebrennikov Diag(SNA.getLoc(), diag::note_conflicting_attribute); 356b755b0cSVlad Serebrennikov } 366b755b0cSVlad Serebrennikov 376b755b0cSVlad Serebrennikov D->dropAttr<SwiftNameAttr>(); 386b755b0cSVlad Serebrennikov } 396b755b0cSVlad Serebrennikov return ::new (getASTContext()) SwiftNameAttr(getASTContext(), SNA, Name); 406b755b0cSVlad Serebrennikov } 416b755b0cSVlad Serebrennikov 426b755b0cSVlad Serebrennikov /// Pointer-like types in the default address space. 436b755b0cSVlad Serebrennikov static bool isValidSwiftContextType(QualType Ty) { 446b755b0cSVlad Serebrennikov if (!Ty->hasPointerRepresentation()) 456b755b0cSVlad Serebrennikov return Ty->isDependentType(); 466b755b0cSVlad Serebrennikov return Ty->getPointeeType().getAddressSpace() == LangAS::Default; 476b755b0cSVlad Serebrennikov } 486b755b0cSVlad Serebrennikov 496b755b0cSVlad Serebrennikov /// Pointers and references in the default address space. 506b755b0cSVlad Serebrennikov static bool isValidSwiftIndirectResultType(QualType Ty) { 516b755b0cSVlad Serebrennikov if (const auto *PtrType = Ty->getAs<PointerType>()) { 526b755b0cSVlad Serebrennikov Ty = PtrType->getPointeeType(); 536b755b0cSVlad Serebrennikov } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { 546b755b0cSVlad Serebrennikov Ty = RefType->getPointeeType(); 556b755b0cSVlad Serebrennikov } else { 566b755b0cSVlad Serebrennikov return Ty->isDependentType(); 576b755b0cSVlad Serebrennikov } 586b755b0cSVlad Serebrennikov return Ty.getAddressSpace() == LangAS::Default; 596b755b0cSVlad Serebrennikov } 606b755b0cSVlad Serebrennikov 616b755b0cSVlad Serebrennikov /// Pointers and references to pointers in the default address space. 626b755b0cSVlad Serebrennikov static bool isValidSwiftErrorResultType(QualType Ty) { 636b755b0cSVlad Serebrennikov if (const auto *PtrType = Ty->getAs<PointerType>()) { 646b755b0cSVlad Serebrennikov Ty = PtrType->getPointeeType(); 656b755b0cSVlad Serebrennikov } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { 666b755b0cSVlad Serebrennikov Ty = RefType->getPointeeType(); 676b755b0cSVlad Serebrennikov } else { 686b755b0cSVlad Serebrennikov return Ty->isDependentType(); 696b755b0cSVlad Serebrennikov } 706b755b0cSVlad Serebrennikov if (!Ty.getQualifiers().empty()) 716b755b0cSVlad Serebrennikov return false; 726b755b0cSVlad Serebrennikov return isValidSwiftContextType(Ty); 736b755b0cSVlad Serebrennikov } 746b755b0cSVlad Serebrennikov 756b755b0cSVlad Serebrennikov void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) { 76d3daa3c4SPavel Yaskevich if (AL.isInvalid() || AL.isUsedAsTypeAttr()) 77d3daa3c4SPavel Yaskevich return; 78d3daa3c4SPavel Yaskevich 796b755b0cSVlad Serebrennikov // Make sure that there is a string literal as the annotation's single 806b755b0cSVlad Serebrennikov // argument. 816b755b0cSVlad Serebrennikov StringRef Str; 82d3daa3c4SPavel Yaskevich if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str)) { 83d3daa3c4SPavel Yaskevich AL.setInvalid(); 846b755b0cSVlad Serebrennikov return; 85d3daa3c4SPavel Yaskevich } 866b755b0cSVlad Serebrennikov 876b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str)); 886b755b0cSVlad Serebrennikov } 896b755b0cSVlad Serebrennikov 906b755b0cSVlad Serebrennikov void SemaSwift::handleBridge(Decl *D, const ParsedAttr &AL) { 916b755b0cSVlad Serebrennikov // Make sure that there is a string literal as the annotation's single 926b755b0cSVlad Serebrennikov // argument. 936b755b0cSVlad Serebrennikov StringRef BT; 946b755b0cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT)) 956b755b0cSVlad Serebrennikov return; 966b755b0cSVlad Serebrennikov 976b755b0cSVlad Serebrennikov // Warn about duplicate attributes if they have different arguments, but drop 986b755b0cSVlad Serebrennikov // any duplicate attributes regardless. 996b755b0cSVlad Serebrennikov if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) { 1006b755b0cSVlad Serebrennikov if (Other->getSwiftType() != BT) 1016b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; 1026b755b0cSVlad Serebrennikov return; 1036b755b0cSVlad Serebrennikov } 1046b755b0cSVlad Serebrennikov 1056b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) SwiftBridgeAttr(getASTContext(), AL, BT)); 1066b755b0cSVlad Serebrennikov } 1076b755b0cSVlad Serebrennikov 1086b755b0cSVlad Serebrennikov static bool isErrorParameter(Sema &S, QualType QT) { 1096b755b0cSVlad Serebrennikov const auto *PT = QT->getAs<PointerType>(); 1106b755b0cSVlad Serebrennikov if (!PT) 1116b755b0cSVlad Serebrennikov return false; 1126b755b0cSVlad Serebrennikov 1136b755b0cSVlad Serebrennikov QualType Pointee = PT->getPointeeType(); 1146b755b0cSVlad Serebrennikov 1156b755b0cSVlad Serebrennikov // Check for NSError**. 1166b755b0cSVlad Serebrennikov if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>()) 1176b755b0cSVlad Serebrennikov if (const auto *ID = OPT->getInterfaceDecl()) 1186b755b0cSVlad Serebrennikov if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) 1196b755b0cSVlad Serebrennikov return true; 1206b755b0cSVlad Serebrennikov 1216b755b0cSVlad Serebrennikov // Check for CFError**. 1226b755b0cSVlad Serebrennikov if (const auto *PT = Pointee->getAs<PointerType>()) 1236b755b0cSVlad Serebrennikov if (const auto *RT = PT->getPointeeType()->getAs<RecordType>()) 1246b755b0cSVlad Serebrennikov if (S.ObjC().isCFError(RT->getDecl())) 1256b755b0cSVlad Serebrennikov return true; 1266b755b0cSVlad Serebrennikov 1276b755b0cSVlad Serebrennikov return false; 1286b755b0cSVlad Serebrennikov } 1296b755b0cSVlad Serebrennikov 1306b755b0cSVlad Serebrennikov void SemaSwift::handleError(Decl *D, const ParsedAttr &AL) { 1316b755b0cSVlad Serebrennikov auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { 1326b755b0cSVlad Serebrennikov for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) { 1336b755b0cSVlad Serebrennikov if (isErrorParameter(S, getFunctionOrMethodParamType(D, I))) 1346b755b0cSVlad Serebrennikov return true; 1356b755b0cSVlad Serebrennikov } 1366b755b0cSVlad Serebrennikov 1376b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter) 1386b755b0cSVlad Serebrennikov << AL << isa<ObjCMethodDecl>(D); 1396b755b0cSVlad Serebrennikov return false; 1406b755b0cSVlad Serebrennikov }; 1416b755b0cSVlad Serebrennikov 1426b755b0cSVlad Serebrennikov auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { 1436b755b0cSVlad Serebrennikov // - C, ObjC, and block pointers are definitely okay. 1446b755b0cSVlad Serebrennikov // - References are definitely not okay. 1456b755b0cSVlad Serebrennikov // - nullptr_t is weird, but acceptable. 1466b755b0cSVlad Serebrennikov QualType RT = getFunctionOrMethodResultType(D); 1476b755b0cSVlad Serebrennikov if (RT->hasPointerRepresentation() && !RT->isReferenceType()) 1486b755b0cSVlad Serebrennikov return true; 1496b755b0cSVlad Serebrennikov 1506b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) 1516b755b0cSVlad Serebrennikov << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) 1526b755b0cSVlad Serebrennikov << /*pointer*/ 1; 1536b755b0cSVlad Serebrennikov return false; 1546b755b0cSVlad Serebrennikov }; 1556b755b0cSVlad Serebrennikov 1566b755b0cSVlad Serebrennikov auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { 1576b755b0cSVlad Serebrennikov QualType RT = getFunctionOrMethodResultType(D); 1586b755b0cSVlad Serebrennikov if (RT->isIntegralType(S.Context)) 1596b755b0cSVlad Serebrennikov return true; 1606b755b0cSVlad Serebrennikov 1616b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) 1626b755b0cSVlad Serebrennikov << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) 1636b755b0cSVlad Serebrennikov << /*integral*/ 0; 1646b755b0cSVlad Serebrennikov return false; 1656b755b0cSVlad Serebrennikov }; 1666b755b0cSVlad Serebrennikov 1676b755b0cSVlad Serebrennikov if (D->isInvalidDecl()) 1686b755b0cSVlad Serebrennikov return; 1696b755b0cSVlad Serebrennikov 1706b755b0cSVlad Serebrennikov IdentifierLoc *Loc = AL.getArgAsIdent(0); 1716b755b0cSVlad Serebrennikov SwiftErrorAttr::ConventionKind Convention; 1726b755b0cSVlad Serebrennikov if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(), 1736b755b0cSVlad Serebrennikov Convention)) { 1746b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) 1756b755b0cSVlad Serebrennikov << AL << Loc->Ident; 1766b755b0cSVlad Serebrennikov return; 1776b755b0cSVlad Serebrennikov } 1786b755b0cSVlad Serebrennikov 1796b755b0cSVlad Serebrennikov switch (Convention) { 1806b755b0cSVlad Serebrennikov case SwiftErrorAttr::None: 1816b755b0cSVlad Serebrennikov // No additional validation required. 1826b755b0cSVlad Serebrennikov break; 1836b755b0cSVlad Serebrennikov 1846b755b0cSVlad Serebrennikov case SwiftErrorAttr::NonNullError: 1856b755b0cSVlad Serebrennikov if (!hasErrorParameter(SemaRef, D, AL)) 1866b755b0cSVlad Serebrennikov return; 1876b755b0cSVlad Serebrennikov break; 1886b755b0cSVlad Serebrennikov 1896b755b0cSVlad Serebrennikov case SwiftErrorAttr::NullResult: 1906b755b0cSVlad Serebrennikov if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL)) 1916b755b0cSVlad Serebrennikov return; 1926b755b0cSVlad Serebrennikov break; 1936b755b0cSVlad Serebrennikov 1946b755b0cSVlad Serebrennikov case SwiftErrorAttr::NonZeroResult: 1956b755b0cSVlad Serebrennikov case SwiftErrorAttr::ZeroResult: 1966b755b0cSVlad Serebrennikov if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL)) 1976b755b0cSVlad Serebrennikov return; 1986b755b0cSVlad Serebrennikov break; 1996b755b0cSVlad Serebrennikov } 2006b755b0cSVlad Serebrennikov 2016b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 2026b755b0cSVlad Serebrennikov SwiftErrorAttr(getASTContext(), AL, Convention)); 2036b755b0cSVlad Serebrennikov } 2046b755b0cSVlad Serebrennikov 2056b755b0cSVlad Serebrennikov static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, 2066b755b0cSVlad Serebrennikov const SwiftAsyncErrorAttr *ErrorAttr, 2076b755b0cSVlad Serebrennikov const SwiftAsyncAttr *AsyncAttr) { 2086b755b0cSVlad Serebrennikov if (AsyncAttr->getKind() == SwiftAsyncAttr::None) { 2096b755b0cSVlad Serebrennikov if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) { 2106b755b0cSVlad Serebrennikov S.Diag(AsyncAttr->getLocation(), 2116b755b0cSVlad Serebrennikov diag::err_swift_async_error_without_swift_async) 2126b755b0cSVlad Serebrennikov << AsyncAttr << isa<ObjCMethodDecl>(D); 2136b755b0cSVlad Serebrennikov } 2146b755b0cSVlad Serebrennikov return; 2156b755b0cSVlad Serebrennikov } 2166b755b0cSVlad Serebrennikov 2176b755b0cSVlad Serebrennikov const ParmVarDecl *HandlerParam = getFunctionOrMethodParam( 2186b755b0cSVlad Serebrennikov D, AsyncAttr->getCompletionHandlerIndex().getASTIndex()); 2196b755b0cSVlad Serebrennikov // handleSwiftAsyncAttr already verified the type is correct, so no need to 2206b755b0cSVlad Serebrennikov // double-check it here. 2216b755b0cSVlad Serebrennikov const auto *FuncTy = HandlerParam->getType() 2226b755b0cSVlad Serebrennikov ->castAs<BlockPointerType>() 2236b755b0cSVlad Serebrennikov ->getPointeeType() 2246b755b0cSVlad Serebrennikov ->getAs<FunctionProtoType>(); 2256b755b0cSVlad Serebrennikov ArrayRef<QualType> BlockParams; 2266b755b0cSVlad Serebrennikov if (FuncTy) 2276b755b0cSVlad Serebrennikov BlockParams = FuncTy->getParamTypes(); 2286b755b0cSVlad Serebrennikov 2296b755b0cSVlad Serebrennikov switch (ErrorAttr->getConvention()) { 2306b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::ZeroArgument: 2316b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::NonZeroArgument: { 2326b755b0cSVlad Serebrennikov uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx(); 2336b755b0cSVlad Serebrennikov if (ParamIdx == 0 || ParamIdx > BlockParams.size()) { 2346b755b0cSVlad Serebrennikov S.Diag(ErrorAttr->getLocation(), 2356b755b0cSVlad Serebrennikov diag::err_attribute_argument_out_of_bounds) 2366b755b0cSVlad Serebrennikov << ErrorAttr << 2; 2376b755b0cSVlad Serebrennikov return; 2386b755b0cSVlad Serebrennikov } 2396b755b0cSVlad Serebrennikov QualType ErrorParam = BlockParams[ParamIdx - 1]; 2406b755b0cSVlad Serebrennikov if (!ErrorParam->isIntegralType(S.Context)) { 2416b755b0cSVlad Serebrennikov StringRef ConvStr = 2426b755b0cSVlad Serebrennikov ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument 2436b755b0cSVlad Serebrennikov ? "zero_argument" 2446b755b0cSVlad Serebrennikov : "nonzero_argument"; 2456b755b0cSVlad Serebrennikov S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral) 2466b755b0cSVlad Serebrennikov << ErrorAttr << ConvStr << ParamIdx << ErrorParam; 2476b755b0cSVlad Serebrennikov return; 2486b755b0cSVlad Serebrennikov } 2496b755b0cSVlad Serebrennikov break; 2506b755b0cSVlad Serebrennikov } 2516b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::NonNullError: { 2526b755b0cSVlad Serebrennikov bool AnyErrorParams = false; 2536b755b0cSVlad Serebrennikov for (QualType Param : BlockParams) { 2546b755b0cSVlad Serebrennikov // Check for NSError *. 2556b755b0cSVlad Serebrennikov if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) { 2566b755b0cSVlad Serebrennikov if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) { 2576b755b0cSVlad Serebrennikov if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) { 2586b755b0cSVlad Serebrennikov AnyErrorParams = true; 2596b755b0cSVlad Serebrennikov break; 2606b755b0cSVlad Serebrennikov } 2616b755b0cSVlad Serebrennikov } 2626b755b0cSVlad Serebrennikov } 2636b755b0cSVlad Serebrennikov // Check for CFError *. 2646b755b0cSVlad Serebrennikov if (const auto *PtrTy = Param->getAs<PointerType>()) { 2656b755b0cSVlad Serebrennikov if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { 2666b755b0cSVlad Serebrennikov if (S.ObjC().isCFError(RT->getDecl())) { 2676b755b0cSVlad Serebrennikov AnyErrorParams = true; 2686b755b0cSVlad Serebrennikov break; 2696b755b0cSVlad Serebrennikov } 2706b755b0cSVlad Serebrennikov } 2716b755b0cSVlad Serebrennikov } 2726b755b0cSVlad Serebrennikov } 2736b755b0cSVlad Serebrennikov 2746b755b0cSVlad Serebrennikov if (!AnyErrorParams) { 2756b755b0cSVlad Serebrennikov S.Diag(ErrorAttr->getLocation(), 2766b755b0cSVlad Serebrennikov diag::err_swift_async_error_no_error_parameter) 2776b755b0cSVlad Serebrennikov << ErrorAttr << isa<ObjCMethodDecl>(D); 2786b755b0cSVlad Serebrennikov return; 2796b755b0cSVlad Serebrennikov } 2806b755b0cSVlad Serebrennikov break; 2816b755b0cSVlad Serebrennikov } 2826b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::None: 2836b755b0cSVlad Serebrennikov break; 2846b755b0cSVlad Serebrennikov } 2856b755b0cSVlad Serebrennikov } 2866b755b0cSVlad Serebrennikov 2876b755b0cSVlad Serebrennikov void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) { 2886b755b0cSVlad Serebrennikov IdentifierLoc *IDLoc = AL.getArgAsIdent(0); 2896b755b0cSVlad Serebrennikov SwiftAsyncErrorAttr::ConventionKind ConvKind; 2906b755b0cSVlad Serebrennikov if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(), 2916b755b0cSVlad Serebrennikov ConvKind)) { 2926b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) 2936b755b0cSVlad Serebrennikov << AL << IDLoc->Ident; 2946b755b0cSVlad Serebrennikov return; 2956b755b0cSVlad Serebrennikov } 2966b755b0cSVlad Serebrennikov 2976b755b0cSVlad Serebrennikov uint32_t ParamIdx = 0; 2986b755b0cSVlad Serebrennikov switch (ConvKind) { 2996b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::ZeroArgument: 3006b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::NonZeroArgument: { 3016b755b0cSVlad Serebrennikov if (!AL.checkExactlyNumArgs(SemaRef, 2)) 3026b755b0cSVlad Serebrennikov return; 3036b755b0cSVlad Serebrennikov 3046b755b0cSVlad Serebrennikov Expr *IdxExpr = AL.getArgAsExpr(1); 3056b755b0cSVlad Serebrennikov if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx)) 3066b755b0cSVlad Serebrennikov return; 3076b755b0cSVlad Serebrennikov break; 3086b755b0cSVlad Serebrennikov } 3096b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::NonNullError: 3106b755b0cSVlad Serebrennikov case SwiftAsyncErrorAttr::None: { 3116b755b0cSVlad Serebrennikov if (!AL.checkExactlyNumArgs(SemaRef, 1)) 3126b755b0cSVlad Serebrennikov return; 3136b755b0cSVlad Serebrennikov break; 3146b755b0cSVlad Serebrennikov } 3156b755b0cSVlad Serebrennikov } 3166b755b0cSVlad Serebrennikov 3176b755b0cSVlad Serebrennikov auto *ErrorAttr = ::new (getASTContext()) 3186b755b0cSVlad Serebrennikov SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx); 3196b755b0cSVlad Serebrennikov D->addAttr(ErrorAttr); 3206b755b0cSVlad Serebrennikov 3216b755b0cSVlad Serebrennikov if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>()) 3226b755b0cSVlad Serebrennikov checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr); 3236b755b0cSVlad Serebrennikov } 3246b755b0cSVlad Serebrennikov 3256b755b0cSVlad Serebrennikov // For a function, this will validate a compound Swift name, e.g. 3266b755b0cSVlad Serebrennikov // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and 3276b755b0cSVlad Serebrennikov // the function will output the number of parameter names, and whether this is a 3286b755b0cSVlad Serebrennikov // single-arg initializer. 3296b755b0cSVlad Serebrennikov // 3306b755b0cSVlad Serebrennikov // For a type, enum constant, property, or variable declaration, this will 3316b755b0cSVlad Serebrennikov // validate either a simple identifier, or a qualified 3326b755b0cSVlad Serebrennikov // <code>context.identifier</code> name. 3336b755b0cSVlad Serebrennikov static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, 3346b755b0cSVlad Serebrennikov SourceLocation Loc, StringRef Name, 3356b755b0cSVlad Serebrennikov unsigned &SwiftParamCount, 3366b755b0cSVlad Serebrennikov bool &IsSingleParamInit) { 3376b755b0cSVlad Serebrennikov SwiftParamCount = 0; 3386b755b0cSVlad Serebrennikov IsSingleParamInit = false; 3396b755b0cSVlad Serebrennikov 3406b755b0cSVlad Serebrennikov // Check whether this will be mapped to a getter or setter of a property. 3416b755b0cSVlad Serebrennikov bool IsGetter = false, IsSetter = false; 3426b755b0cSVlad Serebrennikov if (Name.consume_front("getter:")) 3436b755b0cSVlad Serebrennikov IsGetter = true; 3446b755b0cSVlad Serebrennikov else if (Name.consume_front("setter:")) 3456b755b0cSVlad Serebrennikov IsSetter = true; 3466b755b0cSVlad Serebrennikov 3476b755b0cSVlad Serebrennikov if (Name.back() != ')') { 3486b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; 3496b755b0cSVlad Serebrennikov return false; 3506b755b0cSVlad Serebrennikov } 3516b755b0cSVlad Serebrennikov 3526b755b0cSVlad Serebrennikov bool IsMember = false; 3536b755b0cSVlad Serebrennikov StringRef ContextName, BaseName, Parameters; 3546b755b0cSVlad Serebrennikov 3556b755b0cSVlad Serebrennikov std::tie(BaseName, Parameters) = Name.split('('); 3566b755b0cSVlad Serebrennikov 3576b755b0cSVlad Serebrennikov // Split at the first '.', if it exists, which separates the context name 3586b755b0cSVlad Serebrennikov // from the base name. 3596b755b0cSVlad Serebrennikov std::tie(ContextName, BaseName) = BaseName.split('.'); 3606b755b0cSVlad Serebrennikov if (BaseName.empty()) { 3616b755b0cSVlad Serebrennikov BaseName = ContextName; 3626b755b0cSVlad Serebrennikov ContextName = StringRef(); 3636b755b0cSVlad Serebrennikov } else if (ContextName.empty() || !isValidAsciiIdentifier(ContextName)) { 3646b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 3656b755b0cSVlad Serebrennikov << AL << /*context*/ 1; 3666b755b0cSVlad Serebrennikov return false; 3676b755b0cSVlad Serebrennikov } else { 3686b755b0cSVlad Serebrennikov IsMember = true; 3696b755b0cSVlad Serebrennikov } 3706b755b0cSVlad Serebrennikov 3716b755b0cSVlad Serebrennikov if (!isValidAsciiIdentifier(BaseName) || BaseName == "_") { 3726b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 3736b755b0cSVlad Serebrennikov << AL << /*basename*/ 0; 3746b755b0cSVlad Serebrennikov return false; 3756b755b0cSVlad Serebrennikov } 3766b755b0cSVlad Serebrennikov 3776b755b0cSVlad Serebrennikov bool IsSubscript = BaseName == "subscript"; 3786b755b0cSVlad Serebrennikov // A subscript accessor must be a getter or setter. 3796b755b0cSVlad Serebrennikov if (IsSubscript && !IsGetter && !IsSetter) { 3806b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) 3816b755b0cSVlad Serebrennikov << AL << /* getter or setter */ 0; 3826b755b0cSVlad Serebrennikov return false; 3836b755b0cSVlad Serebrennikov } 3846b755b0cSVlad Serebrennikov 3856b755b0cSVlad Serebrennikov if (Parameters.empty()) { 3866b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL; 3876b755b0cSVlad Serebrennikov return false; 3886b755b0cSVlad Serebrennikov } 3896b755b0cSVlad Serebrennikov 3906b755b0cSVlad Serebrennikov assert(Parameters.back() == ')' && "expected ')'"); 3916b755b0cSVlad Serebrennikov Parameters = Parameters.drop_back(); // ')' 3926b755b0cSVlad Serebrennikov 3936b755b0cSVlad Serebrennikov if (Parameters.empty()) { 3946b755b0cSVlad Serebrennikov // Setters and subscripts must have at least one parameter. 3956b755b0cSVlad Serebrennikov if (IsSubscript) { 3966b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) 3976b755b0cSVlad Serebrennikov << AL << /* have at least one parameter */ 1; 3986b755b0cSVlad Serebrennikov return false; 3996b755b0cSVlad Serebrennikov } 4006b755b0cSVlad Serebrennikov 4016b755b0cSVlad Serebrennikov if (IsSetter) { 4026b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL; 4036b755b0cSVlad Serebrennikov return false; 4046b755b0cSVlad Serebrennikov } 4056b755b0cSVlad Serebrennikov 4066b755b0cSVlad Serebrennikov return true; 4076b755b0cSVlad Serebrennikov } 4086b755b0cSVlad Serebrennikov 4096b755b0cSVlad Serebrennikov if (Parameters.back() != ':') { 4106b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; 4116b755b0cSVlad Serebrennikov return false; 4126b755b0cSVlad Serebrennikov } 4136b755b0cSVlad Serebrennikov 4146b755b0cSVlad Serebrennikov StringRef CurrentParam; 4156b755b0cSVlad Serebrennikov std::optional<unsigned> SelfLocation; 4166b755b0cSVlad Serebrennikov unsigned NewValueCount = 0; 4176b755b0cSVlad Serebrennikov std::optional<unsigned> NewValueLocation; 4186b755b0cSVlad Serebrennikov do { 4196b755b0cSVlad Serebrennikov std::tie(CurrentParam, Parameters) = Parameters.split(':'); 4206b755b0cSVlad Serebrennikov 4216b755b0cSVlad Serebrennikov if (!isValidAsciiIdentifier(CurrentParam)) { 4226b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 4236b755b0cSVlad Serebrennikov << AL << /*parameter*/ 2; 4246b755b0cSVlad Serebrennikov return false; 4256b755b0cSVlad Serebrennikov } 4266b755b0cSVlad Serebrennikov 4276b755b0cSVlad Serebrennikov if (IsMember && CurrentParam == "self") { 4286b755b0cSVlad Serebrennikov // "self" indicates the "self" argument for a member. 4296b755b0cSVlad Serebrennikov 4306b755b0cSVlad Serebrennikov // More than one "self"? 4316b755b0cSVlad Serebrennikov if (SelfLocation) { 4326b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL; 4336b755b0cSVlad Serebrennikov return false; 4346b755b0cSVlad Serebrennikov } 4356b755b0cSVlad Serebrennikov 4366b755b0cSVlad Serebrennikov // The "self" location is the current parameter. 4376b755b0cSVlad Serebrennikov SelfLocation = SwiftParamCount; 4386b755b0cSVlad Serebrennikov } else if (CurrentParam == "newValue") { 4396b755b0cSVlad Serebrennikov // "newValue" indicates the "newValue" argument for a setter. 4406b755b0cSVlad Serebrennikov 4416b755b0cSVlad Serebrennikov // There should only be one 'newValue', but it's only significant for 4426b755b0cSVlad Serebrennikov // subscript accessors, so don't error right away. 4436b755b0cSVlad Serebrennikov ++NewValueCount; 4446b755b0cSVlad Serebrennikov 4456b755b0cSVlad Serebrennikov NewValueLocation = SwiftParamCount; 4466b755b0cSVlad Serebrennikov } 4476b755b0cSVlad Serebrennikov 4486b755b0cSVlad Serebrennikov ++SwiftParamCount; 4496b755b0cSVlad Serebrennikov } while (!Parameters.empty()); 4506b755b0cSVlad Serebrennikov 4516b755b0cSVlad Serebrennikov // Only instance subscripts are currently supported. 4526b755b0cSVlad Serebrennikov if (IsSubscript && !SelfLocation) { 4536b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) 4546b755b0cSVlad Serebrennikov << AL << /*have a 'self:' parameter*/ 2; 4556b755b0cSVlad Serebrennikov return false; 4566b755b0cSVlad Serebrennikov } 4576b755b0cSVlad Serebrennikov 4586b755b0cSVlad Serebrennikov IsSingleParamInit = 4596b755b0cSVlad Serebrennikov SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_"; 4606b755b0cSVlad Serebrennikov 4616b755b0cSVlad Serebrennikov // Check the number of parameters for a getter/setter. 4626b755b0cSVlad Serebrennikov if (IsGetter || IsSetter) { 4636b755b0cSVlad Serebrennikov // Setters have one parameter for the new value. 4646b755b0cSVlad Serebrennikov unsigned NumExpectedParams = IsGetter ? 0 : 1; 4656b755b0cSVlad Serebrennikov unsigned ParamDiag = IsGetter 4666b755b0cSVlad Serebrennikov ? diag::warn_attr_swift_name_getter_parameters 4676b755b0cSVlad Serebrennikov : diag::warn_attr_swift_name_setter_parameters; 4686b755b0cSVlad Serebrennikov 4696b755b0cSVlad Serebrennikov // Instance methods have one parameter for "self". 4706b755b0cSVlad Serebrennikov if (SelfLocation) 4716b755b0cSVlad Serebrennikov ++NumExpectedParams; 4726b755b0cSVlad Serebrennikov 4736b755b0cSVlad Serebrennikov // Subscripts may have additional parameters beyond the expected params for 4746b755b0cSVlad Serebrennikov // the index. 4756b755b0cSVlad Serebrennikov if (IsSubscript) { 4766b755b0cSVlad Serebrennikov if (SwiftParamCount < NumExpectedParams) { 4776b755b0cSVlad Serebrennikov S.Diag(Loc, ParamDiag) << AL; 4786b755b0cSVlad Serebrennikov return false; 4796b755b0cSVlad Serebrennikov } 4806b755b0cSVlad Serebrennikov 4816b755b0cSVlad Serebrennikov // A subscript setter must explicitly label its newValue parameter to 4826b755b0cSVlad Serebrennikov // distinguish it from index parameters. 4836b755b0cSVlad Serebrennikov if (IsSetter) { 4846b755b0cSVlad Serebrennikov if (!NewValueLocation) { 4856b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue) 4866b755b0cSVlad Serebrennikov << AL; 4876b755b0cSVlad Serebrennikov return false; 4886b755b0cSVlad Serebrennikov } 4896b755b0cSVlad Serebrennikov if (NewValueCount > 1) { 4906b755b0cSVlad Serebrennikov S.Diag(Loc, 4916b755b0cSVlad Serebrennikov diag::warn_attr_swift_name_subscript_setter_multiple_newValues) 4926b755b0cSVlad Serebrennikov << AL; 4936b755b0cSVlad Serebrennikov return false; 4946b755b0cSVlad Serebrennikov } 4956b755b0cSVlad Serebrennikov } else { 4966b755b0cSVlad Serebrennikov // Subscript getters should have no 'newValue:' parameter. 4976b755b0cSVlad Serebrennikov if (NewValueLocation) { 4986b755b0cSVlad Serebrennikov S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue) 4996b755b0cSVlad Serebrennikov << AL; 5006b755b0cSVlad Serebrennikov return false; 5016b755b0cSVlad Serebrennikov } 5026b755b0cSVlad Serebrennikov } 5036b755b0cSVlad Serebrennikov } else { 5046b755b0cSVlad Serebrennikov // Property accessors must have exactly the number of expected params. 5056b755b0cSVlad Serebrennikov if (SwiftParamCount != NumExpectedParams) { 5066b755b0cSVlad Serebrennikov S.Diag(Loc, ParamDiag) << AL; 5076b755b0cSVlad Serebrennikov return false; 5086b755b0cSVlad Serebrennikov } 5096b755b0cSVlad Serebrennikov } 5106b755b0cSVlad Serebrennikov } 5116b755b0cSVlad Serebrennikov 5126b755b0cSVlad Serebrennikov return true; 5136b755b0cSVlad Serebrennikov } 5146b755b0cSVlad Serebrennikov 5156b755b0cSVlad Serebrennikov bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc, 5166b755b0cSVlad Serebrennikov const ParsedAttr &AL, bool IsAsync) { 5176b755b0cSVlad Serebrennikov if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { 5186b755b0cSVlad Serebrennikov ArrayRef<ParmVarDecl *> Params; 5196b755b0cSVlad Serebrennikov unsigned ParamCount; 5206b755b0cSVlad Serebrennikov 5216b755b0cSVlad Serebrennikov if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) { 5226b755b0cSVlad Serebrennikov ParamCount = Method->getSelector().getNumArgs(); 5236b755b0cSVlad Serebrennikov Params = Method->parameters().slice(0, ParamCount); 5246b755b0cSVlad Serebrennikov } else { 5256b755b0cSVlad Serebrennikov const auto *F = cast<FunctionDecl>(D); 5266b755b0cSVlad Serebrennikov 5276b755b0cSVlad Serebrennikov ParamCount = F->getNumParams(); 5286b755b0cSVlad Serebrennikov Params = F->parameters(); 5296b755b0cSVlad Serebrennikov 5306b755b0cSVlad Serebrennikov if (!F->hasWrittenPrototype()) { 5316b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attribute_wrong_decl_type) 5326b755b0cSVlad Serebrennikov << AL << AL.isRegularKeywordAttribute() 5336b755b0cSVlad Serebrennikov << ExpectedFunctionWithProtoType; 5346b755b0cSVlad Serebrennikov return false; 5356b755b0cSVlad Serebrennikov } 5366b755b0cSVlad Serebrennikov } 5376b755b0cSVlad Serebrennikov 5386b755b0cSVlad Serebrennikov // The async name drops the last callback parameter. 5396b755b0cSVlad Serebrennikov if (IsAsync) { 5406b755b0cSVlad Serebrennikov if (ParamCount == 0) { 5416b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attr_swift_name_decl_missing_params) 5426b755b0cSVlad Serebrennikov << AL << isa<ObjCMethodDecl>(D); 5436b755b0cSVlad Serebrennikov return false; 5446b755b0cSVlad Serebrennikov } 5456b755b0cSVlad Serebrennikov ParamCount -= 1; 5466b755b0cSVlad Serebrennikov } 5476b755b0cSVlad Serebrennikov 5486b755b0cSVlad Serebrennikov unsigned SwiftParamCount; 5496b755b0cSVlad Serebrennikov bool IsSingleParamInit; 5506b755b0cSVlad Serebrennikov if (!validateSwiftFunctionName(SemaRef, AL, Loc, Name, SwiftParamCount, 5516b755b0cSVlad Serebrennikov IsSingleParamInit)) 5526b755b0cSVlad Serebrennikov return false; 5536b755b0cSVlad Serebrennikov 5546b755b0cSVlad Serebrennikov bool ParamCountValid; 5556b755b0cSVlad Serebrennikov if (SwiftParamCount == ParamCount) { 5566b755b0cSVlad Serebrennikov ParamCountValid = true; 5576b755b0cSVlad Serebrennikov } else if (SwiftParamCount > ParamCount) { 5586b755b0cSVlad Serebrennikov ParamCountValid = IsSingleParamInit && ParamCount == 0; 5596b755b0cSVlad Serebrennikov } else { 5606b755b0cSVlad Serebrennikov // We have fewer Swift parameters than Objective-C parameters, but that 5616b755b0cSVlad Serebrennikov // might be because we've transformed some of them. Check for potential 5626b755b0cSVlad Serebrennikov // "out" parameters and err on the side of not warning. 5636b755b0cSVlad Serebrennikov unsigned MaybeOutParamCount = 5646b755b0cSVlad Serebrennikov llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool { 5656b755b0cSVlad Serebrennikov QualType ParamTy = Param->getType(); 5666b755b0cSVlad Serebrennikov if (ParamTy->isReferenceType() || ParamTy->isPointerType()) 5676b755b0cSVlad Serebrennikov return !ParamTy->getPointeeType().isConstQualified(); 5686b755b0cSVlad Serebrennikov return false; 5696b755b0cSVlad Serebrennikov }); 5706b755b0cSVlad Serebrennikov 5716b755b0cSVlad Serebrennikov ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount; 5726b755b0cSVlad Serebrennikov } 5736b755b0cSVlad Serebrennikov 5746b755b0cSVlad Serebrennikov if (!ParamCountValid) { 5756b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attr_swift_name_num_params) 5766b755b0cSVlad Serebrennikov << (SwiftParamCount > ParamCount) << AL << ParamCount 5776b755b0cSVlad Serebrennikov << SwiftParamCount; 5786b755b0cSVlad Serebrennikov return false; 5796b755b0cSVlad Serebrennikov } 5806b755b0cSVlad Serebrennikov } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) || 5816b755b0cSVlad Serebrennikov isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) || 5826b755b0cSVlad Serebrennikov isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) || 5836b755b0cSVlad Serebrennikov isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) && 5846b755b0cSVlad Serebrennikov !IsAsync) { 5856b755b0cSVlad Serebrennikov StringRef ContextName, BaseName; 5866b755b0cSVlad Serebrennikov 5876b755b0cSVlad Serebrennikov std::tie(ContextName, BaseName) = Name.split('.'); 5886b755b0cSVlad Serebrennikov if (BaseName.empty()) { 5896b755b0cSVlad Serebrennikov BaseName = ContextName; 5906b755b0cSVlad Serebrennikov ContextName = StringRef(); 5916b755b0cSVlad Serebrennikov } else if (!isValidAsciiIdentifier(ContextName)) { 5926b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 5936b755b0cSVlad Serebrennikov << AL << /*context*/ 1; 5946b755b0cSVlad Serebrennikov return false; 5956b755b0cSVlad Serebrennikov } 5966b755b0cSVlad Serebrennikov 5976b755b0cSVlad Serebrennikov if (!isValidAsciiIdentifier(BaseName)) { 5986b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) 5996b755b0cSVlad Serebrennikov << AL << /*basename*/ 0; 6006b755b0cSVlad Serebrennikov return false; 6016b755b0cSVlad Serebrennikov } 6026b755b0cSVlad Serebrennikov } else { 6036b755b0cSVlad Serebrennikov Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL; 6046b755b0cSVlad Serebrennikov return false; 6056b755b0cSVlad Serebrennikov } 6066b755b0cSVlad Serebrennikov return true; 6076b755b0cSVlad Serebrennikov } 6086b755b0cSVlad Serebrennikov 6096b755b0cSVlad Serebrennikov void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) { 6106b755b0cSVlad Serebrennikov StringRef Name; 6116b755b0cSVlad Serebrennikov SourceLocation Loc; 6126b755b0cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) 6136b755b0cSVlad Serebrennikov return; 6146b755b0cSVlad Serebrennikov 6156b755b0cSVlad Serebrennikov if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false)) 6166b755b0cSVlad Serebrennikov return; 6176b755b0cSVlad Serebrennikov 6186b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name)); 6196b755b0cSVlad Serebrennikov } 6206b755b0cSVlad Serebrennikov 6216b755b0cSVlad Serebrennikov void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) { 6226b755b0cSVlad Serebrennikov StringRef Name; 6236b755b0cSVlad Serebrennikov SourceLocation Loc; 6246b755b0cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) 6256b755b0cSVlad Serebrennikov return; 6266b755b0cSVlad Serebrennikov 6276b755b0cSVlad Serebrennikov if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true)) 6286b755b0cSVlad Serebrennikov return; 6296b755b0cSVlad Serebrennikov 6306b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 6316b755b0cSVlad Serebrennikov SwiftAsyncNameAttr(getASTContext(), AL, Name)); 6326b755b0cSVlad Serebrennikov } 6336b755b0cSVlad Serebrennikov 6346b755b0cSVlad Serebrennikov void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) { 6356b755b0cSVlad Serebrennikov // Make sure that there is an identifier as the annotation's single argument. 6366b755b0cSVlad Serebrennikov if (!AL.checkExactlyNumArgs(SemaRef, 1)) 6376b755b0cSVlad Serebrennikov return; 6386b755b0cSVlad Serebrennikov 6396b755b0cSVlad Serebrennikov if (!AL.isArgIdent(0)) { 6406b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_argument_type) 6416b755b0cSVlad Serebrennikov << AL << AANT_ArgumentIdentifier; 6426b755b0cSVlad Serebrennikov return; 6436b755b0cSVlad Serebrennikov } 6446b755b0cSVlad Serebrennikov 6456b755b0cSVlad Serebrennikov SwiftNewTypeAttr::NewtypeKind Kind; 6466b755b0cSVlad Serebrennikov IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 6476b755b0cSVlad Serebrennikov if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) { 6486b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; 6496b755b0cSVlad Serebrennikov return; 6506b755b0cSVlad Serebrennikov } 6516b755b0cSVlad Serebrennikov 6526b755b0cSVlad Serebrennikov if (!isa<TypedefNameDecl>(D)) { 653*41a94de7SMaksim Ivanov Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 654*41a94de7SMaksim Ivanov << AL << AL.isRegularKeywordAttribute() << ExpectedTypedef; 6556b755b0cSVlad Serebrennikov return; 6566b755b0cSVlad Serebrennikov } 6576b755b0cSVlad Serebrennikov 6586b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 6596b755b0cSVlad Serebrennikov SwiftNewTypeAttr(getASTContext(), AL, Kind)); 6606b755b0cSVlad Serebrennikov } 6616b755b0cSVlad Serebrennikov 6626b755b0cSVlad Serebrennikov void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) { 6636b755b0cSVlad Serebrennikov if (!AL.isArgIdent(0)) { 6646b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 6656b755b0cSVlad Serebrennikov << AL << 1 << AANT_ArgumentIdentifier; 6666b755b0cSVlad Serebrennikov return; 6676b755b0cSVlad Serebrennikov } 6686b755b0cSVlad Serebrennikov 6696b755b0cSVlad Serebrennikov SwiftAsyncAttr::Kind Kind; 6706b755b0cSVlad Serebrennikov IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; 6716b755b0cSVlad Serebrennikov if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) { 6726b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II; 6736b755b0cSVlad Serebrennikov return; 6746b755b0cSVlad Serebrennikov } 6756b755b0cSVlad Serebrennikov 6766b755b0cSVlad Serebrennikov ParamIdx Idx; 6776b755b0cSVlad Serebrennikov if (Kind == SwiftAsyncAttr::None) { 6786b755b0cSVlad Serebrennikov // If this is 'none', then there shouldn't be any additional arguments. 6796b755b0cSVlad Serebrennikov if (!AL.checkExactlyNumArgs(SemaRef, 1)) 6806b755b0cSVlad Serebrennikov return; 6816b755b0cSVlad Serebrennikov } else { 6826b755b0cSVlad Serebrennikov // Non-none swift_async requires a completion handler index argument. 6836b755b0cSVlad Serebrennikov if (!AL.checkExactlyNumArgs(SemaRef, 2)) 6846b755b0cSVlad Serebrennikov return; 6856b755b0cSVlad Serebrennikov 6866b755b0cSVlad Serebrennikov Expr *HandlerIdx = AL.getArgAsExpr(1); 6876b755b0cSVlad Serebrennikov if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx)) 6886b755b0cSVlad Serebrennikov return; 6896b755b0cSVlad Serebrennikov 6906b755b0cSVlad Serebrennikov const ParmVarDecl *CompletionBlock = 6916b755b0cSVlad Serebrennikov getFunctionOrMethodParam(D, Idx.getASTIndex()); 6926b755b0cSVlad Serebrennikov QualType CompletionBlockType = CompletionBlock->getType(); 6936b755b0cSVlad Serebrennikov if (!CompletionBlockType->isBlockPointerType()) { 6946b755b0cSVlad Serebrennikov Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type) 6956b755b0cSVlad Serebrennikov << CompletionBlock->getType(); 6966b755b0cSVlad Serebrennikov return; 6976b755b0cSVlad Serebrennikov } 6986b755b0cSVlad Serebrennikov QualType BlockTy = 6996b755b0cSVlad Serebrennikov CompletionBlockType->castAs<BlockPointerType>()->getPointeeType(); 7006b755b0cSVlad Serebrennikov if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) { 7016b755b0cSVlad Serebrennikov Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type) 7026b755b0cSVlad Serebrennikov << CompletionBlock->getType(); 7036b755b0cSVlad Serebrennikov return; 7046b755b0cSVlad Serebrennikov } 7056b755b0cSVlad Serebrennikov } 7066b755b0cSVlad Serebrennikov 7076b755b0cSVlad Serebrennikov auto *AsyncAttr = 7086b755b0cSVlad Serebrennikov ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx); 7096b755b0cSVlad Serebrennikov D->addAttr(AsyncAttr); 7106b755b0cSVlad Serebrennikov 7116b755b0cSVlad Serebrennikov if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>()) 7126b755b0cSVlad Serebrennikov checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr); 7136b755b0cSVlad Serebrennikov } 7146b755b0cSVlad Serebrennikov 7156b755b0cSVlad Serebrennikov void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, 7166b755b0cSVlad Serebrennikov ParameterABI abi) { 7176b755b0cSVlad Serebrennikov ASTContext &Context = getASTContext(); 7186b755b0cSVlad Serebrennikov QualType type = cast<ParmVarDecl>(D)->getType(); 7196b755b0cSVlad Serebrennikov 7206b755b0cSVlad Serebrennikov if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { 7216b755b0cSVlad Serebrennikov if (existingAttr->getABI() != abi) { 7226b755b0cSVlad Serebrennikov Diag(CI.getLoc(), diag::err_attributes_are_not_compatible) 7236b755b0cSVlad Serebrennikov << getParameterABISpelling(abi) << existingAttr 7246b755b0cSVlad Serebrennikov << (CI.isRegularKeywordAttribute() || 7256b755b0cSVlad Serebrennikov existingAttr->isRegularKeywordAttribute()); 7266b755b0cSVlad Serebrennikov Diag(existingAttr->getLocation(), diag::note_conflicting_attribute); 7276b755b0cSVlad Serebrennikov return; 7286b755b0cSVlad Serebrennikov } 7296b755b0cSVlad Serebrennikov } 7306b755b0cSVlad Serebrennikov 7316b755b0cSVlad Serebrennikov switch (abi) { 73289fb8490SChris B case ParameterABI::HLSLOut: 73389fb8490SChris B case ParameterABI::HLSLInOut: 73489fb8490SChris B llvm_unreachable("explicit attribute for non-swift parameter ABI?"); 7356b755b0cSVlad Serebrennikov case ParameterABI::Ordinary: 7366b755b0cSVlad Serebrennikov llvm_unreachable("explicit attribute for ordinary parameter ABI?"); 7376b755b0cSVlad Serebrennikov 7386b755b0cSVlad Serebrennikov case ParameterABI::SwiftContext: 7396b755b0cSVlad Serebrennikov if (!isValidSwiftContextType(type)) { 7406b755b0cSVlad Serebrennikov Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 7416b755b0cSVlad Serebrennikov << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; 7426b755b0cSVlad Serebrennikov } 7436b755b0cSVlad Serebrennikov D->addAttr(::new (Context) SwiftContextAttr(Context, CI)); 7446b755b0cSVlad Serebrennikov return; 7456b755b0cSVlad Serebrennikov 7466b755b0cSVlad Serebrennikov case ParameterABI::SwiftAsyncContext: 7476b755b0cSVlad Serebrennikov if (!isValidSwiftContextType(type)) { 7486b755b0cSVlad Serebrennikov Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 7496b755b0cSVlad Serebrennikov << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; 7506b755b0cSVlad Serebrennikov } 7516b755b0cSVlad Serebrennikov D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI)); 7526b755b0cSVlad Serebrennikov return; 7536b755b0cSVlad Serebrennikov 7546b755b0cSVlad Serebrennikov case ParameterABI::SwiftErrorResult: 7556b755b0cSVlad Serebrennikov if (!isValidSwiftErrorResultType(type)) { 7566b755b0cSVlad Serebrennikov Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 7576b755b0cSVlad Serebrennikov << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type; 7586b755b0cSVlad Serebrennikov } 7596b755b0cSVlad Serebrennikov D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI)); 7606b755b0cSVlad Serebrennikov return; 7616b755b0cSVlad Serebrennikov 7626b755b0cSVlad Serebrennikov case ParameterABI::SwiftIndirectResult: 7636b755b0cSVlad Serebrennikov if (!isValidSwiftIndirectResultType(type)) { 7646b755b0cSVlad Serebrennikov Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) 7656b755b0cSVlad Serebrennikov << getParameterABISpelling(abi) << /*pointer*/ 0 << type; 7666b755b0cSVlad Serebrennikov } 7676b755b0cSVlad Serebrennikov D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI)); 7686b755b0cSVlad Serebrennikov return; 7696b755b0cSVlad Serebrennikov } 7706b755b0cSVlad Serebrennikov llvm_unreachable("bad parameter ABI attribute"); 7716b755b0cSVlad Serebrennikov } 7726b755b0cSVlad Serebrennikov 7736b755b0cSVlad Serebrennikov } // namespace clang 774