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