Skip to content

Commit 86e1a1e

Browse files
committed
[Parser] Improve diagnostics for access-level modifiers
Improve the diagnostics for situations where multiple access-level modifiers are used on the same declaration.
1 parent 50a98d3 commit 86e1a1e

File tree

4 files changed

+68
-31
lines changed

4 files changed

+68
-31
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,10 @@ ERROR(duplicate_attribute,none,
14851485
"duplicate %select{attribute|modifier}0", (bool))
14861486
NOTE(previous_attribute,none,
14871487
"%select{attribute|modifier}0 already specified here", (bool))
1488+
ERROR(multiple_access_level_modifiers,none,
1489+
"multiple incompatible access-level modifiers specified", ())
1490+
NOTE(previous_access_level_modifier,none,
1491+
"previous modifier specified here", ())
14881492
ERROR(mutually_exclusive_attrs,none,
14891493
"'%0' contradicts previous %select{attribute|modifier}2 '%1'", (StringRef, StringRef, bool))
14901494

lib/Parse/ParseDecl.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3093,9 +3093,25 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30933093
if (!Tok.is(tok::l_paren)) {
30943094
// Normal access control attribute.
30953095
AttrRange = Loc;
3096-
DuplicateAttribute = Attributes.getAttribute<AccessControlAttr>();
3097-
if (!DuplicateAttribute)
3096+
3097+
if (!DiscardAttribute) {
30983098
Attributes.add(new (Context) AccessControlAttr(AtLoc, Loc, access));
3099+
break;
3100+
}
3101+
3102+
// Diagnose if there's already an access control attribute on
3103+
// this declaration with a different access level.
3104+
if (access != cast<AccessControlAttr>(DuplicateAttribute)->getAccess()) {
3105+
diagnose(Loc, diag::multiple_access_level_modifiers)
3106+
.highlight(AttrRange);
3107+
diagnose(DuplicateAttribute->getLocation(),
3108+
diag::previous_access_level_modifier)
3109+
.highlight(DuplicateAttribute->getRange());
3110+
3111+
// Remove the reference to the duplicate attribute
3112+
// to avoid the extra diagnostic.
3113+
DuplicateAttribute = nullptr;
3114+
}
30993115
break;
31003116
}
31013117

@@ -3125,11 +3141,28 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
31253141
return makeParserSuccess();
31263142
}
31273143

3144+
// Check for duplicate setter access control attributes.
31283145
DuplicateAttribute = Attributes.getAttribute<SetterAccessAttr>();
3129-
if (!DuplicateAttribute) {
3146+
DiscardAttribute = DuplicateAttribute != nullptr;
3147+
3148+
if (!DiscardAttribute) {
31303149
Attributes.add(new (Context) SetterAccessAttr(AtLoc, AttrRange, access));
3150+
break;
31313151
}
31323152

3153+
// Diagnose if there's already a setter access control attribute on
3154+
// this declaration with a different access level.
3155+
if (access != cast<SetterAccessAttr>(DuplicateAttribute)->getAccess()) {
3156+
diagnose(Loc, diag::multiple_access_level_modifiers)
3157+
.highlight(AttrRange);
3158+
diagnose(DuplicateAttribute->getLocation(),
3159+
diag::previous_access_level_modifier)
3160+
.highlight(DuplicateAttribute->getRange());
3161+
3162+
// Remove the reference to the duplicate attribute
3163+
// to avoid the extra diagnostic.
3164+
DuplicateAttribute = nullptr;
3165+
}
31333166
break;
31343167
}
31353168

test/attr/accessibility.swift

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ private // expected-note {{modifier already specified here}}
55
private // expected-error {{duplicate modifier}}
66
func duplicateAttr() {}
77

8-
private // expected-note {{modifier already specified here}}
9-
public // expected-error {{duplicate modifier}}
8+
private // expected-note {{previous modifier specified here}}
9+
public // expected-error {{multiple incompatible access-level modifiers specified}}
1010
func duplicateAttrChanged() {}
1111

12-
private // expected-note 2 {{modifier already specified here}}
13-
public // expected-error {{duplicate modifier}}
14-
internal // expected-error {{duplicate modifier}}
12+
private // expected-note 2 {{previous modifier specified here}}
13+
public // expected-error {{multiple incompatible access-level modifiers specified}}
14+
internal // expected-error {{multiple incompatible access-level modifiers specified}}
1515
func triplicateAttrChanged() {}
1616

