xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaSwift.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===------ SemaSwift.cpp ------ Swift language-specific routines ---------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric //  This file implements semantic analysis functions specific to Swift.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "clang/Sema/SemaSwift.h"
14*0fca6ea1SDimitry Andric #include "clang/AST/DeclBase.h"
15*0fca6ea1SDimitry Andric #include "clang/Basic/AttributeCommonInfo.h"
16*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
17*0fca6ea1SDimitry Andric #include "clang/Basic/Specifiers.h"
18*0fca6ea1SDimitry Andric #include "clang/Sema/Attr.h"
19*0fca6ea1SDimitry Andric #include "clang/Sema/ParsedAttr.h"
20*0fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
21*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
22*0fca6ea1SDimitry Andric 
23*0fca6ea1SDimitry Andric namespace clang {
24*0fca6ea1SDimitry Andric SemaSwift::SemaSwift(Sema &S) : SemaBase(S) {}
25*0fca6ea1SDimitry Andric 
26*0fca6ea1SDimitry Andric SwiftNameAttr *SemaSwift::mergeNameAttr(Decl *D, const SwiftNameAttr &SNA,
27*0fca6ea1SDimitry Andric                                         StringRef Name) {
28*0fca6ea1SDimitry Andric   if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
29*0fca6ea1SDimitry Andric     if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
30*0fca6ea1SDimitry Andric       Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
31*0fca6ea1SDimitry Andric           << PrevSNA << &SNA
32*0fca6ea1SDimitry Andric           << (PrevSNA->isRegularKeywordAttribute() ||
33*0fca6ea1SDimitry Andric               SNA.isRegularKeywordAttribute());
34*0fca6ea1SDimitry Andric       Diag(SNA.getLoc(), diag::note_conflicting_attribute);
35*0fca6ea1SDimitry Andric     }
36*0fca6ea1SDimitry Andric 
37*0fca6ea1SDimitry Andric     D->dropAttr<SwiftNameAttr>();
38*0fca6ea1SDimitry Andric   }
39*0fca6ea1SDimitry Andric   return ::new (getASTContext()) SwiftNameAttr(getASTContext(), SNA, Name);
40*0fca6ea1SDimitry Andric }
41*0fca6ea1SDimitry Andric 
42*0fca6ea1SDimitry Andric /// Pointer-like types in the default address space.
43*0fca6ea1SDimitry Andric static bool isValidSwiftContextType(QualType Ty) {
44*0fca6ea1SDimitry Andric   if (!Ty->hasPointerRepresentation())
45*0fca6ea1SDimitry Andric     return Ty->isDependentType();
46*0fca6ea1SDimitry Andric   return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
47*0fca6ea1SDimitry Andric }
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric /// Pointers and references in the default address space.
50*0fca6ea1SDimitry Andric static bool isValidSwiftIndirectResultType(QualType Ty) {
51*0fca6ea1SDimitry Andric   if (const auto *PtrType = Ty->getAs<PointerType>()) {
52*0fca6ea1SDimitry Andric     Ty = PtrType->getPointeeType();
53*0fca6ea1SDimitry Andric   } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
54*0fca6ea1SDimitry Andric     Ty = RefType->getPointeeType();
55*0fca6ea1SDimitry Andric   } else {
56*0fca6ea1SDimitry Andric     return Ty->isDependentType();
57*0fca6ea1SDimitry Andric   }
58*0fca6ea1SDimitry Andric   return Ty.getAddressSpace() == LangAS::Default;
59*0fca6ea1SDimitry Andric }
60*0fca6ea1SDimitry Andric 
61*0fca6ea1SDimitry Andric /// Pointers and references to pointers in the default address space.
62*0fca6ea1SDimitry Andric static bool isValidSwiftErrorResultType(QualType Ty) {
63*0fca6ea1SDimitry Andric   if (const auto *PtrType = Ty->getAs<PointerType>()) {
64*0fca6ea1SDimitry Andric     Ty = PtrType->getPointeeType();
65*0fca6ea1SDimitry Andric   } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
66*0fca6ea1SDimitry Andric     Ty = RefType->getPointeeType();
67*0fca6ea1SDimitry Andric   } else {
68*0fca6ea1SDimitry Andric     return Ty->isDependentType();
69*0fca6ea1SDimitry Andric   }
70*0fca6ea1SDimitry Andric   if (!Ty.getQualifiers().empty())
71*0fca6ea1SDimitry Andric     return false;
72*0fca6ea1SDimitry Andric   return isValidSwiftContextType(Ty);
73*0fca6ea1SDimitry Andric }
74*0fca6ea1SDimitry Andric 
75*0fca6ea1SDimitry Andric void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) {
76*0fca6ea1SDimitry Andric   // Make sure that there is a string literal as the annotation's single
77*0fca6ea1SDimitry Andric   // argument.
78*0fca6ea1SDimitry Andric   StringRef Str;
79*0fca6ea1SDimitry Andric   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str))
80*0fca6ea1SDimitry Andric     return;
81*0fca6ea1SDimitry Andric 
82*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str));
83*0fca6ea1SDimitry Andric }
84*0fca6ea1SDimitry Andric 
85*0fca6ea1SDimitry Andric void SemaSwift::handleBridge(Decl *D, const ParsedAttr &AL) {
86*0fca6ea1SDimitry Andric   // Make sure that there is a string literal as the annotation's single
87*0fca6ea1SDimitry Andric   // argument.
88*0fca6ea1SDimitry Andric   StringRef BT;
89*0fca6ea1SDimitry Andric   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT))
90*0fca6ea1SDimitry Andric     return;
91*0fca6ea1SDimitry Andric 
92*0fca6ea1SDimitry Andric   // Warn about duplicate attributes if they have different arguments, but drop
93*0fca6ea1SDimitry Andric   // any duplicate attributes regardless.
94*0fca6ea1SDimitry Andric   if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
95*0fca6ea1SDimitry Andric     if (Other->getSwiftType() != BT)
96*0fca6ea1SDimitry Andric       Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
97*0fca6ea1SDimitry Andric     return;
98*0fca6ea1SDimitry Andric   }
99*0fca6ea1SDimitry Andric 
100*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext()) SwiftBridgeAttr(getASTContext(), AL, BT));
101*0fca6ea1SDimitry Andric }
102*0fca6ea1SDimitry Andric 
103*0fca6ea1SDimitry Andric static bool isErrorParameter(Sema &S, QualType QT) {
104*0fca6ea1SDimitry Andric   const auto *PT = QT->getAs<PointerType>();
105*0fca6ea1SDimitry Andric   if (!PT)
106*0fca6ea1SDimitry Andric     return false;
107*0fca6ea1SDimitry Andric 
108*0fca6ea1SDimitry Andric   QualType Pointee = PT->getPointeeType();
109*0fca6ea1SDimitry Andric 
110*0fca6ea1SDimitry Andric   // Check for NSError**.
111*0fca6ea1SDimitry Andric   if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
112*0fca6ea1SDimitry Andric     if (const auto *ID = OPT->getInterfaceDecl())
113*0fca6ea1SDimitry Andric       if (ID->getIdentifier() == S.ObjC().getNSErrorIdent())
114*0fca6ea1SDimitry Andric         return true;
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric   // Check for CFError**.
117*0fca6ea1SDimitry Andric   if (const auto *PT = Pointee->getAs<PointerType>())
118*0fca6ea1SDimitry Andric     if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
119*0fca6ea1SDimitry Andric       if (S.ObjC().isCFError(RT->getDecl()))
120*0fca6ea1SDimitry Andric         return true;
121*0fca6ea1SDimitry Andric 
122*0fca6ea1SDimitry Andric   return false;
123*0fca6ea1SDimitry Andric }
124*0fca6ea1SDimitry Andric 
125*0fca6ea1SDimitry Andric void SemaSwift::handleError(Decl *D, const ParsedAttr &AL) {
126*0fca6ea1SDimitry Andric   auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
127*0fca6ea1SDimitry Andric     for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
128*0fca6ea1SDimitry Andric       if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
129*0fca6ea1SDimitry Andric         return true;
130*0fca6ea1SDimitry Andric     }
131*0fca6ea1SDimitry Andric 
132*0fca6ea1SDimitry Andric     S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
133*0fca6ea1SDimitry Andric         << AL << isa<ObjCMethodDecl>(D);
134*0fca6ea1SDimitry Andric     return false;
135*0fca6ea1SDimitry Andric   };
136*0fca6ea1SDimitry Andric 
137*0fca6ea1SDimitry Andric   auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
138*0fca6ea1SDimitry Andric     // - C, ObjC, and block pointers are definitely okay.
139*0fca6ea1SDimitry Andric     // - References are definitely not okay.
140*0fca6ea1SDimitry Andric     // - nullptr_t is weird, but acceptable.
141*0fca6ea1SDimitry Andric     QualType RT = getFunctionOrMethodResultType(D);
142*0fca6ea1SDimitry Andric     if (RT->hasPointerRepresentation() && !RT->isReferenceType())
143*0fca6ea1SDimitry Andric       return true;
144*0fca6ea1SDimitry Andric 
145*0fca6ea1SDimitry Andric     S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
146*0fca6ea1SDimitry Andric         << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
147*0fca6ea1SDimitry Andric         << /*pointer*/ 1;
148*0fca6ea1SDimitry Andric     return false;
149*0fca6ea1SDimitry Andric   };
150*0fca6ea1SDimitry Andric 
151*0fca6ea1SDimitry Andric   auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
152*0fca6ea1SDimitry Andric     QualType RT = getFunctionOrMethodResultType(D);
153*0fca6ea1SDimitry Andric     if (RT->isIntegralType(S.Context))
154*0fca6ea1SDimitry Andric       return true;
155*0fca6ea1SDimitry Andric 
156*0fca6ea1SDimitry Andric     S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
157*0fca6ea1SDimitry Andric         << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
158*0fca6ea1SDimitry Andric         << /*integral*/ 0;
159*0fca6ea1SDimitry Andric     return false;
160*0fca6ea1SDimitry Andric   };
161*0fca6ea1SDimitry Andric 
162*0fca6ea1SDimitry Andric   if (D->isInvalidDecl())
163*0fca6ea1SDimitry Andric     return;
164*0fca6ea1SDimitry Andric 
165*0fca6ea1SDimitry Andric   IdentifierLoc *Loc = AL.getArgAsIdent(0);
166*0fca6ea1SDimitry Andric   SwiftErrorAttr::ConventionKind Convention;
167*0fca6ea1SDimitry Andric   if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
168*0fca6ea1SDimitry Andric                                                   Convention)) {
169*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
170*0fca6ea1SDimitry Andric         << AL << Loc->Ident;
171*0fca6ea1SDimitry Andric     return;
172*0fca6ea1SDimitry Andric   }
173*0fca6ea1SDimitry Andric 
174*0fca6ea1SDimitry Andric   switch (Convention) {
175*0fca6ea1SDimitry Andric   case SwiftErrorAttr::None:
176*0fca6ea1SDimitry Andric     // No additional validation required.
177*0fca6ea1SDimitry Andric     break;
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric   case SwiftErrorAttr::NonNullError:
180*0fca6ea1SDimitry Andric     if (!hasErrorParameter(SemaRef, D, AL))
181*0fca6ea1SDimitry Andric       return;
182*0fca6ea1SDimitry Andric     break;
183*0fca6ea1SDimitry Andric 
184*0fca6ea1SDimitry Andric   case SwiftErrorAttr::NullResult:
185*0fca6ea1SDimitry Andric     if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))
186*0fca6ea1SDimitry Andric       return;
187*0fca6ea1SDimitry Andric     break;
188*0fca6ea1SDimitry Andric 
189*0fca6ea1SDimitry Andric   case SwiftErrorAttr::NonZeroResult:
190*0fca6ea1SDimitry Andric   case SwiftErrorAttr::ZeroResult:
191*0fca6ea1SDimitry Andric     if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))
192*0fca6ea1SDimitry Andric       return;
193*0fca6ea1SDimitry Andric     break;
194*0fca6ea1SDimitry Andric   }
195*0fca6ea1SDimitry Andric 
196*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext())
197*0fca6ea1SDimitry Andric                  SwiftErrorAttr(getASTContext(), AL, Convention));
198*0fca6ea1SDimitry Andric }
199*0fca6ea1SDimitry Andric 
200*0fca6ea1SDimitry Andric static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
201*0fca6ea1SDimitry Andric                                       const SwiftAsyncErrorAttr *ErrorAttr,
202*0fca6ea1SDimitry Andric                                       const SwiftAsyncAttr *AsyncAttr) {
203*0fca6ea1SDimitry Andric   if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
204*0fca6ea1SDimitry Andric     if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
205*0fca6ea1SDimitry Andric       S.Diag(AsyncAttr->getLocation(),
206*0fca6ea1SDimitry Andric              diag::err_swift_async_error_without_swift_async)
207*0fca6ea1SDimitry Andric           << AsyncAttr << isa<ObjCMethodDecl>(D);
208*0fca6ea1SDimitry Andric     }
209*0fca6ea1SDimitry Andric     return;
210*0fca6ea1SDimitry Andric   }
211*0fca6ea1SDimitry Andric 
212*0fca6ea1SDimitry Andric   const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
213*0fca6ea1SDimitry Andric       D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
214*0fca6ea1SDimitry Andric   // handleSwiftAsyncAttr already verified the type is correct, so no need to
215*0fca6ea1SDimitry Andric   // double-check it here.
216*0fca6ea1SDimitry Andric   const auto *FuncTy = HandlerParam->getType()
217*0fca6ea1SDimitry Andric                            ->castAs<BlockPointerType>()
218*0fca6ea1SDimitry Andric                            ->getPointeeType()
219*0fca6ea1SDimitry Andric                            ->getAs<FunctionProtoType>();
220*0fca6ea1SDimitry Andric   ArrayRef<QualType> BlockParams;
221*0fca6ea1SDimitry Andric   if (FuncTy)
222*0fca6ea1SDimitry Andric     BlockParams = FuncTy->getParamTypes();
223*0fca6ea1SDimitry Andric 
224*0fca6ea1SDimitry Andric   switch (ErrorAttr->getConvention()) {
225*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::ZeroArgument:
226*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::NonZeroArgument: {
227*0fca6ea1SDimitry Andric     uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
228*0fca6ea1SDimitry Andric     if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
229*0fca6ea1SDimitry Andric       S.Diag(ErrorAttr->getLocation(),
230*0fca6ea1SDimitry Andric              diag::err_attribute_argument_out_of_bounds)
231*0fca6ea1SDimitry Andric           << ErrorAttr << 2;
232*0fca6ea1SDimitry Andric       return;
233*0fca6ea1SDimitry Andric     }
234*0fca6ea1SDimitry Andric     QualType ErrorParam = BlockParams[ParamIdx - 1];
235*0fca6ea1SDimitry Andric     if (!ErrorParam->isIntegralType(S.Context)) {
236*0fca6ea1SDimitry Andric       StringRef ConvStr =
237*0fca6ea1SDimitry Andric           ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
238*0fca6ea1SDimitry Andric               ? "zero_argument"
239*0fca6ea1SDimitry Andric               : "nonzero_argument";
240*0fca6ea1SDimitry Andric       S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
241*0fca6ea1SDimitry Andric           << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
242*0fca6ea1SDimitry Andric       return;
243*0fca6ea1SDimitry Andric     }
244*0fca6ea1SDimitry Andric     break;
245*0fca6ea1SDimitry Andric   }
246*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::NonNullError: {
247*0fca6ea1SDimitry Andric     bool AnyErrorParams = false;
248*0fca6ea1SDimitry Andric     for (QualType Param : BlockParams) {
249*0fca6ea1SDimitry Andric       // Check for NSError *.
250*0fca6ea1SDimitry Andric       if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
251*0fca6ea1SDimitry Andric         if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
252*0fca6ea1SDimitry Andric           if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) {
253*0fca6ea1SDimitry Andric             AnyErrorParams = true;
254*0fca6ea1SDimitry Andric             break;
255*0fca6ea1SDimitry Andric           }
256*0fca6ea1SDimitry Andric         }
257*0fca6ea1SDimitry Andric       }
258*0fca6ea1SDimitry Andric       // Check for CFError *.
259*0fca6ea1SDimitry Andric       if (const auto *PtrTy = Param->getAs<PointerType>()) {
260*0fca6ea1SDimitry Andric         if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
261*0fca6ea1SDimitry Andric           if (S.ObjC().isCFError(RT->getDecl())) {
262*0fca6ea1SDimitry Andric             AnyErrorParams = true;
263*0fca6ea1SDimitry Andric             break;
264*0fca6ea1SDimitry Andric           }
265*0fca6ea1SDimitry Andric         }
266*0fca6ea1SDimitry Andric       }
267*0fca6ea1SDimitry Andric     }
268*0fca6ea1SDimitry Andric 
269*0fca6ea1SDimitry Andric     if (!AnyErrorParams) {
270*0fca6ea1SDimitry Andric       S.Diag(ErrorAttr->getLocation(),
271*0fca6ea1SDimitry Andric              diag::err_swift_async_error_no_error_parameter)
272*0fca6ea1SDimitry Andric           << ErrorAttr << isa<ObjCMethodDecl>(D);
273*0fca6ea1SDimitry Andric       return;
274*0fca6ea1SDimitry Andric     }
275*0fca6ea1SDimitry Andric     break;
276*0fca6ea1SDimitry Andric   }
277*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::None:
278*0fca6ea1SDimitry Andric     break;
279*0fca6ea1SDimitry Andric   }
280*0fca6ea1SDimitry Andric }
281*0fca6ea1SDimitry Andric 
282*0fca6ea1SDimitry Andric void SemaSwift::handleAsyncError(Decl *D, const ParsedAttr &AL) {
283*0fca6ea1SDimitry Andric   IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
284*0fca6ea1SDimitry Andric   SwiftAsyncErrorAttr::ConventionKind ConvKind;
285*0fca6ea1SDimitry Andric   if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),
286*0fca6ea1SDimitry Andric                                                        ConvKind)) {
287*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
288*0fca6ea1SDimitry Andric         << AL << IDLoc->Ident;
289*0fca6ea1SDimitry Andric     return;
290*0fca6ea1SDimitry Andric   }
291*0fca6ea1SDimitry Andric 
292*0fca6ea1SDimitry Andric   uint32_t ParamIdx = 0;
293*0fca6ea1SDimitry Andric   switch (ConvKind) {
294*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::ZeroArgument:
295*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::NonZeroArgument: {
296*0fca6ea1SDimitry Andric     if (!AL.checkExactlyNumArgs(SemaRef, 2))
297*0fca6ea1SDimitry Andric       return;
298*0fca6ea1SDimitry Andric 
299*0fca6ea1SDimitry Andric     Expr *IdxExpr = AL.getArgAsExpr(1);
300*0fca6ea1SDimitry Andric     if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx))
301*0fca6ea1SDimitry Andric       return;
302*0fca6ea1SDimitry Andric     break;
303*0fca6ea1SDimitry Andric   }
304*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::NonNullError:
305*0fca6ea1SDimitry Andric   case SwiftAsyncErrorAttr::None: {
306*0fca6ea1SDimitry Andric     if (!AL.checkExactlyNumArgs(SemaRef, 1))
307*0fca6ea1SDimitry Andric       return;
308*0fca6ea1SDimitry Andric     break;
309*0fca6ea1SDimitry Andric   }
310*0fca6ea1SDimitry Andric   }
311*0fca6ea1SDimitry Andric 
312*0fca6ea1SDimitry Andric   auto *ErrorAttr = ::new (getASTContext())
313*0fca6ea1SDimitry Andric       SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx);
314*0fca6ea1SDimitry Andric   D->addAttr(ErrorAttr);
315*0fca6ea1SDimitry Andric 
316*0fca6ea1SDimitry Andric   if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
317*0fca6ea1SDimitry Andric     checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
318*0fca6ea1SDimitry Andric }
319*0fca6ea1SDimitry Andric 
320*0fca6ea1SDimitry Andric // For a function, this will validate a compound Swift name, e.g.
321*0fca6ea1SDimitry Andric // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
322*0fca6ea1SDimitry Andric // the function will output the number of parameter names, and whether this is a
323*0fca6ea1SDimitry Andric // single-arg initializer.
324*0fca6ea1SDimitry Andric //
325*0fca6ea1SDimitry Andric // For a type, enum constant, property, or variable declaration, this will
326*0fca6ea1SDimitry Andric // validate either a simple identifier, or a qualified
327*0fca6ea1SDimitry Andric // <code>context.identifier</code> name.
328*0fca6ea1SDimitry Andric static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
329*0fca6ea1SDimitry Andric                                       SourceLocation Loc, StringRef Name,
330*0fca6ea1SDimitry Andric                                       unsigned &SwiftParamCount,
331*0fca6ea1SDimitry Andric                                       bool &IsSingleParamInit) {
332*0fca6ea1SDimitry Andric   SwiftParamCount = 0;
333*0fca6ea1SDimitry Andric   IsSingleParamInit = false;
334*0fca6ea1SDimitry Andric 
335*0fca6ea1SDimitry Andric   // Check whether this will be mapped to a getter or setter of a property.
336*0fca6ea1SDimitry Andric   bool IsGetter = false, IsSetter = false;
337*0fca6ea1SDimitry Andric   if (Name.consume_front("getter:"))
338*0fca6ea1SDimitry Andric     IsGetter = true;
339*0fca6ea1SDimitry Andric   else if (Name.consume_front("setter:"))
340*0fca6ea1SDimitry Andric     IsSetter = true;
341*0fca6ea1SDimitry Andric 
342*0fca6ea1SDimitry Andric   if (Name.back() != ')') {
343*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
344*0fca6ea1SDimitry Andric     return false;
345*0fca6ea1SDimitry Andric   }
346*0fca6ea1SDimitry Andric 
347*0fca6ea1SDimitry Andric   bool IsMember = false;
348*0fca6ea1SDimitry Andric   StringRef ContextName, BaseName, Parameters;
349*0fca6ea1SDimitry Andric 
350*0fca6ea1SDimitry Andric   std::tie(BaseName, Parameters) = Name.split('(');
351*0fca6ea1SDimitry Andric 
352*0fca6ea1SDimitry Andric   // Split at the first '.', if it exists, which separates the context name
353*0fca6ea1SDimitry Andric   // from the base name.
354*0fca6ea1SDimitry Andric   std::tie(ContextName, BaseName) = BaseName.split('.');
355*0fca6ea1SDimitry Andric   if (BaseName.empty()) {
356*0fca6ea1SDimitry Andric     BaseName = ContextName;
357*0fca6ea1SDimitry Andric     ContextName = StringRef();
358*0fca6ea1SDimitry Andric   } else if (ContextName.empty() || !isValidAsciiIdentifier(ContextName)) {
359*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
360*0fca6ea1SDimitry Andric         << AL << /*context*/ 1;
361*0fca6ea1SDimitry Andric     return false;
362*0fca6ea1SDimitry Andric   } else {
363*0fca6ea1SDimitry Andric     IsMember = true;
364*0fca6ea1SDimitry Andric   }
365*0fca6ea1SDimitry Andric 
366*0fca6ea1SDimitry Andric   if (!isValidAsciiIdentifier(BaseName) || BaseName == "_") {
367*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
368*0fca6ea1SDimitry Andric         << AL << /*basename*/ 0;
369*0fca6ea1SDimitry Andric     return false;
370*0fca6ea1SDimitry Andric   }
371*0fca6ea1SDimitry Andric 
372*0fca6ea1SDimitry Andric   bool IsSubscript = BaseName == "subscript";
373*0fca6ea1SDimitry Andric   // A subscript accessor must be a getter or setter.
374*0fca6ea1SDimitry Andric   if (IsSubscript && !IsGetter && !IsSetter) {
375*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
376*0fca6ea1SDimitry Andric         << AL << /* getter or setter */ 0;
377*0fca6ea1SDimitry Andric     return false;
378*0fca6ea1SDimitry Andric   }
379*0fca6ea1SDimitry Andric 
380*0fca6ea1SDimitry Andric   if (Parameters.empty()) {
381*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
382*0fca6ea1SDimitry Andric     return false;
383*0fca6ea1SDimitry Andric   }
384*0fca6ea1SDimitry Andric 
385*0fca6ea1SDimitry Andric   assert(Parameters.back() == ')' && "expected ')'");
386*0fca6ea1SDimitry Andric   Parameters = Parameters.drop_back(); // ')'
387*0fca6ea1SDimitry Andric 
388*0fca6ea1SDimitry Andric   if (Parameters.empty()) {
389*0fca6ea1SDimitry Andric     // Setters and subscripts must have at least one parameter.
390*0fca6ea1SDimitry Andric     if (IsSubscript) {
391*0fca6ea1SDimitry Andric       S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
392*0fca6ea1SDimitry Andric           << AL << /* have at least one parameter */ 1;
393*0fca6ea1SDimitry Andric       return false;
394*0fca6ea1SDimitry Andric     }
395*0fca6ea1SDimitry Andric 
396*0fca6ea1SDimitry Andric     if (IsSetter) {
397*0fca6ea1SDimitry Andric       S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
398*0fca6ea1SDimitry Andric       return false;
399*0fca6ea1SDimitry Andric     }
400*0fca6ea1SDimitry Andric 
401*0fca6ea1SDimitry Andric     return true;
402*0fca6ea1SDimitry Andric   }
403*0fca6ea1SDimitry Andric 
404*0fca6ea1SDimitry Andric   if (Parameters.back() != ':') {
405*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
406*0fca6ea1SDimitry Andric     return false;
407*0fca6ea1SDimitry Andric   }
408*0fca6ea1SDimitry Andric 
409*0fca6ea1SDimitry Andric   StringRef CurrentParam;
410*0fca6ea1SDimitry Andric   std::optional<unsigned> SelfLocation;
411*0fca6ea1SDimitry Andric   unsigned NewValueCount = 0;
412*0fca6ea1SDimitry Andric   std::optional<unsigned> NewValueLocation;
413*0fca6ea1SDimitry Andric   do {
414*0fca6ea1SDimitry Andric     std::tie(CurrentParam, Parameters) = Parameters.split(':');
415*0fca6ea1SDimitry Andric 
416*0fca6ea1SDimitry Andric     if (!isValidAsciiIdentifier(CurrentParam)) {
417*0fca6ea1SDimitry Andric       S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
418*0fca6ea1SDimitry Andric           << AL << /*parameter*/ 2;
419*0fca6ea1SDimitry Andric       return false;
420*0fca6ea1SDimitry Andric     }
421*0fca6ea1SDimitry Andric 
422*0fca6ea1SDimitry Andric     if (IsMember && CurrentParam == "self") {
423*0fca6ea1SDimitry Andric       // "self" indicates the "self" argument for a member.
424*0fca6ea1SDimitry Andric 
425*0fca6ea1SDimitry Andric       // More than one "self"?
426*0fca6ea1SDimitry Andric       if (SelfLocation) {
427*0fca6ea1SDimitry Andric         S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
428*0fca6ea1SDimitry Andric         return false;
429*0fca6ea1SDimitry Andric       }
430*0fca6ea1SDimitry Andric 
431*0fca6ea1SDimitry Andric       // The "self" location is the current parameter.
432*0fca6ea1SDimitry Andric       SelfLocation = SwiftParamCount;
433*0fca6ea1SDimitry Andric     } else if (CurrentParam == "newValue") {
434*0fca6ea1SDimitry Andric       // "newValue" indicates the "newValue" argument for a setter.
435*0fca6ea1SDimitry Andric 
436*0fca6ea1SDimitry Andric       // There should only be one 'newValue', but it's only significant for
437*0fca6ea1SDimitry Andric       // subscript accessors, so don't error right away.
438*0fca6ea1SDimitry Andric       ++NewValueCount;
439*0fca6ea1SDimitry Andric 
440*0fca6ea1SDimitry Andric       NewValueLocation = SwiftParamCount;
441*0fca6ea1SDimitry Andric     }
442*0fca6ea1SDimitry Andric 
443*0fca6ea1SDimitry Andric     ++SwiftParamCount;
444*0fca6ea1SDimitry Andric   } while (!Parameters.empty());
445*0fca6ea1SDimitry Andric 
446*0fca6ea1SDimitry Andric   // Only instance subscripts are currently supported.
447*0fca6ea1SDimitry Andric   if (IsSubscript && !SelfLocation) {
448*0fca6ea1SDimitry Andric     S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
449*0fca6ea1SDimitry Andric         << AL << /*have a 'self:' parameter*/ 2;
450*0fca6ea1SDimitry Andric     return false;
451*0fca6ea1SDimitry Andric   }
452*0fca6ea1SDimitry Andric 
453*0fca6ea1SDimitry Andric   IsSingleParamInit =
454*0fca6ea1SDimitry Andric       SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
455*0fca6ea1SDimitry Andric 
456*0fca6ea1SDimitry Andric   // Check the number of parameters for a getter/setter.
457*0fca6ea1SDimitry Andric   if (IsGetter || IsSetter) {
458*0fca6ea1SDimitry Andric     // Setters have one parameter for the new value.
459*0fca6ea1SDimitry Andric     unsigned NumExpectedParams = IsGetter ? 0 : 1;
460*0fca6ea1SDimitry Andric     unsigned ParamDiag = IsGetter
461*0fca6ea1SDimitry Andric                              ? diag::warn_attr_swift_name_getter_parameters
462*0fca6ea1SDimitry Andric                              : diag::warn_attr_swift_name_setter_parameters;
463*0fca6ea1SDimitry Andric 
464*0fca6ea1SDimitry Andric     // Instance methods have one parameter for "self".
465*0fca6ea1SDimitry Andric     if (SelfLocation)
466*0fca6ea1SDimitry Andric       ++NumExpectedParams;
467*0fca6ea1SDimitry Andric 
468*0fca6ea1SDimitry Andric     // Subscripts may have additional parameters beyond the expected params for
469*0fca6ea1SDimitry Andric     // the index.
470*0fca6ea1SDimitry Andric     if (IsSubscript) {
471*0fca6ea1SDimitry Andric       if (SwiftParamCount < NumExpectedParams) {
472*0fca6ea1SDimitry Andric         S.Diag(Loc, ParamDiag) << AL;
473*0fca6ea1SDimitry Andric         return false;
474*0fca6ea1SDimitry Andric       }
475*0fca6ea1SDimitry Andric 
476*0fca6ea1SDimitry Andric       // A subscript setter must explicitly label its newValue parameter to
477*0fca6ea1SDimitry Andric       // distinguish it from index parameters.
478*0fca6ea1SDimitry Andric       if (IsSetter) {
479*0fca6ea1SDimitry Andric         if (!NewValueLocation) {
480*0fca6ea1SDimitry Andric           S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
481*0fca6ea1SDimitry Andric               << AL;
482*0fca6ea1SDimitry Andric           return false;
483*0fca6ea1SDimitry Andric         }
484*0fca6ea1SDimitry Andric         if (NewValueCount > 1) {
485*0fca6ea1SDimitry Andric           S.Diag(Loc,
486*0fca6ea1SDimitry Andric                  diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
487*0fca6ea1SDimitry Andric               << AL;
488*0fca6ea1SDimitry Andric           return false;
489*0fca6ea1SDimitry Andric         }
490*0fca6ea1SDimitry Andric       } else {
491*0fca6ea1SDimitry Andric         // Subscript getters should have no 'newValue:' parameter.
492*0fca6ea1SDimitry Andric         if (NewValueLocation) {
493*0fca6ea1SDimitry Andric           S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
494*0fca6ea1SDimitry Andric               << AL;
495*0fca6ea1SDimitry Andric           return false;
496*0fca6ea1SDimitry Andric         }
497*0fca6ea1SDimitry Andric       }
498*0fca6ea1SDimitry Andric     } else {
499*0fca6ea1SDimitry Andric       // Property accessors must have exactly the number of expected params.
500*0fca6ea1SDimitry Andric       if (SwiftParamCount != NumExpectedParams) {
501*0fca6ea1SDimitry Andric         S.Diag(Loc, ParamDiag) << AL;
502*0fca6ea1SDimitry Andric         return false;
503*0fca6ea1SDimitry Andric       }
504*0fca6ea1SDimitry Andric     }
505*0fca6ea1SDimitry Andric   }
506*0fca6ea1SDimitry Andric 
507*0fca6ea1SDimitry Andric   return true;
508*0fca6ea1SDimitry Andric }
509*0fca6ea1SDimitry Andric 
510*0fca6ea1SDimitry Andric bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
511*0fca6ea1SDimitry Andric                              const ParsedAttr &AL, bool IsAsync) {
512*0fca6ea1SDimitry Andric   if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
513*0fca6ea1SDimitry Andric     ArrayRef<ParmVarDecl *> Params;
514*0fca6ea1SDimitry Andric     unsigned ParamCount;
515*0fca6ea1SDimitry Andric 
516*0fca6ea1SDimitry Andric     if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
517*0fca6ea1SDimitry Andric       ParamCount = Method->getSelector().getNumArgs();
518*0fca6ea1SDimitry Andric       Params = Method->parameters().slice(0, ParamCount);
519*0fca6ea1SDimitry Andric     } else {
520*0fca6ea1SDimitry Andric       const auto *F = cast<FunctionDecl>(D);
521*0fca6ea1SDimitry Andric 
522*0fca6ea1SDimitry Andric       ParamCount = F->getNumParams();
523*0fca6ea1SDimitry Andric       Params = F->parameters();
524*0fca6ea1SDimitry Andric 
525*0fca6ea1SDimitry Andric       if (!F->hasWrittenPrototype()) {
526*0fca6ea1SDimitry Andric         Diag(Loc, diag::warn_attribute_wrong_decl_type)
527*0fca6ea1SDimitry Andric             << AL << AL.isRegularKeywordAttribute()
528*0fca6ea1SDimitry Andric             << ExpectedFunctionWithProtoType;
529*0fca6ea1SDimitry Andric         return false;
530*0fca6ea1SDimitry Andric       }
531*0fca6ea1SDimitry Andric     }
532*0fca6ea1SDimitry Andric 
533*0fca6ea1SDimitry Andric     // The async name drops the last callback parameter.
534*0fca6ea1SDimitry Andric     if (IsAsync) {
535*0fca6ea1SDimitry Andric       if (ParamCount == 0) {
536*0fca6ea1SDimitry Andric         Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
537*0fca6ea1SDimitry Andric             << AL << isa<ObjCMethodDecl>(D);
538*0fca6ea1SDimitry Andric         return false;
539*0fca6ea1SDimitry Andric       }
540*0fca6ea1SDimitry Andric       ParamCount -= 1;
541*0fca6ea1SDimitry Andric     }
542*0fca6ea1SDimitry Andric 
543*0fca6ea1SDimitry Andric     unsigned SwiftParamCount;
544*0fca6ea1SDimitry Andric     bool IsSingleParamInit;
545*0fca6ea1SDimitry Andric     if (!validateSwiftFunctionName(SemaRef, AL, Loc, Name, SwiftParamCount,
546*0fca6ea1SDimitry Andric                                    IsSingleParamInit))
547*0fca6ea1SDimitry Andric       return false;
548*0fca6ea1SDimitry Andric 
549*0fca6ea1SDimitry Andric     bool ParamCountValid;
550*0fca6ea1SDimitry Andric     if (SwiftParamCount == ParamCount) {
551*0fca6ea1SDimitry Andric       ParamCountValid = true;
552*0fca6ea1SDimitry Andric     } else if (SwiftParamCount > ParamCount) {
553*0fca6ea1SDimitry Andric       ParamCountValid = IsSingleParamInit && ParamCount == 0;
554*0fca6ea1SDimitry Andric     } else {
555*0fca6ea1SDimitry Andric       // We have fewer Swift parameters than Objective-C parameters, but that
556*0fca6ea1SDimitry Andric       // might be because we've transformed some of them. Check for potential
557*0fca6ea1SDimitry Andric       // "out" parameters and err on the side of not warning.
558*0fca6ea1SDimitry Andric       unsigned MaybeOutParamCount =
559*0fca6ea1SDimitry Andric           llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {
560*0fca6ea1SDimitry Andric             QualType ParamTy = Param->getType();
561*0fca6ea1SDimitry Andric             if (ParamTy->isReferenceType() || ParamTy->isPointerType())
562*0fca6ea1SDimitry Andric               return !ParamTy->getPointeeType().isConstQualified();
563*0fca6ea1SDimitry Andric             return false;
564*0fca6ea1SDimitry Andric           });
565*0fca6ea1SDimitry Andric 
566*0fca6ea1SDimitry Andric       ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
567*0fca6ea1SDimitry Andric     }
568*0fca6ea1SDimitry Andric 
569*0fca6ea1SDimitry Andric     if (!ParamCountValid) {
570*0fca6ea1SDimitry Andric       Diag(Loc, diag::warn_attr_swift_name_num_params)
571*0fca6ea1SDimitry Andric           << (SwiftParamCount > ParamCount) << AL << ParamCount
572*0fca6ea1SDimitry Andric           << SwiftParamCount;
573*0fca6ea1SDimitry Andric       return false;
574*0fca6ea1SDimitry Andric     }
575*0fca6ea1SDimitry Andric   } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
576*0fca6ea1SDimitry Andric               isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
577*0fca6ea1SDimitry Andric               isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
578*0fca6ea1SDimitry Andric               isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
579*0fca6ea1SDimitry Andric              !IsAsync) {
580*0fca6ea1SDimitry Andric     StringRef ContextName, BaseName;
581*0fca6ea1SDimitry Andric 
582*0fca6ea1SDimitry Andric     std::tie(ContextName, BaseName) = Name.split('.');
583*0fca6ea1SDimitry Andric     if (BaseName.empty()) {
584*0fca6ea1SDimitry Andric       BaseName = ContextName;
585*0fca6ea1SDimitry Andric       ContextName = StringRef();
586*0fca6ea1SDimitry Andric     } else if (!isValidAsciiIdentifier(ContextName)) {
587*0fca6ea1SDimitry Andric       Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
588*0fca6ea1SDimitry Andric           << AL << /*context*/ 1;
589*0fca6ea1SDimitry Andric       return false;
590*0fca6ea1SDimitry Andric     }
591*0fca6ea1SDimitry Andric 
592*0fca6ea1SDimitry Andric     if (!isValidAsciiIdentifier(BaseName)) {
593*0fca6ea1SDimitry Andric       Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
594*0fca6ea1SDimitry Andric           << AL << /*basename*/ 0;
595*0fca6ea1SDimitry Andric       return false;
596*0fca6ea1SDimitry Andric     }
597*0fca6ea1SDimitry Andric   } else {
598*0fca6ea1SDimitry Andric     Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
599*0fca6ea1SDimitry Andric     return false;
600*0fca6ea1SDimitry Andric   }
601*0fca6ea1SDimitry Andric   return true;
602*0fca6ea1SDimitry Andric }
603*0fca6ea1SDimitry Andric 
604*0fca6ea1SDimitry Andric void SemaSwift::handleName(Decl *D, const ParsedAttr &AL) {
605*0fca6ea1SDimitry Andric   StringRef Name;
606*0fca6ea1SDimitry Andric   SourceLocation Loc;
607*0fca6ea1SDimitry Andric   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
608*0fca6ea1SDimitry Andric     return;
609*0fca6ea1SDimitry Andric 
610*0fca6ea1SDimitry Andric   if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false))
611*0fca6ea1SDimitry Andric     return;
612*0fca6ea1SDimitry Andric 
613*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name));
614*0fca6ea1SDimitry Andric }
615*0fca6ea1SDimitry Andric 
616*0fca6ea1SDimitry Andric void SemaSwift::handleAsyncName(Decl *D, const ParsedAttr &AL) {
617*0fca6ea1SDimitry Andric   StringRef Name;
618*0fca6ea1SDimitry Andric   SourceLocation Loc;
619*0fca6ea1SDimitry Andric   if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
620*0fca6ea1SDimitry Andric     return;
621*0fca6ea1SDimitry Andric 
622*0fca6ea1SDimitry Andric   if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true))
623*0fca6ea1SDimitry Andric     return;
624*0fca6ea1SDimitry Andric 
625*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext())
626*0fca6ea1SDimitry Andric                  SwiftAsyncNameAttr(getASTContext(), AL, Name));
627*0fca6ea1SDimitry Andric }
628*0fca6ea1SDimitry Andric 
629*0fca6ea1SDimitry Andric void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) {
630*0fca6ea1SDimitry Andric   // Make sure that there is an identifier as the annotation's single argument.
631*0fca6ea1SDimitry Andric   if (!AL.checkExactlyNumArgs(SemaRef, 1))
632*0fca6ea1SDimitry Andric     return;
633*0fca6ea1SDimitry Andric 
634*0fca6ea1SDimitry Andric   if (!AL.isArgIdent(0)) {
635*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_attribute_argument_type)
636*0fca6ea1SDimitry Andric         << AL << AANT_ArgumentIdentifier;
637*0fca6ea1SDimitry Andric     return;
638*0fca6ea1SDimitry Andric   }
639*0fca6ea1SDimitry Andric 
640*0fca6ea1SDimitry Andric   SwiftNewTypeAttr::NewtypeKind Kind;
641*0fca6ea1SDimitry Andric   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
642*0fca6ea1SDimitry Andric   if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
643*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
644*0fca6ea1SDimitry Andric     return;
645*0fca6ea1SDimitry Andric   }
646*0fca6ea1SDimitry Andric 
647*0fca6ea1SDimitry Andric   if (!isa<TypedefNameDecl>(D)) {
648*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
649*0fca6ea1SDimitry Andric         << AL << AL.isRegularKeywordAttribute() << "typedefs";
650*0fca6ea1SDimitry Andric     return;
651*0fca6ea1SDimitry Andric   }
652*0fca6ea1SDimitry Andric 
653*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext())
654*0fca6ea1SDimitry Andric                  SwiftNewTypeAttr(getASTContext(), AL, Kind));
655*0fca6ea1SDimitry Andric }
656*0fca6ea1SDimitry Andric 
657*0fca6ea1SDimitry Andric void SemaSwift::handleAsyncAttr(Decl *D, const ParsedAttr &AL) {
658*0fca6ea1SDimitry Andric   if (!AL.isArgIdent(0)) {
659*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
660*0fca6ea1SDimitry Andric         << AL << 1 << AANT_ArgumentIdentifier;
661*0fca6ea1SDimitry Andric     return;
662*0fca6ea1SDimitry Andric   }
663*0fca6ea1SDimitry Andric 
664*0fca6ea1SDimitry Andric   SwiftAsyncAttr::Kind Kind;
665*0fca6ea1SDimitry Andric   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
666*0fca6ea1SDimitry Andric   if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
667*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
668*0fca6ea1SDimitry Andric     return;
669*0fca6ea1SDimitry Andric   }
670*0fca6ea1SDimitry Andric 
671*0fca6ea1SDimitry Andric   ParamIdx Idx;
672*0fca6ea1SDimitry Andric   if (Kind == SwiftAsyncAttr::None) {
673*0fca6ea1SDimitry Andric     // If this is 'none', then there shouldn't be any additional arguments.
674*0fca6ea1SDimitry Andric     if (!AL.checkExactlyNumArgs(SemaRef, 1))
675*0fca6ea1SDimitry Andric       return;
676*0fca6ea1SDimitry Andric   } else {
677*0fca6ea1SDimitry Andric     // Non-none swift_async requires a completion handler index argument.
678*0fca6ea1SDimitry Andric     if (!AL.checkExactlyNumArgs(SemaRef, 2))
679*0fca6ea1SDimitry Andric       return;
680*0fca6ea1SDimitry Andric 
681*0fca6ea1SDimitry Andric     Expr *HandlerIdx = AL.getArgAsExpr(1);
682*0fca6ea1SDimitry Andric     if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))
683*0fca6ea1SDimitry Andric       return;
684*0fca6ea1SDimitry Andric 
685*0fca6ea1SDimitry Andric     const ParmVarDecl *CompletionBlock =
686*0fca6ea1SDimitry Andric         getFunctionOrMethodParam(D, Idx.getASTIndex());
687*0fca6ea1SDimitry Andric     QualType CompletionBlockType = CompletionBlock->getType();
688*0fca6ea1SDimitry Andric     if (!CompletionBlockType->isBlockPointerType()) {
689*0fca6ea1SDimitry Andric       Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
690*0fca6ea1SDimitry Andric           << CompletionBlock->getType();
691*0fca6ea1SDimitry Andric       return;
692*0fca6ea1SDimitry Andric     }
693*0fca6ea1SDimitry Andric     QualType BlockTy =
694*0fca6ea1SDimitry Andric         CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
695*0fca6ea1SDimitry Andric     if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
696*0fca6ea1SDimitry Andric       Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
697*0fca6ea1SDimitry Andric           << CompletionBlock->getType();
698*0fca6ea1SDimitry Andric       return;
699*0fca6ea1SDimitry Andric     }
700*0fca6ea1SDimitry Andric   }
701*0fca6ea1SDimitry Andric 
702*0fca6ea1SDimitry Andric   auto *AsyncAttr =
703*0fca6ea1SDimitry Andric       ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx);
704*0fca6ea1SDimitry Andric   D->addAttr(AsyncAttr);
705*0fca6ea1SDimitry Andric 
706*0fca6ea1SDimitry Andric   if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
707*0fca6ea1SDimitry Andric     checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
708*0fca6ea1SDimitry Andric }
709*0fca6ea1SDimitry Andric 
710*0fca6ea1SDimitry Andric void SemaSwift::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
711*0fca6ea1SDimitry Andric                                     ParameterABI abi) {
712*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
713*0fca6ea1SDimitry Andric   QualType type = cast<ParmVarDecl>(D)->getType();
714*0fca6ea1SDimitry Andric 
715*0fca6ea1SDimitry Andric   if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
716*0fca6ea1SDimitry Andric     if (existingAttr->getABI() != abi) {
717*0fca6ea1SDimitry Andric       Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
718*0fca6ea1SDimitry Andric           << getParameterABISpelling(abi) << existingAttr
719*0fca6ea1SDimitry Andric           << (CI.isRegularKeywordAttribute() ||
720*0fca6ea1SDimitry Andric               existingAttr->isRegularKeywordAttribute());
721*0fca6ea1SDimitry Andric       Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
722*0fca6ea1SDimitry Andric       return;
723*0fca6ea1SDimitry Andric     }
724*0fca6ea1SDimitry Andric   }
725*0fca6ea1SDimitry Andric 
726*0fca6ea1SDimitry Andric   switch (abi) {
727*0fca6ea1SDimitry Andric   case ParameterABI::Ordinary:
728*0fca6ea1SDimitry Andric     llvm_unreachable("explicit attribute for ordinary parameter ABI?");
729*0fca6ea1SDimitry Andric 
730*0fca6ea1SDimitry Andric   case ParameterABI::SwiftContext:
731*0fca6ea1SDimitry Andric     if (!isValidSwiftContextType(type)) {
732*0fca6ea1SDimitry Andric       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
733*0fca6ea1SDimitry Andric           << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
734*0fca6ea1SDimitry Andric     }
735*0fca6ea1SDimitry Andric     D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
736*0fca6ea1SDimitry Andric     return;
737*0fca6ea1SDimitry Andric 
738*0fca6ea1SDimitry Andric   case ParameterABI::SwiftAsyncContext:
739*0fca6ea1SDimitry Andric     if (!isValidSwiftContextType(type)) {
740*0fca6ea1SDimitry Andric       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
741*0fca6ea1SDimitry Andric           << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
742*0fca6ea1SDimitry Andric     }
743*0fca6ea1SDimitry Andric     D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
744*0fca6ea1SDimitry Andric     return;
745*0fca6ea1SDimitry Andric 
746*0fca6ea1SDimitry Andric   case ParameterABI::SwiftErrorResult:
747*0fca6ea1SDimitry Andric     if (!isValidSwiftErrorResultType(type)) {
748*0fca6ea1SDimitry Andric       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
749*0fca6ea1SDimitry Andric           << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
750*0fca6ea1SDimitry Andric     }
751*0fca6ea1SDimitry Andric     D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
752*0fca6ea1SDimitry Andric     return;
753*0fca6ea1SDimitry Andric 
754*0fca6ea1SDimitry Andric   case ParameterABI::SwiftIndirectResult:
755*0fca6ea1SDimitry Andric     if (!isValidSwiftIndirectResultType(type)) {
756*0fca6ea1SDimitry Andric       Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
757*0fca6ea1SDimitry Andric           << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
758*0fca6ea1SDimitry Andric     }
759*0fca6ea1SDimitry Andric     D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
760*0fca6ea1SDimitry Andric     return;
761*0fca6ea1SDimitry Andric   }
762*0fca6ea1SDimitry Andric   llvm_unreachable("bad parameter ABI attribute");
763*0fca6ea1SDimitry Andric }
764*0fca6ea1SDimitry Andric 
765*0fca6ea1SDimitry Andric } // namespace clang
766