Skip to content

Commit aa1e4ee

Browse files
committed
sema: check if @_originalDefinedIn attribute has duplicated entries for the same platform name
1 parent 7f8c04e commit aa1e4ee

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,9 @@ WARNING(option_set_zero_constant,none,
14721472
NOTE(option_set_empty_set_init,none,
14731473
"use [] to silence this warning", ())
14741474

1475+
ERROR(originally_defined_in_dupe_platform,none,
1476+
"duplicate version number for platform %0", (StringRef))
1477+
14751478
// Alignment attribute
14761479
ERROR(alignment_not_power_of_two,none,
14771480
"alignment value must be a power of two", ())

lib/Sema/TypeCheckAttr.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
111111
IGNORED_ATTR(DisfavoredOverload)
112112
IGNORED_ATTR(ProjectedValueProperty)
113113
IGNORED_ATTR(ReferenceOwnership)
114+
IGNORED_ATTR(OriginallyDefinedIn)
114115

115116
// TODO: Changes are yet to be upstreamed from apple/tensorflow branch.
116117
IGNORED_ATTR(Differentiable)
@@ -177,7 +178,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
177178
void visitFinalAttr(FinalAttr *attr);
178179
void visitIBActionAttr(IBActionAttr *attr);
179180
void visitIBSegueActionAttr(IBSegueActionAttr *attr);
180-
void visitOriginallyDefinedInAttr(OriginallyDefinedInAttr *attr);
181181
void visitLazyAttr(LazyAttr *attr);
182182
void visitIBDesignableAttr(IBDesignableAttr *attr);
183183
void visitIBInspectableAttr(IBInspectableAttr *attr);
@@ -246,6 +246,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
246246

247247
void visitImplementationOnlyAttr(ImplementationOnlyAttr *attr);
248248
void visitNonEphemeralAttr(NonEphemeralAttr *attr);
249+
void checkOriginalDefinedInAttrs(ArrayRef<OriginallyDefinedInAttr*> Attrs);
249250
};
250251
} // end anonymous namespace
251252

@@ -409,11 +410,6 @@ void AttributeChecker::visitIBActionAttr(IBActionAttr *attr) {
409410
validateIBActionSignature(Ctx, attr, FD, /*minParams=*/1, /*maxParams=*/1);
410411
}
411412

412-
void
413-
AttributeChecker::visitOriginallyDefinedInAttr(OriginallyDefinedInAttr *attr) {
414-
// TODO: implement diagnostics
415-
}
416-
417413
void AttributeChecker::visitIBSegueActionAttr(IBSegueActionAttr *attr) {
418414
// Only instance methods can be IBActions.
419415
const FuncDecl *FD = cast<FuncDecl>(D);
@@ -1017,14 +1013,21 @@ void AttributeChecker::visitOptionalAttr(OptionalAttr *attr) {
10171013

10181014
void TypeChecker::checkDeclAttributes(Decl *D) {
10191015
AttributeChecker Checker(D);
1016+
// We need to check all OriginallyDefinedInAttr relative to each other, so
1017+
// collect them and check in batch later.
1018+
llvm::SmallVector<OriginallyDefinedInAttr*, 4> ODIAttrs;
10201019
for (auto attr : D->getAttrs()) {
10211020
if (!attr->isValid()) continue;
10221021

10231022
// If Attr.def says that the attribute cannot appear on this kind of
10241023
// declaration, diagnose it and disable it.
10251024
if (attr->canAppearOnDecl(D)) {
1026-
// Otherwise, check it.
1027-
Checker.visit(attr);
1025+
if (auto *ODI = dyn_cast<OriginallyDefinedInAttr>(attr)) {
1026+
ODIAttrs.push_back(ODI);
1027+
} else {
1028+
// Otherwise, check it.
1029+
Checker.visit(attr);
1030+
}
10281031
continue;
10291032
}
10301033

@@ -1061,6 +1064,7 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
10611064
else
10621065
Checker.diagnoseAndRemoveAttr(attr, diag::invalid_decl_attribute, attr);
10631066
}
1067+
Checker.checkOriginalDefinedInAttrs(ODIAttrs);
10641068
}
10651069

10661070
/// Returns true if the given method is an valid implementation of a
@@ -2689,6 +2693,23 @@ void TypeChecker::checkParameterAttributes(ParameterList *params) {
26892693
}
26902694
}
26912695

2696+
void
2697+
AttributeChecker::checkOriginalDefinedInAttrs(
2698+
ArrayRef<OriginallyDefinedInAttr*> Attrs) {
2699+
llvm::SmallSet<PlatformKind, 4> AllPlatforms;
2700+
// Attrs are in the reverse order of the source order. We need to visit them
2701+
// in source order to diagnose the later attribute.
2702+
for (auto It = Attrs.rbegin(), End = Attrs.rend(); It != End; ++ It) {
2703+
auto *Attr = *It;
2704+
auto CurPlat = Attr->Platform;
2705+
if (!AllPlatforms.insert(CurPlat).second) {
2706+
// Only one version number is allowed for one platform name.
2707+
diagnose(Attr->AtLoc, diag::originally_defined_in_dupe_platform,
2708+
platformString(Attr->Platform));
2709+
}
2710+
}
2711+
}
2712+
26922713
Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
26932714
ReferenceOwnershipAttr *attr) {
26942715
auto &Diags = var->getASTContext().Diags;

test/Parse/original_defined_in_attr.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,11 @@ class ToplevelClass3 {}
2020

2121
@_originallyDefinedIn(module: "foo", * 13.13) // expected-warning {{* as platform name has no effect}} expected-error {{expected at least one platform version in @_originallyDefinedIn}}
2222
@_originallyDefinedIn(module: "foo", OSX 13.13, iOS 7.0)
23-
@_originallyDefinedIn(module: "foo", OSX 13.14, * 7.0) // expected-warning {{* as platform name has no effect}}
24-
class ToplevelClass4 {}
23+
@_originallyDefinedIn(module: "foo", OSX 13.14, * 7.0) // expected-warning {{* as platform name has no effect}} expected-error {{duplicate version number for platform OSX}}
24+
class ToplevelClass4 {
25+
@_originallyDefinedIn(module: "foo", OSX 13.13) // expected-error {{'@_originallyDefinedIn' attribute cannot be applied to this declaration}}
26+
subscript(index: Int) -> Int {
27+
get { return 1 }
28+
set(newValue) {}
29+
}
30+
}

0 commit comments

Comments
 (0)