clang 24.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
14#include "clang/AST/DeclBase.h"
18#include "clang/Sema/Attr.h"
20#include "clang/Sema/Sema.h"
21#include "clang/Sema/SemaObjC.h"
22
23namespace clang {
25
26SwiftNameAttr *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
75static bool isValidIdentifierEscapedChar(char c) {
76 if (c == '`' || c == '\\')
77 return false;
78
79 unsigned char uc = static_cast<unsigned char>(c);
80 // ASCII control characters and non-ASCII characters are not allowed.
81 if (uc < 0x20 || uc >= 0x7F)
82 return false;
83
84 return true;
85}
86
87static bool isValidAsEscapedIdentifier(StringRef string) {
88 if (string.empty())
89 return false;
90
91 bool allSpace = true;
92 for (char c : string) {
94 return false;
95 if (c != ' ')
96 allSpace = false;
97 }
98
99 return !allSpace;
100}
101
102static std::pair<StringRef, StringRef> backtickAwareSplit(StringRef text,
103 char separator) {
104 bool inBackticks = false;
105 for (size_t i = 0; i < text.size(); ++i) {
106 char c = text[i];
107 if (c == '`') {
108 inBackticks = !inBackticks;
109 } else if (c == separator && !inBackticks) {
110 return {text.substr(0, i), text.substr(i + 1)};
111 }
112 }
113 return {text, StringRef()};
114}
115
116static std::pair<StringRef, StringRef> backtickAwareRSplit(StringRef text,
117 char separator) {
118 bool inBackticks = false;
119 for (size_t i = text.size(); i > 0; --i) {
120 char c = text[i - 1];
121 if (c == '`') {
122 inBackticks = !inBackticks;
123 } else if (c == separator && !inBackticks) {
124 return {text.substr(0, i - 1), text.substr(i)};
125 }
126 }
127 return {text, StringRef()};
128}
129
130/// Returns true if the string is a valid ASCII Swift identifier. This includes
131/// raw identifiers if they are surrounded by backticks (e.g., "`My Struct`").
132static bool isValidSwiftIdentifier(StringRef text) {
133 if (text.size() > 2 && text.front() == '`' && text.back() == '`')
134 return isValidAsEscapedIdentifier(text.drop_front().drop_back());
135 return isValidAsciiIdentifier(text);
136}
137
138static bool isValidSwiftContextName(StringRef ContextName) {
139 // ContextName might be qualified, e.g. 'MyNamespace.MyStruct'.
140 StringRef First, Rest = ContextName;
141 do {
142 std::tie(First, Rest) = backtickAwareSplit(Rest, '.');
144 return false;
145 } while (!Rest.empty());
146 return true;
147}
148
150 if (AL.isInvalid() || AL.isUsedAsTypeAttr())
151 return;
152
153 // Make sure that there is a string literal as the annotation's single
154 // argument.
155 StringRef Str;
156 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str)) {
157 AL.setInvalid();
158 return;
159 }
160
161 D->addAttr(::new (getASTContext()) SwiftAttrAttr(getASTContext(), AL, Str));
162}
163
165 // Make sure that there is a string literal as the annotation's single
166 // argument.
167 StringRef BT;
168 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT))
169 return;
170
171 // Warn about duplicate attributes if they have different arguments, but drop
172 // any duplicate attributes regardless.
173 if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
174 if (Other->getSwiftType() != BT)
175 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
176 return;
177 }
178
179 D->addAttr(::new (getASTContext()) SwiftBridgeAttr(getASTContext(), AL, BT));
180}
181
182static bool isErrorParameter(Sema &S, QualType QT) {
183 const auto *PT = QT->getAs<PointerType>();
184 if (!PT)
185 return false;
186
187 QualType Pointee = PT->getPointeeType();
188
189 // Check for NSError**.
190 if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
191 if (const auto *ID = OPT->getInterfaceDecl())
192 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent())
193 return true;
194
195 // Check for CFError**.
196 if (const auto *PT = Pointee->getAs<PointerType>())
197 if (auto *RD = PT->getPointeeType()->getAsRecordDecl();
198 RD && S.ObjC().isCFError(RD))
199 return true;
200
201 return false;
202}
203
205 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
206 for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
208 return true;
209 }
210
211 S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
212 << AL << isa<ObjCMethodDecl>(D);
213 return false;
214 };
215
216 auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
217 // - C, ObjC, and block pointers are definitely okay.
218 // - References are definitely not okay.
219 // - nullptr_t is weird, but acceptable.
221 if (RT->hasPointerRepresentation() && !RT->isReferenceType())
222 return true;
223
224 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
225 << AL << AL.getArgAsIdent(0)->getIdentifierInfo()->getName()
226 << isa<ObjCMethodDecl>(D) << /*pointer*/ 1;
227 return false;
228 };
229
230 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
232 if (RT->isIntegralType(S.Context))
233 return true;
234
235 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
236 << AL << AL.getArgAsIdent(0)->getIdentifierInfo()->getName()
237 << isa<ObjCMethodDecl>(D) << /*integral*/ 0;
238 return false;
239 };
240
241 if (D->isInvalidDecl())
242 return;
243
244 IdentifierLoc *Loc = AL.getArgAsIdent(0);
245 SwiftErrorAttr::ConventionKind Convention;
246 if (!SwiftErrorAttr::ConvertStrToConventionKind(
247 Loc->getIdentifierInfo()->getName(), Convention)) {
248 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
249 << AL << Loc->getIdentifierInfo();
250 return;
251 }
252
253 switch (Convention) {
254 case SwiftErrorAttr::None:
255 // No additional validation required.
256 break;
257
258 case SwiftErrorAttr::NonNullError:
259 if (!hasErrorParameter(SemaRef, D, AL))
260 return;
261 break;
262
263 case SwiftErrorAttr::NullResult:
264 if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))
265 return;
266 break;
267
268 case SwiftErrorAttr::NonZeroResult:
269 case SwiftErrorAttr::ZeroResult:
270 if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))
271 return;
272 break;
273 }
274
275 D->addAttr(::new (getASTContext())
276 SwiftErrorAttr(getASTContext(), AL, Convention));
277}
278
280 const SwiftAsyncErrorAttr *ErrorAttr,
281 const SwiftAsyncAttr *AsyncAttr) {
282 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
283 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
284 S.Diag(AsyncAttr->getLocation(),
285 diag::err_swift_async_error_without_swift_async)
286 << AsyncAttr << isa<ObjCMethodDecl>(D);
287 }
288 return;
289 }
290
291 const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
292 D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
293 // handleSwiftAsyncAttr already verified the type is correct, so no need to
294 // double-check it here.
295 const auto *FuncTy = HandlerParam->getType()
299 ArrayRef<QualType> BlockParams;
300 if (FuncTy)
301 BlockParams = FuncTy->getParamTypes();
302
303 switch (ErrorAttr->getConvention()) {
304 case SwiftAsyncErrorAttr::ZeroArgument:
305 case SwiftAsyncErrorAttr::NonZeroArgument: {
306 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
307 if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
308 S.Diag(ErrorAttr->getLocation(),
309 diag::err_attribute_argument_out_of_bounds)
310 << ErrorAttr << 2;
311 return;
312 }
313 QualType ErrorParam = BlockParams[ParamIdx - 1];
314 if (!ErrorParam->isIntegralType(S.Context)) {
315 StringRef ConvStr =
316 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
317 ? "zero_argument"
318 : "nonzero_argument";
319 S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
320 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
321 return;
322 }
323 break;
324 }
325 case SwiftAsyncErrorAttr::NonNullError: {
326 bool AnyErrorParams = false;
327 for (QualType Param : BlockParams) {
328 // Check for NSError *.
329 if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
330 if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
331 if (ID->getIdentifier() == S.ObjC().getNSErrorIdent()) {
332 AnyErrorParams = true;
333 break;
334 }
335 }
336 }
337 // Check for CFError *.
338 if (const auto *PtrTy = Param->getAs<PointerType>()) {
339 if (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl();
340 RD && S.ObjC().isCFError(RD)) {
341 AnyErrorParams = true;
342 break;
343 }
344 }
345 }
346
347 if (!AnyErrorParams) {
348 S.Diag(ErrorAttr->getLocation(),
349 diag::err_swift_async_error_no_error_parameter)
350 << ErrorAttr << isa<ObjCMethodDecl>(D);
351 return;
352 }
353 break;
354 }
355 case SwiftAsyncErrorAttr::None:
356 break;
357 }
358}
359
361 IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
362 SwiftAsyncErrorAttr::ConventionKind ConvKind;
363 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(
364 IDLoc->getIdentifierInfo()->getName(), ConvKind)) {
365 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
366 << AL << IDLoc->getIdentifierInfo();
367 return;
368 }
369
370 uint32_t ParamIdx = 0;
371 switch (ConvKind) {
372 case SwiftAsyncErrorAttr::ZeroArgument:
373 case SwiftAsyncErrorAttr::NonZeroArgument: {
374 if (!AL.checkExactlyNumArgs(SemaRef, 2))
375 return;
376
377 Expr *IdxExpr = AL.getArgAsExpr(1);
378 if (!SemaRef.checkUInt32Argument(AL, IdxExpr, ParamIdx))
379 return;
380 break;
381 }
382 case SwiftAsyncErrorAttr::NonNullError:
383 case SwiftAsyncErrorAttr::None: {
384 if (!AL.checkExactlyNumArgs(SemaRef, 1))
385 return;
386 break;
387 }
388 }
389
390 auto *ErrorAttr = ::new (getASTContext())
391 SwiftAsyncErrorAttr(getASTContext(), AL, ConvKind, ParamIdx);
392 D->addAttr(ErrorAttr);
393
394 if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
395 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
396}
397
398// For a function, this will validate a compound Swift name, e.g.
399// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
400// the function will output the number of parameter names, and whether this is a
401// single-arg initializer.
402//
403// For a type, enum constant, property, or variable declaration, this will
404// validate either a simple identifier, or a qualified
405// <code>context.identifier</code> name.
406static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
407 SourceLocation Loc, StringRef Name,
408 unsigned &SwiftParamCount,
409 bool &IsSingleParamInit) {
410 SwiftParamCount = 0;
411 IsSingleParamInit = false;
412
413 // Check whether this will be mapped to a getter or setter of a property.
414 bool IsGetter = false, IsSetter = false;
415 if (Name.consume_front("getter:"))
416 IsGetter = true;
417 else if (Name.consume_front("setter:"))
418 IsSetter = true;
419
420 if (Name.empty() || Name.back() != ')') {
421 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
422 return false;
423 }
424
425 bool IsMember = false;
426 StringRef ContextName, BaseName, Parameters;
427
428 std::tie(BaseName, Parameters) = backtickAwareSplit(Name, '(');
429
430 // Split at the last '.', if it exists, which separates the context name
431 // from the base name.
432 std::tie(ContextName, BaseName) = backtickAwareRSplit(BaseName, '.');
433 if (BaseName.empty()) {
434 BaseName = ContextName;
435 ContextName = StringRef();
436 } else if (ContextName.empty() || !isValidSwiftContextName(ContextName)) {
437 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
438 << AL << /*context*/ 1;
439 return false;
440 } else {
441 IsMember = true;
442 }
443
444 if (!isValidSwiftIdentifier(BaseName) || BaseName == "_") {
445 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
446 << AL << /*basename*/ 0;
447 return false;
448 }
449
450 bool IsSubscript = BaseName == "subscript";
451 // A subscript accessor must be a getter or setter.
452 if (IsSubscript && !IsGetter && !IsSetter) {
453 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
454 << AL << /* getter or setter */ 0;
455 return false;
456 }
457
458 if (Parameters.empty()) {
459 S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
460 return false;
461 }
462
463 assert(Parameters.back() == ')' && "expected ')'");
464 Parameters = Parameters.drop_back(); // ')'
465
466 if (Parameters.empty()) {
467 // Setters and subscripts must have at least one parameter.
468 if (IsSubscript) {
469 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
470 << AL << /* have at least one parameter */ 1;
471 return false;
472 }
473
474 if (IsSetter) {
475 S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
476 return false;
477 }
478
479 return true;
480 }
481
482 if (Parameters.back() != ':') {
483 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
484 return false;
485 }
486
487 StringRef CurrentParam;
488 std::optional<unsigned> SelfLocation;
489 unsigned NewValueCount = 0;
490 std::optional<unsigned> NewValueLocation;
491 do {
492 std::tie(CurrentParam, Parameters) = backtickAwareSplit(Parameters, ':');
493
494 if (!isValidSwiftIdentifier(CurrentParam)) {
495 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
496 << AL << /*parameter*/ 2;
497 return false;
498 }
499
500 if (IsMember && CurrentParam == "self") {
501 // "self" indicates the "self" argument for a member.
502
503 // More than one "self"?
504 if (SelfLocation) {
505 S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
506 return false;
507 }
508
509 // The "self" location is the current parameter.
510 SelfLocation = SwiftParamCount;
511 } else if (CurrentParam == "newValue") {
512 // "newValue" indicates the "newValue" argument for a setter.
513
514 // There should only be one 'newValue', but it's only significant for
515 // subscript accessors, so don't error right away.
516 ++NewValueCount;
517
518 NewValueLocation = SwiftParamCount;
519 }
520
521 ++SwiftParamCount;
522 } while (!Parameters.empty());
523
524 // Only instance subscripts are currently supported.
525 if (IsSubscript && !SelfLocation) {
526 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
527 << AL << /*have a 'self:' parameter*/ 2;
528 return false;
529 }
530
531 IsSingleParamInit =
532 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
533
534 // Check the number of parameters for a getter/setter.
535 if (IsGetter || IsSetter) {
536 // Setters have one parameter for the new value.
537 unsigned NumExpectedParams = IsGetter ? 0 : 1;
538 unsigned ParamDiag = IsGetter
539 ? diag::warn_attr_swift_name_getter_parameters
540 : diag::warn_attr_swift_name_setter_parameters;
541
542 // Instance methods have one parameter for "self".
543 if (SelfLocation)
544 ++NumExpectedParams;
545
546 // Subscripts may have additional parameters beyond the expected params for
547 // the index.
548 if (IsSubscript) {
549 if (SwiftParamCount < NumExpectedParams) {
550 S.Diag(Loc, ParamDiag) << AL;
551 return false;
552 }
553
554 // A subscript setter must explicitly label its newValue parameter to
555 // distinguish it from index parameters.
556 if (IsSetter) {
557 if (!NewValueLocation) {
558 S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
559 << AL;
560 return false;
561 }
562 if (NewValueCount > 1) {
563 S.Diag(Loc,
564 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
565 << AL;
566 return false;
567 }
568 } else {
569 // Subscript getters should have no 'newValue:' parameter.
570 if (NewValueLocation) {
571 S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
572 << AL;
573 return false;
574 }
575 }
576 } else {
577 // Property accessors must have exactly the number of expected params.
578 if (SwiftParamCount != NumExpectedParams) {
579 S.Diag(Loc, ParamDiag) << AL;
580 return false;
581 }
582 }
583 }
584
585 return true;
586}
587
588bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
589 const ParsedAttr &AL, bool IsAsync) {
592 unsigned ParamCount;
593
594 if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
595 ParamCount = Method->getSelector().getNumArgs();
596 Params = Method->parameters().slice(0, ParamCount);
597 } else {
598 const auto *F = cast<FunctionDecl>(D);
599
600 ParamCount = F->getNumParams();
601 Params = F->parameters();
602
603 if (!F->hasWrittenPrototype()) {
604 Diag(Loc, diag::warn_attribute_wrong_decl_type)
605 << AL << AL.isRegularKeywordAttribute()
607 return false;
608 }
609 }
610
611 // The async name drops the last callback parameter.
612 if (IsAsync) {
613 if (ParamCount == 0) {
614 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
615 << AL << isa<ObjCMethodDecl>(D);
616 return false;
617 }
618 ParamCount -= 1;
619 }
620
621 unsigned SwiftParamCount;
622 bool IsSingleParamInit;
623 if (!validateSwiftFunctionName(SemaRef, AL, Loc, Name, SwiftParamCount,
624 IsSingleParamInit))
625 return false;
626
627 bool ParamCountValid;
628 if (SwiftParamCount == ParamCount) {
629 ParamCountValid = true;
630 } else if (SwiftParamCount > ParamCount) {
631 ParamCountValid = IsSingleParamInit && ParamCount == 0;
632 } else {
633 // We have fewer Swift parameters than Objective-C parameters, but that
634 // might be because we've transformed some of them. Check for potential
635 // "out" parameters and err on the side of not warning.
636 unsigned MaybeOutParamCount =
637 llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {
638 QualType ParamTy = Param->getType();
639 if (ParamTy->isReferenceType() || ParamTy->isPointerType())
640 return !ParamTy->getPointeeType().isConstQualified();
641 return false;
642 });
643
644 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
645 }
646
647 if (!ParamCountValid) {
648 Diag(Loc, diag::warn_attr_swift_name_num_params)
649 << (SwiftParamCount > ParamCount) << AL << ParamCount
650 << SwiftParamCount;
651 return false;
652 }
653 } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
657 !IsAsync) {
658 StringRef ContextName, BaseName;
659
660 std::tie(ContextName, BaseName) = backtickAwareRSplit(Name, '.');
661 if (BaseName.empty()) {
662 BaseName = ContextName;
663 ContextName = StringRef();
664 } else if (!isValidSwiftContextName(ContextName)) {
665 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
666 << AL << /*context*/ 1;
667 return false;
668 }
669
670 if (!isValidSwiftIdentifier(BaseName)) {
671 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
672 << AL << /*basename*/ 0;
673 return false;
674 }
675 } else {
676 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
677 return false;
678 }
679 return true;
680}
681
683 StringRef Name;
684 SourceLocation Loc;
685 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
686 return;
687
688 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/false))
689 return;
690
691 D->addAttr(::new (getASTContext()) SwiftNameAttr(getASTContext(), AL, Name));
692}
693
695 StringRef Name;
696 SourceLocation Loc;
697 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
698 return;
699
700 if (!DiagnoseName(D, Name, Loc, AL, /*IsAsync=*/true))
701 return;
702
703 D->addAttr(::new (getASTContext())
704 SwiftAsyncNameAttr(getASTContext(), AL, Name));
705}
706
708 // Make sure that there is an identifier as the annotation's single argument.
709 if (!AL.checkExactlyNumArgs(SemaRef, 1))
710 return;
711
712 if (!AL.isArgIdent(0)) {
713 Diag(AL.getLoc(), diag::err_attribute_argument_type)
715 return;
716 }
717
718 SwiftNewTypeAttr::NewtypeKind Kind;
720 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
721 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
722 return;
723 }
724
725 if (!isa<TypedefNameDecl>(D)) {
726 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
728 return;
729 }
730
731 D->addAttr(::new (getASTContext())
732 SwiftNewTypeAttr(getASTContext(), AL, Kind));
733}
734
736 if (!AL.isArgIdent(0)) {
737 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
738 << AL << 1 << AANT_ArgumentIdentifier;
739 return;
740 }
741
742 SwiftAsyncAttr::Kind Kind;
744 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
745 Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
746 return;
747 }
748
749 ParamIdx Idx;
750 if (Kind == SwiftAsyncAttr::None) {
751 // If this is 'none', then there shouldn't be any additional arguments.
752 if (!AL.checkExactlyNumArgs(SemaRef, 1))
753 return;
754 } else {
755 // Non-none swift_async requires a completion handler index argument.
756 if (!AL.checkExactlyNumArgs(SemaRef, 2))
757 return;
758
759 Expr *HandlerIdx = AL.getArgAsExpr(1);
760 if (!SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))
761 return;
762
763 const ParmVarDecl *CompletionBlock =
765 QualType CompletionBlockType = CompletionBlock->getType();
766 if (!CompletionBlockType->isBlockPointerType()) {
767 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
768 << CompletionBlock->getType();
769 return;
770 }
771 QualType BlockTy =
772 CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
773 if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
774 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
775 << CompletionBlock->getType();
776 return;
777 }
778 }
779
780 auto *AsyncAttr =
781 ::new (getASTContext()) SwiftAsyncAttr(getASTContext(), AL, Kind, Idx);
782 D->addAttr(AsyncAttr);
783
784 if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
785 checkSwiftAsyncErrorBlock(SemaRef, D, ErrorAttr, AsyncAttr);
786}
787
790 ASTContext &Context = getASTContext();
791 QualType type = cast<ParmVarDecl>(D)->getType();
792
793 if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
794 if (existingAttr->getABI() != abi) {
795 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
796 << getParameterABISpelling(abi) << existingAttr
797 << (CI.isRegularKeywordAttribute() ||
798 existingAttr->isRegularKeywordAttribute());
799 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
800 return;
801 }
802 }
803
804 switch (abi) {
807 llvm_unreachable("explicit attribute for non-swift parameter ABI?");
809 llvm_unreachable("explicit attribute for ordinary parameter ABI?");
810
813 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
814 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
815 }
816 D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
817 return;
818
821 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
822 << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
823 }
824 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
825 return;
826
829 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
830 << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
831 }
832 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
833 return;
834
837 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
838 << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
839 }
840 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
841 return;
842 }
843 llvm_unreachable("bad parameter ABI attribute");
844}
845
846} // namespace clang
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:223
SourceLocation getLoc() const
Pointer to a block type.
Definition TypeBase.h:3656
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
void addAttr(Attr *A)
bool isInvalidDecl() const
Definition DeclBase.h:596
SourceLocation getLocation() const
Definition DeclBase.h:447
void dropAttr()
Definition DeclBase.h:564
This represents one expression.
Definition Expr.h:112
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4617
QualType getReturnType() const
Definition TypeBase.h:4957
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A simple pair of identifier info and location.
IdentifierInfo * getIdentifierInfo() const
Represents a pointer to an Objective C object.
Definition TypeBase.h:8122
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Definition Attr.h:279
unsigned getASTIndex() const
Get the parameter index as it would normally be encoded at the AST level of representation: zero-orig...
Definition Attr.h:362
A parameter attribute which changes the argument-passing ABI rule for the parameter.
Definition Attr.h:260
Represents a parameter to a function.
Definition Decl.h:1819
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition ParsedAttr.h:389
void setInvalid(bool b=true) const
Definition ParsedAttr.h:345
bool isArgIdent(unsigned Arg) const
Definition ParsedAttr.h:385
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
bool isUsedAsTypeAttr() const
Definition ParsedAttr.h:359
bool isInvalid() const
Definition ParsedAttr.h:344
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3408
A (possibly-)qualified type.
Definition TypeBase.h:938
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8630
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8544
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8577
bool empty() const
Definition TypeBase.h:648
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3687
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
bool isCFError(RecordDecl *D)
IdentifierInfo * getNSErrorIdent()
Retrieve the identifier "NSError".
void handleBridge(Decl *D, const ParsedAttr &AL)
void handleAsyncAttr(Decl *D, const ParsedAttr &AL)
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...
void handleAsyncName(Decl *D, const ParsedAttr &AL)
SwiftNameAttr * mergeNameAttr(Decl *D, const SwiftNameAttr &SNA, StringRef Name)
Definition SemaSwift.cpp:26
void handleNewType(Decl *D, const ParsedAttr &AL)
SemaSwift(Sema &S)
Definition SemaSwift.cpp:24
void handleError(Decl *D, const ParsedAttr &AL)
void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI abi)
void handleAsyncError(Decl *D, const ParsedAttr &AL)
void handleName(Decl *D, const ParsedAttr &AL)
void handleAttrAttr(Decl *D, const ParsedAttr &AL)
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:864
ASTContext & Context
Definition Sema.h:1305
SemaObjC & ObjC()
Definition Sema.h:1517
Encodes a location in the source.
bool isBlockPointerType() const
Definition TypeBase.h:8761
bool isVoidType() const
Definition TypeBase.h:9113
bool isPointerType() const
Definition TypeBase.h:8741
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9407
bool isReferenceType() const
Definition TypeBase.h:8765
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2186
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2859
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
Definition TypeBase.h:9284
QualType getType() const
Definition Decl.h:723
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Top level wrappers for InstallAPI frontend operations.
static bool isValidAsEscapedIdentifier(StringRef string)
Definition SemaSwift.cpp:87
static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, const SwiftAsyncErrorAttr *ErrorAttr, const SwiftAsyncAttr *AsyncAttr)
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ ExpectedFunctionWithProtoType
@ ExpectedTypedef
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:130
static bool isValidSwiftContextName(StringRef ContextName)
const ParmVarDecl * getFunctionOrMethodParam(const Decl *D, unsigned Idx)
getFunctionOrMethodParam - Return parameter declaration for the given index of the passed Decl,...
Definition Attr.h:77
static bool isErrorParameter(Sema &S, QualType QT)
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:115
static std::pair< StringRef, StringRef > backtickAwareSplit(StringRef text, char separator)
@ AANT_ArgumentIdentifier
static std::pair< StringRef, StringRef > backtickAwareRSplit(StringRef text, char separator)
ParameterABI
Kinds of parameter ABI.
Definition Specifiers.h:381
@ SwiftAsyncContext
This parameter (which must have pointer type) uses the special Swift asynchronous context-pointer ABI...
Definition Specifiers.h:402
@ SwiftErrorResult
This parameter (which must have pointer-to-pointer type) uses the special Swift error-result ABI trea...
Definition Specifiers.h:392
@ Ordinary
This parameter uses ordinary ABI rules for its type.
Definition Specifiers.h:383
@ SwiftIndirectResult
This parameter (which must have pointer type) is a Swift indirect result parameter.
Definition Specifiers.h:387
@ SwiftContext
This parameter (which must have pointer type) uses the special Swift context-pointer ABI treatment.
Definition Specifiers.h:397
static bool isValidSwiftContextType(QualType Ty)
Pointer-like types in the default address space.
Definition SemaSwift.cpp:43
static bool isValidSwiftIdentifier(StringRef text)
Returns true if the string is a valid ASCII Swift identifier.
static bool isValidIdentifierEscapedChar(char c)
Definition SemaSwift.cpp:75
static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, StringRef Name, unsigned &SwiftParamCount, bool &IsSingleParamInit)
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition Attr.h:65
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1774
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t