Skip to content

Commit d0105f5

Browse files
committed
Sema: Fix incorrect 'static' operator check
We were not enforcing that operators were static if the operator was defined in a final class, or if it was defined in a non-final class but the operator was itself final. Fixes <rdar://problem/31469036>.
1 parent c3ac890 commit d0105f5

File tree

2 files changed

+14
-25
lines changed

2 files changed

+14
-25
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,35 +4733,24 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
47334733
// Check for static/final/class when we're in a type.
47344734
auto dc = FD->getDeclContext();
47354735
if (dc->isTypeContext()) {
4736-
// Within a class, operator functions must be 'static' or 'final'.
4737-
if (auto classDecl = dc->getAsClassOrClassExtensionContext()) {
4738-
// For a class, we also need the function or class to be 'final'.
4739-
if (!classDecl->isFinal() && !FD->isFinal() &&
4740-
FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) {
4741-
if (!FD->isStatic()) {
4742-
TC.diagnose(FD->getLoc(), diag::nonstatic_operator_in_type,
4743-
operatorName,
4744-
dc->getDeclaredInterfaceType())
4745-
.fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
4746-
"static ");
4747-
4748-
FD->setStatic();
4749-
} else {
4750-
TC.diagnose(FD->getLoc(), diag::nonfinal_operator_in_class,
4751-
operatorName, dc->getDeclaredInterfaceType())
4752-
.fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
4753-
"final ");
4754-
FD->getAttrs().add(new (TC.Context) FinalAttr(/*IsImplicit=*/true));
4755-
}
4756-
}
4757-
} else if (!FD->isStatic()) {
4758-
// Operator functions must be static.
4759-
TC.diagnose(FD, diag::nonstatic_operator_in_type,
4736+
if (!FD->isStatic()) {
4737+
TC.diagnose(FD->getLoc(), diag::nonstatic_operator_in_type,
47604738
operatorName,
47614739
dc->getDeclaredInterfaceType())
47624740
.fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
47634741
"static ");
4742+
47644743
FD->setStatic();
4744+
} else if (auto classDecl = dc->getAsClassOrClassExtensionContext()) {
4745+
// For a class, we also need the function or class to be 'final'.
4746+
if (!classDecl->isFinal() && !FD->isFinal() &&
4747+
FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) {
4748+
TC.diagnose(FD->getLoc(), diag::nonfinal_operator_in_class,
4749+
operatorName, dc->getDeclaredInterfaceType())
4750+
.fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
4751+
"final ");
4752+
FD->getAttrs().add(new (TC.Context) FinalAttr(/*IsImplicit=*/true));
4753+
}
47654754
}
47664755
} else if (!dc->isModuleScopeContext()) {
47674756
TC.diagnose(FD, diag::operator_in_local_scope);

test/decl/func/operator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class C0 {
228228
}
229229

230230
class C1 {
231-
final func %%%(lhs: C1, rhs: C1) -> C1 { return lhs }
231+
final func %%%(lhs: C1, rhs: C1) -> C1 { return lhs } // expected-error{{operator '%%%' declared in type 'C1' must be 'static'}}{{3-3=static }}
232232
}
233233

234234
final class C2 {

0 commit comments

Comments
 (0)