xref: /llvm-project/clang/lib/Sema/SemaSwift.cpp (revision 41a94de75caacb979070ec7a010dfe3c4e9f116f)
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