Skip to content

Commit 481504d

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. Implement the new diagnostics for setter access control attributes Update the tests with the new diagnostics' messages Keep the original duplicate message if the access levels match Removing a DuplicateAttribute reassignment and improving the other
1 parent 7e9013d commit 481504d

File tree

4 files changed

+71
-32
lines changed

4 files changed

+71
-32
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", (StringRef))
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: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3063,9 +3063,26 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30633063
if (!Tok.is(tok::l_paren)) {
30643064
// Normal access control attribute.
30653065
AttrRange = Loc;
3066-
DuplicateAttribute = Attributes.getAttribute<AccessControlAttr>();
3067-
if (!DuplicateAttribute)
3066+
3067+
if (!DiscardAttribute) {
30683068
Attributes.add(new (Context) AccessControlAttr(AtLoc, Loc, access));
3069+
break;
3070+
}
3071+
3072+
// Diagnose if there's already an access control attribute on
3073+
// this declaration with a different access level.
3074+
if (access != cast<AccessControlAttr>(DuplicateAttribute)->getAccess()) {
3075+
diagnose(Loc, diag::multiple_access_level_modifiers)
3076+
.highlight(AttrRange);
3077+
diagnose(DuplicateAttribute->getLocation(),
3078+
diag::previous_access_level_modifier,
3079+
DuplicateAttribute->getAttrName())
3080+
.highlight(DuplicateAttribute->getRange());
3081+
3082+
// Remove the reference to the duplicate attribute
3083+
// to avoid the extra diagnostic.
3084+
DuplicateAttribute = nullptr;
3085+
}
30693086
break;
30703087
}
30713088

@@ -3095,11 +3112,29 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30953112
return makeParserSuccess();
30963113
}
30973114

3115+
// Check for duplicate setter access control attributes.
30983116
DuplicateAttribute = Attributes.getAttribute<SetterAccessAttr>();
3099-
if (!DuplicateAttribute) {
3117+
DiscardAttribute = DuplicateAttribute != nullptr;
3118+
3119+
if (!DiscardAttribute) {
31003120
Attributes.add(new (Context) SetterAccessAttr(AtLoc, AttrRange, access));
3121+
break;
3122+
}
3123+
3124+
// Diagnose if there's already a setter access control attribute on
3125+
// this declaration with a different access level.
3126+
if (access != cast<SetterAccessAttr>(DuplicateAttribute)->getAccess()) {
3127+
diagnose(Loc, diag::multiple_access_level_modifiers)
3128+
.highlight(AttrRange);
3129+
diagnose(DuplicateAttribute->getLocation(),
3130+
diag::previous_access_level_modifier,
3131+
DuplicateAttribute->getAttrName())
3132+
.highlight(DuplicateAttribute->getRange());
3133+
3134+
// Remove the reference to the duplicate attribute
3135+
// to avoid the extra diagnostic.
3136+
DuplicateAttribute = nullptr;
31013137
}
3102-
31033138
break;
31043139
}
31053140

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)