@@ -2542,24 +2542,23 @@ namespace {
2542
2542
void validateForeignReferenceType (const clang::CXXRecordDecl *decl,
2543
2543
ClassDecl *classDecl) {
2544
2544
2545
- enum class RetainReleaseOperatonKind {
2545
+ enum class RetainReleaseOperationKind {
2546
2546
notAfunction,
2547
- doesntReturnVoid ,
2547
+ doesntReturnVoidOrSelf ,
2548
2548
invalidParameters,
2549
2549
valid
2550
2550
};
2551
2551
2552
2552
auto getOperationValidity =
2553
- [&](ValueDecl *operation) -> RetainReleaseOperatonKind {
2553
+ [&](ValueDecl *operation,
2554
+ CustomRefCountingOperationKind operationKind)
2555
+ -> RetainReleaseOperationKind {
2554
2556
auto operationFn = dyn_cast<FuncDecl>(operation);
2555
2557
if (!operationFn)
2556
- return RetainReleaseOperatonKind::notAfunction;
2557
-
2558
- if (!operationFn->getResultInterfaceType ()->isVoid ())
2559
- return RetainReleaseOperatonKind::doesntReturnVoid;
2558
+ return RetainReleaseOperationKind::notAfunction;
2560
2559
2561
2560
if (operationFn->getParameters ()->size () != 1 )
2562
- return RetainReleaseOperatonKind ::invalidParameters;
2561
+ return RetainReleaseOperationKind ::invalidParameters;
2563
2562
2564
2563
Type paramType =
2565
2564
operationFn->getParameters ()->get (0 )->getInterfaceType ();
@@ -2569,20 +2568,31 @@ namespace {
2569
2568
}
2570
2569
2571
2570
swift::NominalTypeDecl *paramDecl = paramType->getAnyNominal ();
2571
+
2572
+ // The return type should be void (for release functions), or void
2573
+ // or the parameter type (for retain functions).
2574
+ auto resultInterfaceType = operationFn->getResultInterfaceType ();
2575
+ if (!resultInterfaceType->isVoid ()) {
2576
+ if (operationKind == CustomRefCountingOperationKind::release ||
2577
+ !resultInterfaceType->lookThroughSingleOptionalType ()->isEqual (paramType))
2578
+ return RetainReleaseOperationKind::doesntReturnVoidOrSelf;
2579
+ }
2580
+
2572
2581
// The parameter of the retain/release function should be pointer to the
2573
2582
// same FRT or a base FRT.
2574
2583
if (paramDecl != classDecl) {
2575
2584
if (const clang::Decl *paramClangDecl = paramDecl->getClangDecl ()) {
2576
2585
if (const auto *paramTypeDecl =
2577
2586
dyn_cast<clang::CXXRecordDecl>(paramClangDecl)) {
2578
2587
if (decl->isDerivedFrom (paramTypeDecl)) {
2579
- return RetainReleaseOperatonKind ::valid;
2588
+ return RetainReleaseOperationKind ::valid;
2580
2589
}
2581
2590
}
2582
2591
}
2583
- return RetainReleaseOperatonKind ::invalidParameters;
2592
+ return RetainReleaseOperationKind ::invalidParameters;
2584
2593
}
2585
- return RetainReleaseOperatonKind::valid;
2594
+
2595
+ return RetainReleaseOperationKind::valid;
2586
2596
};
2587
2597
2588
2598
auto retainOperation = evaluateOrDefault (
@@ -2619,28 +2629,29 @@ namespace {
2619
2629
false , retainOperation.name , decl->getNameAsString ());
2620
2630
} else if (retainOperation.kind ==
2621
2631
CustomRefCountingOperationResult::foundOperation) {
2622
- RetainReleaseOperatonKind operationKind =
2623
- getOperationValidity (retainOperation.operation );
2632
+ RetainReleaseOperationKind operationKind =
2633
+ getOperationValidity (retainOperation.operation ,
2634
+ CustomRefCountingOperationKind::retain);
2624
2635
HeaderLoc loc (decl->getLocation ());
2625
2636
switch (operationKind) {
2626
- case RetainReleaseOperatonKind ::notAfunction:
2637
+ case RetainReleaseOperationKind ::notAfunction:
2627
2638
Impl.diagnose (
2628
2639
loc,
2629
2640
diag::foreign_reference_types_retain_release_not_a_function_decl,
2630
2641
false , retainOperation.name );
2631
2642
break ;
2632
- case RetainReleaseOperatonKind::doesntReturnVoid :
2643
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2633
2644
Impl.diagnose (
2634
2645
loc,
2635
- diag::foreign_reference_types_retain_release_non_void_return_type ,
2636
- false , retainOperation.name );
2646
+ diag::foreign_reference_types_retain_non_void_or_self_return_type ,
2647
+ retainOperation.name );
2637
2648
break ;
2638
- case RetainReleaseOperatonKind ::invalidParameters:
2649
+ case RetainReleaseOperationKind ::invalidParameters:
2639
2650
Impl.diagnose (loc,
2640
2651
diag::foreign_reference_types_invalid_retain_release,
2641
2652
false , retainOperation.name , classDecl->getNameStr ());
2642
2653
break ;
2643
- case RetainReleaseOperatonKind ::valid:
2654
+ case RetainReleaseOperationKind ::valid:
2644
2655
break ;
2645
2656
}
2646
2657
} else {
@@ -2683,28 +2694,29 @@ namespace {
2683
2694
true , releaseOperation.name , decl->getNameAsString ());
2684
2695
} else if (releaseOperation.kind ==
2685
2696
CustomRefCountingOperationResult::foundOperation) {
2686
- RetainReleaseOperatonKind operationKind =
2687
- getOperationValidity (releaseOperation.operation );
2697
+ RetainReleaseOperationKind operationKind =
2698
+ getOperationValidity (releaseOperation.operation ,
2699
+ CustomRefCountingOperationKind::release);
2688
2700
HeaderLoc loc (decl->getLocation ());
2689
2701
switch (operationKind) {
2690
- case RetainReleaseOperatonKind ::notAfunction:
2702
+ case RetainReleaseOperationKind ::notAfunction:
2691
2703
Impl.diagnose (
2692
2704
loc,
2693
2705
diag::foreign_reference_types_retain_release_not_a_function_decl,
2694
2706
true , releaseOperation.name );
2695
2707
break ;
2696
- case RetainReleaseOperatonKind::doesntReturnVoid :
2708
+ case RetainReleaseOperationKind::doesntReturnVoidOrSelf :
2697
2709
Impl.diagnose (
2698
2710
loc,
2699
- diag::foreign_reference_types_retain_release_non_void_return_type ,
2700
- true , releaseOperation.name );
2711
+ diag::foreign_reference_types_release_non_void_return_type ,
2712
+ releaseOperation.name );
2701
2713
break ;
2702
- case RetainReleaseOperatonKind ::invalidParameters:
2714
+ case RetainReleaseOperationKind ::invalidParameters:
2703
2715
Impl.diagnose (loc,
2704
2716
diag::foreign_reference_types_invalid_retain_release,
2705
2717
true , releaseOperation.name , classDecl->getNameStr ());
2706
2718
break ;
2707
- case RetainReleaseOperatonKind ::valid:
2719
+ case RetainReleaseOperationKind ::valid:
2708
2720
break ;
2709
2721
}
2710
2722
} else {
0 commit comments