@@ -47,13 +47,16 @@ using namespace swift;
4747namespace {
4848 // / This emits a diagnostic with a fixit to remove the attribute.
4949 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+
5255 assert (!D->hasClangNode () && " Clang importer propagated a bogus attribute" );
5356 if (!D->hasClangNode ()) {
5457 SourceLoc loc = attr->getLocation ();
5558#ifndef NDEBUG
56- if (!loc.isValid ()) {
59+ if (!loc.isValid () && !attr-> getAddedByAccessNote () ) {
5760 llvm::errs () << " Attribute '" ;
5861 attr->print (llvm::errs ());
5962 llvm::errs () << " ' has invalid location, failed to diagnose!\n " ;
@@ -64,12 +67,11 @@ namespace {
6467 loc = D->getLoc ();
6568 }
6669 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 () ));
6972 }
7073 }
71-
72- attr->setInvalid ();
74+ return InFlightDiagnostic ();
7375 }
7476
7577// / This visits each attribute on a decl. The visitor should return true if
@@ -83,9 +85,10 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
8385
8486 // / This emits a diagnostic with a fixit to remove the attribute.
8587 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)...);
8992 }
9093
9194 template <typename ... ArgTypes>
@@ -936,7 +939,8 @@ static bool checkObjCDeclContext(Decl *D) {
936939 return false ;
937940}
938941
939- static void diagnoseObjCAttrWithoutFoundation (ObjCAttr *attr, Decl *decl) {
942+ static void diagnoseObjCAttrWithoutFoundation (ObjCAttr *attr, Decl *decl,
943+ DiagnosticBehavior behavior) {
940944 auto *SF = decl->getDeclContext ()->getParentSourceFile ();
941945 assert (SF);
942946
@@ -948,7 +952,8 @@ static void diagnoseObjCAttrWithoutFoundation(ObjCAttr *attr, Decl *decl) {
948952
949953 if (!ctx.LangOpts .EnableObjCInterop ) {
950954 ctx.Diags .diagnose (attr->getLocation (), diag::objc_interop_disabled)
951- .fixItRemove (attr->getRangeWithAt ());
955+ .fixItRemove (attr->getRangeWithAt ())
956+ .limitBehavior (behavior);
952957 return ;
953958 }
954959
@@ -968,10 +973,14 @@ static void diagnoseObjCAttrWithoutFoundation(ObjCAttr *attr, Decl *decl) {
968973 ctx.Diags .diagnose (attr->getLocation (),
969974 diag::attr_used_without_required_module, attr,
970975 ctx.Id_Foundation )
971- .highlight (attr->getRangeWithAt ());
976+ .highlight (attr->getRangeWithAt ())
977+ .limitBehavior (behavior);
972978}
973979
974980void AttributeChecker::visitObjCAttr (ObjCAttr *attr) {
981+ auto reason = objCReasonForObjCAttr (attr);
982+ auto behavior = behaviorLimitForObjCReason (reason, Ctx);
983+
975984 // Only certain decls can be ObjC.
976985 Optional<Diag<>> error;
977986 if (isa<ClassDecl>(D) ||
@@ -1007,7 +1016,7 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
10071016 }
10081017
10091018 if (error) {
1010- diagnoseAndRemoveAttr (attr, *error);
1019+ diagnoseAndRemoveAttr (attr, *error). limitBehavior (behavior) ;
10111020 return ;
10121021 }
10131022
@@ -1021,21 +1030,32 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
10211030 // names. Complain and recover by chopping off everything
10221031 // after the first name.
10231032 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+ }
10271042 diagnose (firstNameLoc, diag::objc_name_req_nullary,
10281043 D->getDescriptiveKind ())
1029- .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ());
1044+ .fixItRemoveChars (afterFirstNameLoc, attr->getRParenLoc ())
1045+ .limitBehavior (behavior);
10301046 const_cast <ObjCAttr *>(attr)->setName (
10311047 ObjCSelector (Ctx, 0 , objcName->getSelectorPieces ()[0 ]),
10321048 /* implicit=*/ false );
10331049 }
10341050 } 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,
10361055 isa<SubscriptDecl>(D)
10371056 ? diag::objc_name_subscript
1038- : diag::objc_name_deinit);
1057+ : diag::objc_name_deinit)
1058+ .limitBehavior (behavior);
10391059 const_cast <ObjCAttr *>(attr)->clearName ();
10401060 } else {
10411061 auto func = cast<AbstractFunctionDecl>(D);
@@ -1063,26 +1083,31 @@ void AttributeChecker::visitObjCAttr(ObjCAttr *attr) {
10631083
10641084 unsigned numArgumentNames = objcName->getNumArgs ();
10651085 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,
10671090 diag::objc_name_func_mismatch,
10681091 isa<FuncDecl>(func),
10691092 numArgumentNames,
10701093 numArgumentNames != 1 ,
10711094 numParameters,
10721095 numParameters != 1 ,
1073- func->hasThrows ());
1096+ func->hasThrows ())
1097+ .limitBehavior (behavior);
10741098 D->getAttrs ().add (
10751099 ObjCAttr::createUnnamed (Ctx, attr->AtLoc , attr->Range .Start ));
10761100 D->getAttrs ().removeAttribute (attr);
10771101 }
10781102 }
10791103 } else if (isa<EnumElementDecl>(D)) {
10801104 // 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);
10821107 }
10831108
10841109 // Diagnose an @objc attribute used without importing Foundation.
1085- diagnoseObjCAttrWithoutFoundation (attr, D);
1110+ diagnoseObjCAttrWithoutFoundation (attr, D, behavior );
10861111}
10871112
10881113void AttributeChecker::visitNonObjCAttr (NonObjCAttr *attr) {
@@ -1130,6 +1155,9 @@ void AttributeChecker::visitOptionalAttr(OptionalAttr *attr) {
11301155}
11311156
11321157void TypeChecker::checkDeclAttributes (Decl *D) {
1158+ if (auto VD = dyn_cast<ValueDecl>(D))
1159+ TypeChecker::applyAccessNote (VD);
1160+
11331161 AttributeChecker Checker (D);
11341162 // We need to check all OriginallyDefinedInAttr relative to each other, so
11351163 // collect them and check in batch later.
@@ -1174,13 +1202,20 @@ void TypeChecker::checkDeclAttributes(Decl *D) {
11741202 default : break ;
11751203 }
11761204
1205+ DiagnosticBehavior behavior = attr->getAddedByAccessNote ()
1206+ ? DiagnosticBehavior::Remark
1207+ : DiagnosticBehavior::Unspecified;
1208+
11771209 if (!OnlyKind.empty ())
11781210 Checker.diagnoseAndRemoveAttr (attr, diag::attr_only_one_decl_kind,
1179- attr, OnlyKind);
1211+ attr, OnlyKind)
1212+ .limitBehavior (behavior);
11801213 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);
11821216 else
1183- Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr);
1217+ Checker.diagnoseAndRemoveAttr (attr, diag::invalid_decl_attribute, attr)
1218+ .limitBehavior (behavior);
11841219 }
11851220 Checker.checkOriginalDefinedInAttrs (D, ODIAttrs);
11861221}
0 commit comments