clang: lib/Sema/SemaSwift.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
22
25
27 StringRef Name) {
28 if (const auto *PrevSNA = D->getAttr()) {
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
38 }
40}
41
42
48
49
60
61
67 } else {
69 }
71 return false;
73}
74
76
78 ContextName.split(ContextNameComponents, '.');
79 return all_of(ContextNameComponents, [&](StringRef Component) {
81 });
82}
83
86 return;
87
88
89
90 StringRef Str;
91 if (.checkStringLiteralArgumentAttr(AL, 0, Str)) {
93 return;
94 }
95
97}
98
100
101
102 StringRef BT;
103 if (.checkStringLiteralArgumentAttr(AL, 0, BT))
104 return;
105
106
107
108 if (const auto *Other = D->getAttr()) {
109 if (Other->getSwiftType() != BT)
110 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
111 return;
112 }
113
115}
116
119 if (!PT)
120 return false;
121
123
124
126 if (const auto *ID = OPT->getInterfaceDecl())
128 return true;
129
130
132 if (auto *RD = PT->getPointeeType()->getAsRecordDecl();
134 return true;
135
136 return false;
137}
138
140 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
143 return true;
144 }
145
146 S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
147 << AL << isa(D);
148 return false;
149 };
150
151 auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
152
153
154
157 return true;
158
159 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
162 return false;
163 };
164
165 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
168 return true;
169
170 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
173 return false;
174 };
175
177 return;
178
180 SwiftErrorAttr::ConventionKind Convention;
181 if (!SwiftErrorAttr::ConvertStrToConventionKind(
183 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
185 return;
186 }
187
188 switch (Convention) {
189 case SwiftErrorAttr::None:
190
191 break;
192
193 case SwiftErrorAttr::NonNullError:
194 if (!hasErrorParameter(SemaRef, D, AL))
195 return;
196 break;
197
198 case SwiftErrorAttr::NullResult:
199 if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))
200 return;
201 break;
202
203 case SwiftErrorAttr::NonZeroResult:
204 case SwiftErrorAttr::ZeroResult:
205 if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))
206 return;
207 break;
208 }
209
211 SwiftErrorAttr(getASTContext(), AL, Convention));
212}
213
215 const SwiftAsyncErrorAttr *ErrorAttr,
216 const SwiftAsyncAttr *AsyncAttr) {
217 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
218 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
219 S.Diag(AsyncAttr->getLocation(),
220 diag::err_swift_async_error_without_swift_async)
221 << AsyncAttr << isa(D);
222 }
223 return;
224 }
225
227 D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
228
229
230 const auto *FuncTy = HandlerParam->getType()
235 if (FuncTy)
236 BlockParams = FuncTy->getParamTypes();
237
238 switch (ErrorAttr->getConvention()) {
239 case SwiftAsyncErrorAttr::ZeroArgument:
240 case SwiftAsyncErrorAttr::NonZeroArgument: {
241 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
243 S.Diag(ErrorAttr->getLocation(),
244 diag::err_attribute_argument_out_of_bounds)
245 << ErrorAttr << 2;
246 return;
247 }
250 StringRef ConvStr =
251 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
252 ? "zero_argument"
253 : "nonzero_argument";
254 S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
255 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
256 return;
257 }
258 break;
259 }
260 case SwiftAsyncErrorAttr::NonNullError: {
261 bool AnyErrorParams = false;
262 for (QualType Param : BlockParams) {
263
265 if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
267 AnyErrorParams = true;
268 break;
269 }
270 }
271 }
272
273 if (const auto *PtrTy = Param->getAs<PointerType>()) {
274 if (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl();
276 AnyErrorParams = true;
277 break;
278 }
279 }
280 }
281
282 if (!AnyErrorParams) {
283 S.Diag(ErrorAttr->getLocation(),
284 diag::err_swift_async_error_no_error_parameter)
285 << ErrorAttr << isa(D);
286 return;
287 }
288 break;
289 }
290 case SwiftAsyncErrorAttr::None:
291 break;
292 }
293}
294
297 SwiftAsyncErrorAttr::ConventionKind ConvKind;
298 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(
300 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
302 return;
303 }
304
306 switch (ConvKind) {
307 case SwiftAsyncErrorAttr::ZeroArgument:
308 case SwiftAsyncErrorAttr::NonZeroArgument: {
310 return;
311
314 return;
315 break;
316 }
317 case SwiftAsyncErrorAttr::NonNullError:
318 case SwiftAsyncErrorAttr::None: {
320 return;
321 break;
322 }
323 }
324
328
329 if (auto *AsyncAttr = D->getAttr())
331}
332
333
334
335
336
337
338
339
340
343 unsigned &SwiftParamCount,
344 bool &IsSingleParamInit) {
345 SwiftParamCount = 0;
346 IsSingleParamInit = false;
347
348
349 bool IsGetter = false, IsSetter = false;
350 if (Name.consume_front("getter:"))
351 IsGetter = true;
352 else if (Name.consume_front("setter:"))
353 IsSetter = true;
354
355 if (Name.empty() || Name.back() != ')') {
356 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
357 return false;
358 }
359
360 bool IsMember = false;
361 StringRef ContextName, BaseName, Parameters;
362
363 std::tie(BaseName, Parameters) = Name.split('(');
364
365
366
367 std::tie(ContextName, BaseName) = BaseName.rsplit('.');
368 if (BaseName.empty()) {
369 BaseName = ContextName;
370 ContextName = StringRef();
372 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
373 << AL << 1;
374 return false;
375 } else {
376 IsMember = true;
377 }
378
380 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
381 << AL << 0;
382 return false;
383 }
384
385 bool IsSubscript = BaseName == "subscript";
386
387 if (IsSubscript && !IsGetter && !IsSetter) {
388 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
389 << AL << 0;
390 return false;
391 }
392
393 if (Parameters.empty()) {
394 S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
395 return false;
396 }
397
398 assert(Parameters.back() == ')' && "expected ')'");
399 Parameters = Parameters.drop_back();
400
401 if (Parameters.empty()) {
402
403 if (IsSubscript) {
404 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
405 << AL << 1;
406 return false;
407 }
408
409 if (IsSetter) {
410 S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
411 return false;
412 }
413
414 return true;
415 }
416
417 if (Parameters.back() != ':') {
418 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
419 return false;
420 }
421
422 StringRef CurrentParam;
423 std::optional SelfLocation;
424 unsigned NewValueCount = 0;
425 std::optional NewValueLocation;
426 do {
427 std::tie(CurrentParam, Parameters) = Parameters.split(':');
428
430 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
431 << AL << 2;
432 return false;
433 }
434
435 if (IsMember && CurrentParam == "self") {
436
437
438
439 if (SelfLocation) {
440 S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
441 return false;
442 }
443
444
445 SelfLocation = SwiftParamCount;
446 } else if (CurrentParam == "newValue") {
447
448
449
450
451 ++NewValueCount;
452
453 NewValueLocation = SwiftParamCount;
454 }
455
456 ++SwiftParamCount;
457 } while (!Parameters.empty());
458
459
460 if (IsSubscript && !SelfLocation) {
461 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
462 << AL << 2;
463 return false;
464 }
465
466 IsSingleParamInit =
467 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
468
469
470 if (IsGetter || IsSetter) {
471
472 unsigned NumExpectedParams = IsGetter ? 0 : 1;
473 unsigned ParamDiag = IsGetter
474 ? diag::warn_attr_swift_name_getter_parameters
475 : diag::warn_attr_swift_name_setter_parameters;
476
477
478 if (SelfLocation)
479 ++NumExpectedParams;
480
481
482
483 if (IsSubscript) {
484 if (SwiftParamCount < NumExpectedParams) {
485 S.Diag(Loc, ParamDiag) << AL;
486 return false;
487 }
488
489
490
491 if (IsSetter) {
492 if (!NewValueLocation) {
493 S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
494 << AL;
495 return false;
496 }
497 if (NewValueCount > 1) {
499 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
500 << AL;
501 return false;
502 }
503 } else {
504
505 if (NewValueLocation) {
506 S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
507 << AL;
508 return false;
509 }
510 }
511 } else {
512
513 if (SwiftParamCount != NumExpectedParams) {
514 S.Diag(Loc, ParamDiag) << AL;
515 return false;
516 }
517 }
518 }
519
520 return true;
521}
522
524 const ParsedAttr &AL, bool IsAsync) {
527 unsigned ParamCount;
528
529 if (const auto *Method = dyn_cast(D)) {
530 ParamCount = Method->getSelector().getNumArgs();
531 Params = Method->parameters().slice(0, ParamCount);
532 } else {
534
535 ParamCount = F->getNumParams();
536 Params = F->parameters();
537
538 if (!F->hasWrittenPrototype()) {
539 Diag(Loc, diag::warn_attribute_wrong_decl_type)
542 return false;
543 }
544 }
545
546
547 if (IsAsync) {
548 if (ParamCount == 0) {
549 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
550 << AL << isa(D);
551 return false;
552 }
553 ParamCount -= 1;
554 }
555
556 unsigned SwiftParamCount;
557 bool IsSingleParamInit;
559 IsSingleParamInit))
560 return false;
561
562 bool ParamCountValid;
563 if (SwiftParamCount == ParamCount) {
564 ParamCountValid = true;
565 } else if (SwiftParamCount > ParamCount) {
566 ParamCountValid = IsSingleParamInit && ParamCount == 0;
567 } else {
568
569
570
571 unsigned MaybeOutParamCount =
572 llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {
573 QualType ParamTy = Param->getType();
576 return false;
577 });
578
579 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
580 }
581
582 if (!ParamCountValid) {
583 Diag(Loc, diag::warn_attr_swift_name_num_params)
584 << (SwiftParamCount > ParamCount) << AL << ParamCount
585 << SwiftParamCount;
586 return false;
587 }
592 !IsAsync) {
593 StringRef ContextName, BaseName;
594
595 std::tie(ContextName, BaseName) = Name.rsplit('.');
596 if (BaseName.empty()) {
597 BaseName = ContextName;
598 ContextName = StringRef();
600 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
601 << AL << 1;
602 return false;
603 }
604
606 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
607 << AL << 0;
608 return false;
609 }
610 } else {
611 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
612 return false;
613 }
614 return true;
615}
616
618 StringRef Name;
620 if (.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
621 return;
622
623 if ((D, Name, Loc, AL, false))
624 return;
625
627}
628
630 StringRef Name;
632 if (.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
633 return;
634
635 if ((D, Name, Loc, AL, true))
636 return;
637
640}
641
643
645 return;
646
648 Diag(AL.getLoc(), diag::err_attribute_argument_type)
650 return;
651 }
652
653 SwiftNewTypeAttr::NewtypeKind Kind;
655 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
656 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
657 return;
658 }
659
661 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
663 return;
664 }
665
668}
669
672 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
674 return;
675 }
676
677 SwiftAsyncAttr::Kind Kind;
679 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
680 Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
681 return;
682 }
683
685 if (Kind == SwiftAsyncAttr::None) {
686
688 return;
689 } else {
690
692 return;
693
695 if (.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))
696 return;
697
700 QualType CompletionBlockType = CompletionBlock->getType();
702 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
703 << CompletionBlock->getType();
704 return;
705 }
709 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)
710 << CompletionBlock->getType();
711 return;
712 }
713 }
714
715 auto *AsyncAttr =
718
719 if (auto *ErrorAttr = D->getAttr())
721}
722
727
729 if (existingAttr->getABI() != abi) {
730 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
733 existingAttr->isRegularKeywordAttribute());
734 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
735 return;
736 }
737 }
738
739 switch (abi) {
742 llvm_unreachable("explicit attribute for non-swift parameter ABI?");
744 llvm_unreachable("explicit attribute for ordinary parameter ABI?");
745
748 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
750 }
751 D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
752 return;
753
756 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
758 }
759 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
760 return;
761
764 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
766 }
767 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
768 return;
769
772 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
774 }
775 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
776 return;
777 }
778 llvm_unreachable("bad parameter ABI attribute");
779}
780
781}
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 ...
bool isRegularKeywordAttribute() const
SourceLocation getLoc() const
Decl - This represents one declaration (or definition), e.g.
bool isInvalidDecl() const
SourceLocation getLocation() const
This represents one expression.
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
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.
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
unsigned getASTIndex() const
Get the parameter index as it would normally be encoded at the AST level of representation: zero-orig...
A parameter attribute which changes the argument-passing ABI rule for the parameter.
Represents a parameter to a function.
ParsedAttr - Represents a syntactic attribute.
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
IdentifierLoc * getArgAsIdent(unsigned Arg) const
void setInvalid(bool b=true) const
bool isArgIdent(unsigned Arg) const
Expr * getArgAsExpr(unsigned Arg) const
bool isUsedAsTypeAttr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isConstQualified() const
Determine whether this type is const-qualified.
Base for LValueReferenceType and RValueReferenceType.
ASTContext & getASTContext() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
bool isCFError(RecordDecl *D)
IdentifierInfo * getNSErrorIdent()
Retrieve the identifier "NSError".
void handleBridge(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:99
void handleAsyncAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:670
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:523
void handleAsyncName(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:629
SwiftNameAttr * mergeNameAttr(Decl *D, const SwiftNameAttr &SNA, StringRef Name)
Definition SemaSwift.cpp:26
void handleNewType(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:642
SemaSwift(Sema &S)
Definition SemaSwift.cpp:24
void handleError(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:139
void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI abi)
Definition SemaSwift.cpp:723
void handleAsyncError(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:295
void handleName(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:617
void handleAttrAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSwift.cpp:84
Sema - This implements semantic analysis and AST building for C.
Encodes a location in the source.
bool isBlockPointerType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
const T * getAs() const
Member-template getAs'.
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
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:214
bool isa(CodeGen::Address addr)
@ ExpectedFunctionWithProtoType
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)
static bool isValidSwiftContextName(StringRef ContextName)
Definition SemaSwift.cpp:75
const ParmVarDecl * getFunctionOrMethodParam(const Decl *D, unsigned Idx)
static bool isErrorParameter(Sema &S, QualType QT)
Definition SemaSwift.cpp:117
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
static bool isValidSwiftIndirectResultType(QualType Ty)
Pointers and references in the default address space.
Definition SemaSwift.cpp:50
QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx)
@ AANT_ArgumentIdentifier
ParameterABI
Kinds of parameter ABI.
@ 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:341
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.