@@ -47,13 +47,16 @@ using namespace swift;
47
47
namespace {
48
48
// / This emits a diagnostic with a fixit to remove the attribute.
49
49
template <typename ...ArgTypes>
50
- void diagnoseAndRemoveAttr (DiagnosticEngine &Diags, Decl *D,
51
- DeclAttribute *attr, ArgTypes &&...Args) {
50
+ InFlightDiagnostic
51
+ diagnoseAndRemoveAttr (DiagnosticEngine &Diags, Decl *D, DeclAttribute *attr,
52
+ ArgTypes &&...Args) {
53
+ attr->setInvalid ();
54
+
52
55
assert (!D->hasClangNode () && " Clang importer propagated a bogus attribute" );
53
56
if (!D->hasClangNode ()) {
54
57
SourceLoc loc = attr->getLocation ();
55
58
#ifndef NDEBUG
56
- if (!loc.isValid ()) {
59
+ if (!loc.isValid () && !attr-> getAddedByAccessNote () ) {
57
60
llvm::errs () << " Attribute '" ;
58
61
attr->print (llvm::errs ());
59
62
llvm::errs () << " ' has invalid location, failed to diagnose!\n " ;
@@ -64,12 +67,11 @@ namespace {
64
67
loc = D->getLoc ();
65
68
}
66
69
if (loc.isValid ()) {
67
- Diags.diagnose (loc, std::forward<ArgTypes>(Args)...)
68
- .fixItRemove (attr->getRangeWithAt ());
70
+ return std::move ( Diags.diagnose (loc, std::forward<ArgTypes>(Args)...)
71
+ .fixItRemove (attr->getRangeWithAt () ));
69
72
}
70
73
}
71
-
72
- attr->setInvalid ();
74
+ return InFlightDiagnostic ();
73
75
}
74
76
75
77
// / This visits each attribute on a decl. The visitor should return true if
@@ -83,9 +85,10 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
83
85
84
86
// / This emits a diagnostic with a fixit to remove the attribute.
85
87
template <typename ...ArgTypes>
86
- void diagnoseAndRemoveAttr (DeclAttribute *attr, ArgTypes &&...Args) {
87
- ::diagnoseAndRemoveAttr (Ctx.Diags, D, attr,
88
- std::forward<ArgTypes>(Args)...);
88
+ InFlightDiagnostic diagnoseAndRemoveAttr (DeclAttribute *attr,
89
+ ArgTypes &&...Args) {
90
+ return ::diagnoseAndRemoveAttr (Ctx.Diags , D, attr,
91
+ std::forward<ArgTypes>(Args)...);
89
92
}
90
93
91
94
template <typename ... ArgTypes>
@@ -936,7 +939,8 @@ static bool checkObjCDeclContext(Decl *D) {
936
939
return false ;
937
940
}
938
941
939
- static void diagnoseObjCAttrWithoutFoundation (ObjCAttr *attr, Decl *decl) {
942
+ static void diagnoseObjCAttrWithoutFoundation (ObjCAttr *attr, Decl *decl,
943
+ DiagnosticBehavior behavior) {
940
944
auto *SF = decl->getDeclContext ()->getParentSourceFile ();
941
945
assert (SF);
942
946
@@ -948,7 +952,8 @@ static void diagnoseObjCAttrWithoutFoundation(ObjCAttr *attr, Decl *decl) {
948
952
949
953
if (!ctx.LangOpts .EnableObjCInterop ) {
950
954
ctx.Diags .diagnose (attr->getLocation (), diag::objc_interop_disabled)
951
- .fixItRemove (attr->getRangeWithAt ());
955
+ .fixItRemove (attr->getRangeWithAt ())
956
+ .limitBehavior (behavior);
952
957
return ;
953
958
}
954
959
@@ -968,10 +973,14 @@ static void diagnoseObjCAttrWithoutFoundation(ObjCAttr *attr, Decl *decl) {
968
973
ctx.Diags .diagnose (attr->getLocation (),
969
974
diag::attr_used_without_required_module, attr,
970
975
ctx.Id_Foundation )
971
- .highlight (attr->getRangeWithAt ());
976
+ .highlight (attr->getRangeWithAt ())
977
+ .limitBehavior (behavior);
972
978
}
973
979
974
980
void AttributeChecker::visitObjCAttr (ObjCAttr *attr) {
981
+ auto reason = objCReasonForObjCAttr (attr);
982
+ auto behavior = behaviorLimitForObjCReason (reason, Ctx);
983
+
975
984
// Only certain decls can be ObjC.
976
985
Optional<Diag<>> error;
977
986
if (isa<ClassDecl>(D) ||
@@ -1007,7 +1016,7 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1007
1016
}
1008
1017
1009
1018
if (error) {
1010
- diagnoseAndRemoveAttr (attr, *error);
1019
+ diagnoseAndRemoveAttr (attr, *error). limitBehavior (behavior) ;
1011
1020
return ;
1012
1021
}
1013
1022
@@ -1026,7 +1035,8 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1026
1035
Lexer::getLocForEndOfToken (Ctx.SourceMgr , firstNameLoc);
1027
1036
diagnose (firstNameLoc, diag::objc_name_req_nullary,
1028
1037
D->getDescriptiveKind ())
1029
- .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ());
1038
+ .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ())
1039
+ .limitBehavior (behavior);
1030
1040
const_cast <ObjCAttr *>(attr)->setName (
1031
1041
ObjCSelector (Ctx, 0 , objcName->getSelectorPieces ()[0 ]),
1032
1042
/* implicit=*/ false );
@@ -1035,7 +1045,8 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1035
1045
diagnose (attr->getLParenLoc (),
1036
1046
isa<SubscriptDecl>(D)
1037
1047
? diag::objc_name_subscript
1038
- : diag::objc_name_deinit);
1048
+ : diag::objc_name_deinit)
1049
+ .limitBehavior (behavior);
1039
1050
const_cast <ObjCAttr *>(attr)->clearName ();
1040
1051
} else {
1041
1052
auto func = cast<AbstractFunctionDecl>(D);
@@ -1070,19 +1081,21 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1070
1081
numArgumentNames != 1 ,
1071
1082
numParameters,
1072
1083
numParameters != 1 ,
1073
- func->hasThrows ());
1084
+ func->hasThrows ())
1085
+ .limitBehavior (behavior);
1074
1086
D->getAttrs ().add (
1075
1087
ObjCAttr::createUnnamed (Ctx, attr->AtLoc , attr->Range .Start ));
1076
1088
D->getAttrs ().removeAttribute (attr);
1077
1089
}
1078
1090
}
1079
1091
} else if (isa<EnumElementDecl>(D)) {
1080
1092
// Enum elements require names.
1081
- diagnoseAndRemoveAttr (attr, diag::objc_enum_case_req_name);
1093
+ diagnoseAndRemoveAttr (attr, diag::objc_enum_case_req_name)
1094
+ .limitBehavior (behavior);
1082
1095
}
1083
1096
1084
1097
// Diagnose an @objc attribute used without importing Foundation.
1085
- diagnoseObjCAttrWithoutFoundation (attr, D);
1098
+ diagnoseObjCAttrWithoutFoundation (attr, D, behavior );
1086
1099
}
1087
1100
1088
1101
void AttributeChecker::visitNonObjCAttr (NonObjCAttr *attr) {
@@ -1132,7 +1145,7 @@ void AttributeChecker::visitOptionalAttr(OptionalAttr *attr) {
1132
1145
void TypeChecker::checkDeclAttributes (Decl *D) {
1133
1146
if (auto VD = dyn_cast<ValueDecl>(D))
1134
1147
TypeChecker::applyAccessNote (VD);
1135
-
1148
+
1136
1149
AttributeChecker Checker (D);
1137
1150
// We need to check all OriginallyDefinedInAttr relative to each other, so
1138
1151
// collect them and check in batch later.
@@ -1177,13 +1190,20 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
1177
1190
default : break ;
1178
1191
}
1179
1192
1193
+ DiagnosticBehavior behavior = attr->getAddedByAccessNote ()
1194
+ ? DiagnosticBehavior::Remark
1195
+ : DiagnosticBehavior::Unspecified;
1196
+
1180
1197
if (!OnlyKind.empty ())
1181
1198
Checker.diagnoseAndRemoveAttr (attr, diag::attr_only_one_decl_kind,
1182
- attr, OnlyKind);
1199
+ attr, OnlyKind)
1200
+ .limitBehavior (behavior);
1183
1201
else if (attr->isDeclModifier ())
1184
- Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_modifier, attr);
1202
+ Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_modifier, attr)
1203
+ .limitBehavior (behavior);
1185
1204
else
1186
- Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr);
1205
+ Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr)
1206
+ .limitBehavior (behavior);
1187
1207
}
1188
1208
Checker.checkOriginalDefinedInAttrs (D, ODIAttrs);
1189
1209
}
0 commit comments