17-
private // expected-note 3 {{modifier already specified here}}
18-
public // expected-error {{duplicate modifier}}
19-
package // expected-error {{duplicate modifier}}
20-
internal // expected-error {{duplicate modifier}}
17+
private // expected-note 3 {{previous modifier specified here}}
18+
public // expected-error {{multiple incompatible access-level modifiers specified}}
19+
package // expected-error {{multiple incompatible access-level modifiers specified}}
20+
internal // expected-error {{multiple incompatible access-level modifiers specified}}
2121
func quadruplicateAttrChanged() {}
2222

23-
private // expected-note 4 {{modifier already specified here}}
24-
public // expected-error {{duplicate modifier}}
25-
package // expected-error {{duplicate modifier}}
26-
internal // expected-error {{duplicate modifier}}
27-
fileprivate // expected-error {{duplicate modifier}}
23+
private // expected-note 4 {{previous modifier specified here}}
24+
public // expected-error {{multiple incompatible access-level modifiers specified}}
25+
package // expected-error {{multiple incompatible access-level modifiers specified}}
26+
internal // expected-error {{multiple incompatible access-level modifiers specified}}
27+
fileprivate // expected-error {{multiple incompatible access-level modifiers specified}}
2828
func quintuplicateAttrChanged() {}
2929

3030
private(set)
@@ -51,22 +51,22 @@ internal(set)
5151
package
5252
var customSetter6 = 0
5353

54-
private(set) // expected-note {{modifier already specified here}}
55-
public(set) // expected-error {{duplicate modifier}}
54+
private(set) // expected-note {{previous modifier specified here}}
55+
public(set) // expected-error {{multiple incompatible access-level modifiers specified}}
5656
var customSetterDuplicateAttr = 0
5757

58-
private(set) // expected-note {{modifier already specified here}}
59-
public // expected-note {{modifier already specified here}}
60-
public(set) // expected-error {{duplicate modifier}}
61-
private // expected-error {{duplicate modifier}}
58+
private(set) // expected-note {{previous modifier specified here}}
59+
public // expected-note {{previous modifier specified here}}
60+
public(set) // expected-error {{multiple incompatible access-level modifiers specified}}
61+
private // expected-error {{multiple incompatible access-level modifiers specified}}
6262
var customSetterDuplicateAttrsAllAround = 0
6363

64-
private(set) // expected-note {{modifier already specified here}}
65-
package(set) // expected-error {{duplicate modifier}}
64+
private(set) // expected-note {{previous modifier specified here}}
65+
package(set) // expected-error {{multiple incompatible access-level modifiers specified}}
6666
var customSetterDuplicateAttr2 = 0
6767

68-
package(set) // expected-note {{modifier already specified here}}
69-
public(set) // expected-error {{duplicate modifier}}
68+
package(set) // expected-note {{previous modifier specified here}}
69+
public(set) // expected-error {{multiple incompatible access-level modifiers specified}}
7070
public var customSetterDuplicateAttr3 = 0
7171

7272
private(get) // expected-error{{expected 'set' as subject of 'private' modifier}}

test/attr/open.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import OpenHelpers
66

77
/**** General structural limitations on open. ****/
88

9-
open private class OpenIsNotCompatibleWithPrivate {} // expected-error {{duplicate modifier}} expected-note{{modifier already specified here}}
10-
open fileprivate class OpenIsNotCompatibleWithFilePrivate {} // expected-error {{duplicate modifier}} expected-note{{modifier already specified here}}
11-
open internal class OpenIsNotCompatibleWithInternal {} // expected-error {{duplicate modifier}} expected-note{{modifier already specified here}}
12-
open public class OpenIsNotCompatibleWithPublic {} // expected-error {{duplicate modifier}} expected-note{{modifier already specified here}}
9+
open private class OpenIsNotCompatibleWithPrivate {} // expected-error {{multiple incompatible access-level modifiers specified}} expected-note{{previous modifier specified here}}
10+
open fileprivate class OpenIsNotCompatibleWithFilePrivate {} // expected-error {{multiple incompatible access-level modifiers specified}} expected-note{{previous modifier specified here}}
11+
open internal class OpenIsNotCompatibleWithInternal {} // expected-error {{multiple incompatible access-level modifiers specified}} expected-note{{previous modifier specified here}}
12+
open public class OpenIsNotCompatibleWithPublic {} // expected-error {{multiple incompatible access-level modifiers specified}} expected-note{{previous modifier specified here}}
1313
open open class OpenIsNotCompatibleWithOpen {} // expected-error {{duplicate modifier}} expected-note{{modifier already specified here}}
1414

1515
open typealias OpenIsNotAllowedOnTypeAliases = Int // expected-error {{only classes and overridable class members can be declared 'open'; use 'public'}}

0 commit comments

Comments
 (0)