@@ -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
@@ -1021,21 +1030,32 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1021
1030
// names. Complain and recover by chopping off everything
1022
1031
// after the first name.
1023
1032
if (objcName->getNumArgs () > 0 ) {
1024
- SourceLoc firstNameLoc = attr->getNameLocs ().front ();
1025
- SourceLoc afterFirstNameLoc =
1026
- Lexer::getLocForEndOfToken (Ctx.SourceMgr , firstNameLoc);
1033
+ SourceLoc firstNameLoc, afterFirstNameLoc;
1034
+ if (!attr->getNameLocs ().empty ()) {
1035
+ firstNameLoc = attr->getNameLocs ().front ();
1036
+ afterFirstNameLoc =
1037
+ Lexer::getLocForEndOfToken (Ctx.SourceMgr , firstNameLoc);
1038
+ }
1039
+ else {
1040
+ firstNameLoc = D->getLoc ();
1041
+ }
1027
1042
diagnose (firstNameLoc, diag::objc_name_req_nullary,
1028
1043
D->getDescriptiveKind ())
1029
- .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ());
1044
+ .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ())
1045
+ .limitBehavior (behavior);
1030
1046
const_cast <ObjCAttr *>(attr)->setName (
1031
1047
ObjCSelector (Ctx, 0 , objcName->getSelectorPieces ()[0 ]),
1032
1048
/* implicit=*/ false );
1033
1049
}
1034
1050
} else if (isa<SubscriptDecl>(D) || isa<DestructorDecl>(D)) {
1035
- diagnose (attr->getLParenLoc (),
1051
+ SourceLoc diagLoc = attr->getLParenLoc ();
1052
+ if (diagLoc.isInvalid ())
1053
+ diagLoc = D->getLoc ();
1054
+ diagnose (diagLoc,
1036
1055
isa<SubscriptDecl>(D)
1037
1056
? diag::objc_name_subscript
1038
- : diag::objc_name_deinit);
1057
+ : diag::objc_name_deinit)
1058
+ .limitBehavior (behavior);
1039
1059
const_cast <ObjCAttr *>(attr)->clearName ();
1040
1060
} else {
1041
1061
auto func = cast<AbstractFunctionDecl>(D);
@@ -1063,26 +1083,31 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
1063
1083
1064
1084
unsigned numArgumentNames = objcName->getNumArgs ();
1065
1085
if (numArgumentNames != numParameters) {
1066
- diagnose (attr->getNameLocs ().front (),
1086
+ SourceLoc firstNameLoc = func->getLoc ();
1087
+ if (!attr->getNameLocs ().empty ())
1088
+ firstNameLoc = attr->getNameLocs ().front ();
1089
+ diagnose (firstNameLoc,
1067
1090
diag::objc_name_func_mismatch,
1068
1091
isa<FuncDecl>(func),
1069
1092
numArgumentNames,
1070
1093
numArgumentNames != 1 ,
1071
1094
numParameters,
1072
1095
numParameters != 1 ,
1073
- func->hasThrows ());
1096
+ func->hasThrows ())
1097
+ .limitBehavior (behavior);
1074
1098
D->getAttrs ().add (
1075
1099
ObjCAttr::createUnnamed (Ctx, attr->AtLoc , attr->Range .Start ));
1076
1100
D->getAttrs ().removeAttribute (attr);
1077
1101
}
1078
1102
}
1079
1103
} else if (isa<EnumElementDecl>(D)) {
1080
1104
// Enum elements require names.
1081
- diagnoseAndRemoveAttr (attr, diag::objc_enum_case_req_name);
1105
+ diagnoseAndRemoveAttr (attr, diag::objc_enum_case_req_name)
1106
+ .limitBehavior (behavior);
1082
1107
}
1083
1108
1084
1109
// Diagnose an @objc attribute used without importing Foundation.
1085
- diagnoseObjCAttrWithoutFoundation (attr, D);
1110
+ diagnoseObjCAttrWithoutFoundation (attr, D, behavior );
1086
1111
}
1087
1112
1088
1113
void AttributeChecker::visitNonObjCAttr (NonObjCAttr *attr) {
@@ -1130,6 +1155,9 @@ void AttributeChecker::visitOptionalAttr(OptionalAttr *attr) {
1130
1155
}
1131
1156
1132
1157
void TypeChecker::checkDeclAttributes (Decl *D) {
1158
+ if (auto VD = dyn_cast<ValueDecl>(D))
1159
+ TypeChecker::applyAccessNote (VD);
1160
+
1133
1161
AttributeChecker Checker (D);
1134
1162
// We need to check all OriginallyDefinedInAttr relative to each other, so
1135
1163
// collect them and check in batch later.
@@ -1174,13 +1202,20 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
1174
1202
default : break ;
1175
1203
}
1176
1204
1205
+ DiagnosticBehavior behavior = attr->getAddedByAccessNote ()
1206
+ ? DiagnosticBehavior::Remark
1207
+ : DiagnosticBehavior::Unspecified;
1208
+
1177
1209
if (!OnlyKind.empty ())
1178
1210
Checker.diagnoseAndRemoveAttr (attr, diag::attr_only_one_decl_kind,
1179
- attr, OnlyKind);
1211
+ attr, OnlyKind)
1212
+ .limitBehavior (behavior);
1180
1213
else if (attr->isDeclModifier ())
1181
- Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_modifier, attr);
1214
+ Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_modifier, attr)
1215
+ .limitBehavior (behavior);
1182
1216
else
1183
- Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr);
1217
+ Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr)
1218
+ .limitBehavior (behavior);
1184
1219
}
1185
1220
Checker.checkOriginalDefinedInAttrs (D, ODIAttrs);
1186
1221
}
0 commit comments