Skip to content

Commit 3911542

Browse files
committed
Rephrase all access note remarks
• There is now one access note success remark and fix-it per declaration, not per attribute/modifier. • Failure remarks have been rephrased to better emphasize the cause of the failure. • The wording of other access note remarks and notes have been changed to follow a similar formula.
1 parent 5dc102b commit 3911542

File tree

7 files changed

+281
-242
lines changed

7 files changed

+281
-242
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5852,39 +5852,43 @@ ERROR(atomics_ordering_must_be_constant, none,
58525852
// MARK: access notes
58535853
//------------------------------------------------------------------------------
58545854

5855+
#define WHICH_ACCESS_NOTE(reason) "specified by access note for %" #reason
5856+
58555857
REMARK(attr_added_by_access_note, none,
5856-
"access note for %0 adds %select{attribute|modifier}1 '%2' to this %3",
5857-
(StringRef, bool, StringRef, DescriptiveDeclKind))
5858+
"implicitly added '%1' to this %2, as " WHICH_ACCESS_NOTE(0),
5859+
(StringRef, StringRef, DescriptiveDeclKind))
58585860
NOTE(fixit_attr_added_by_access_note, none,
5859-
"add %select{attribute|modifier}0 explicitly to silence this warning",
5860-
(bool))
5861+
"add '%0' explicitly to silence this warning",
5862+
(StringRef))
58615863

58625864
REMARK(attr_removed_by_access_note, none,
5863-
"access note for %0 removes %select{attribute|modifier}1 '%2' from "
5864-
"this %3",
5865-
(StringRef, bool, StringRef, DescriptiveDeclKind))
5865+
"implicitly removed '%1' from this %3, as " WHICH_ACCESS_NOTE(0),
5866+
(StringRef, StringRef, DescriptiveDeclKind))
58665867
NOTE(fixit_attr_removed_by_access_note, none,
5867-
"remove %select{attribute|modifier}0 explicitly to silence this warning",
5868-
(bool))
5868+
"remove '%0' explicitly to silence this warning",
5869+
(StringRef))
58695870

58705871
REMARK(attr_objc_name_changed_by_access_note, none,
5871-
"access note for %0 changes the '@objc' name of this %1 to %2",
5872-
(StringRef, DescriptiveDeclKind, ObjCSelector))
5872+
"implicitly changed Objective-C name of this %1 to %2, as "
5873+
WHICH_ACCESS_NOTE(0),
5874+
(StringRef, DescriptiveDeclKind, ObjCSelector))
58735875
NOTE(fixit_attr_objc_name_changed_by_access_note, none,
5874-
"change '@objc' name in source code explicitly to silence this warning",
5876+
"change Objective-C name explicitly to silence this warning",
58755877
())
58765878

58775879
// Bad access note diagnostics. These are usually emitted as remarks, but
58785880
// '-Raccess-note=all-validate' emits them as errors.
58795881

58805882
ERROR(attr_objc_name_conflicts_with_access_note, none,
5881-
"access note for %0 changes the '@objc' name of this %1 to %2, but "
5882-
"source code specifies %3; the access note will be ignored",
5883+
"ignored access note: did not change Objective-C name of this %1 from %2 "
5884+
"to %3, even though it was " WHICH_ACCESS_NOTE(0),
58835885
(StringRef, DescriptiveDeclKind, ObjCSelector, ObjCSelector))
58845886
ERROR(wrap_invalid_attr_added_by_access_note, none,
5885-
"access note for %1 failed to add invalid "
5886-
"%select{attribute|modifier}2 '%3': %0",
5887-
(DiagnosticInfo *, StringRef, bool, StringRef))
5887+
"ignored access note: %0; did not implicitly add '%2' to this %3, even "
5888+
"though it was " WHICH_ACCESS_NOTE(1),
5889+
(DiagnosticInfo *, StringRef, StringRef, DescriptiveDeclKind))
5890+
5891+
#undef WHICH_ACCESS_NOTE
58885892

58895893
#define UNDEFINE_DIAGNOSTIC_MACROS
58905894
#include "DefineDiagnosticMacros.h"

include/swift/AST/SourceFile.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,10 @@ class SourceFile final : public FileUnit {
246246
/// List of Objective-C member conflicts we have found during type checking.
247247
std::vector<ObjCMethodConflict> ObjCMethodConflicts;
248248

249-
using DeclAndAttr = std::tuple<ValueDecl *, DeclAttribute *>;
250-
251249
/// List of attributes added by access notes, used to emit remarks for valid
252250
/// ones.
253-
std::vector<DeclAndAttr> AttrsAddedByAccessNotes;
251+
llvm::DenseMap<ValueDecl *, std::vector<DeclAttribute *>>
252+
AttrsAddedByAccessNotes;
254253

255254
/// Describes what kind of file this is, which can affect some type checking
256255
/// and other behavior.

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 101 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,35 +1416,59 @@ void TypeChecker::diagnoseDuplicateCaptureVars(CaptureListExpr *expr) {
14161416
diagnoseDuplicateDecls(captureListVars);
14171417
}
14181418

1419-
template<typename ...DiagIDAndArgs> InFlightDiagnostic
1420-
diagnoseAtAttrOrDecl(DeclAttribute *attr, ValueDecl *VD,
1421-
DiagIDAndArgs... idAndArgs) {
1422-
ASTContext &ctx = VD->getASTContext();
1423-
if (attr->getLocation().isValid())
1424-
return ctx.Diags.diagnose(attr->getLocation(), idAndArgs...);
1425-
else
1426-
return ctx.Diags.diagnose(VD, idAndArgs...);
1419+
static StringRef prettyPrintAttrs(const ValueDecl *VD,
1420+
ArrayRef<const DeclAttribute *> attrs,
1421+
SmallVectorImpl<char> &out) {
1422+
llvm::raw_svector_ostream os(out);
1423+
StreamPrinter printer(os);
1424+
1425+
PrintOptions opts = PrintOptions::printEverything();
1426+
VD->getAttrs().print(printer, opts, attrs, VD);
1427+
return StringRef(out.begin(), out.size()).drop_back();
1428+
}
1429+
1430+
static void diagnoseChangesByAccessNote(
1431+
ValueDecl *VD,
1432+
ArrayRef<const DeclAttribute *> attrs,
1433+
Diag<StringRef, StringRef, DescriptiveDeclKind> diagID,
1434+
Diag<StringRef> fixItID,
1435+
llvm::function_ref<void(InFlightDiagnostic, StringRef)> addFixIts) {
1436+
if (!VD->getASTContext().LangOpts.shouldRemarkOnAccessNoteSuccess() ||
1437+
attrs.empty())
1438+
return;
1439+
1440+
// Generate string containing all attributes.
1441+
SmallString<64> attrString;
1442+
auto attrText = prettyPrintAttrs(VD, attrs, attrString);
1443+
1444+
SourceLoc fixItLoc;
1445+
1446+
auto reason = VD->getModuleContext()->getAccessNotes().Reason;
1447+
auto diag = VD->diagnose(diagID, reason, attrText, VD->getDescriptiveKind());
1448+
for (auto attr : attrs) {
1449+
diag.highlight(attr->getRangeWithAt());
1450+
if (fixItLoc.isInvalid())
1451+
fixItLoc = attr->getRangeWithAt().Start;
1452+
}
1453+
diag.flush();
1454+
1455+
if (!fixItLoc)
1456+
fixItLoc = VD->getAttributeInsertionLoc(true);
1457+
1458+
addFixIts(VD->getASTContext().Diags.diagnose(fixItLoc, fixItID, attrText),
1459+
attrString);
14271460
}
14281461

14291462
template <typename Attr>
14301463
static void addOrRemoveAttr(ValueDecl *VD, const AccessNotesFile &notes,
14311464
Optional<bool> expected,
1465+
SmallVectorImpl<DeclAttribute *> &removedAttrs,
14321466
llvm::function_ref<Attr*()> willCreate) {
14331467
if (!expected) return;
14341468

14351469
auto attr = VD->getAttrs().getAttribute<Attr>();
14361470
if (*expected == (attr != nullptr)) return;
14371471

1438-
auto diagnoseChangeByAccessNote =
1439-
[&](Diag<StringRef, bool, StringRef, DescriptiveDeclKind> diagID,
1440-
Diag<bool> fixitID) -> InFlightDiagnostic {
1441-
bool isModifier = attr->isDeclModifier();
1442-
1443-
diagnoseAtAttrOrDecl(attr, VD, diagID, notes.Reason, isModifier,
1444-
attr->getAttrName(), VD->getDescriptiveKind());
1445-
return diagnoseAtAttrOrDecl(attr, VD, fixitID, isModifier);
1446-
};
1447-
14481472
if (*expected) {
14491473
attr = willCreate();
14501474
attr->setAddedByAccessNote();
@@ -1453,77 +1477,80 @@ static void addOrRemoveAttr(ValueDecl *VD, const AccessNotesFile &notes,
14531477
// Arrange for us to emit a remark about this attribute after type checking
14541478
// has ensured it's valid.
14551479
if (auto SF = VD->getDeclContext()->getParentSourceFile())
1456-
SF->AttrsAddedByAccessNotes.emplace_back(VD, attr);
1480+
SF->AttrsAddedByAccessNotes[VD].push_back(attr);
14571481
} else {
1482+
removedAttrs.push_back(attr);
14581483
VD->getAttrs().removeAttribute(attr);
1459-
if (VD->getASTContext().LangOpts.shouldRemarkOnAccessNoteSuccess())
1460-
diagnoseChangeByAccessNote(diag::attr_removed_by_access_note,
1461-
diag::fixit_attr_removed_by_access_note)
1462-
.fixItRemove(attr->getRangeWithAt());
14631484
}
14641485
}
14651486

14661487
InFlightDiagnostic
14671488
swift::softenIfAccessNote(const Decl *D, const DeclAttribute *attr,
14681489
InFlightDiagnostic &diag) {
1469-
if (!attr || !attr->getAddedByAccessNote())
1490+
const ValueDecl *VD = dyn_cast<ValueDecl>(D);
1491+
if (!VD || !attr || !attr->getAddedByAccessNote())
14701492
return std::move(diag);
14711493

1472-
auto behavior = D->getASTContext().LangOpts.getAccessNoteFailureLimit();
1494+
SmallString<32> attrString;
1495+
auto attrText = prettyPrintAttrs(VD, makeArrayRef(attr), attrString);
1496+
1497+
ASTContext &ctx = D->getASTContext();
1498+
auto behavior = ctx.LangOpts.getAccessNoteFailureLimit();
14731499
return std::move(diag.wrapIn(diag::wrap_invalid_attr_added_by_access_note,
14741500
D->getModuleContext()->getAccessNotes().Reason,
1475-
attr->isDeclModifier(), attr->getAttrName())
1501+
ctx.AllocateCopy(attrText), D->getDescriptiveKind())
14761502
.limitBehavior(behavior));
14771503
}
14781504

14791505
static void applyAccessNote(ValueDecl *VD, const AccessNote &note,
14801506
const AccessNotesFile &notes) {
14811507
ASTContext &ctx = VD->getASTContext();
1508+
SmallVector<DeclAttribute *, 2> removedAttrs;
14821509

1483-
addOrRemoveAttr<ObjCAttr>(VD, notes, note.ObjC, [&]{
1510+
addOrRemoveAttr<ObjCAttr>(VD, notes, note.ObjC, removedAttrs, [&]{
14841511
return ObjCAttr::create(ctx, note.ObjCName, false);
14851512
});
14861513

1487-
addOrRemoveAttr<DynamicAttr>(VD, notes, note.Dynamic, [&]{
1514+
addOrRemoveAttr<DynamicAttr>(VD, notes, note.Dynamic, removedAttrs, [&]{
14881515
return new (ctx) DynamicAttr(true);
14891516
});
14901517

1518+
// FIXME: If we ever have more attributes, we'll need to sort removedAttrs by
1519+
// SourceLoc. As it is, attrs are always before modifiers, so we're okay now.
1520+
1521+
diagnoseChangesByAccessNote(VD, removedAttrs,
1522+
diag::attr_removed_by_access_note,
1523+
diag::fixit_attr_removed_by_access_note,
1524+
[&](InFlightDiagnostic diag, StringRef code) {
1525+
for (auto attr : llvm::reverse(removedAttrs))
1526+
diag.fixItRemove(attr->getRangeWithAt());
1527+
});
1528+
14911529
if (note.ObjCName) {
14921530
auto attr = VD->getAttrs().getAttribute<ObjCAttr>();
14931531
assert(attr && "ObjCName set, but ObjCAttr not true or did not apply???");
14941532

14951533
if (!attr->hasName()) {
1534+
auto oldName = attr->getName();
14961535
attr->setName(*note.ObjCName, true);
14971536

14981537
if (!ctx.LangOpts.shouldRemarkOnAccessNoteSuccess())
14991538
return;
15001539

1501-
diagnoseAtAttrOrDecl(attr, VD,
1502-
diag::attr_objc_name_changed_by_access_note,
1503-
notes.Reason, VD->getDescriptiveKind(),
1504-
*note.ObjCName);
1505-
1506-
SmallString<64> newNameString;
1507-
llvm::raw_svector_ostream os(newNameString);
1508-
os << "(";
1509-
os << *note.ObjCName;
1510-
os << ")";
1511-
1512-
auto note = diagnoseAtAttrOrDecl(attr, VD,
1513-
diag::fixit_attr_objc_name_changed_by_access_note);
1540+
VD->diagnose(diag::attr_objc_name_changed_by_access_note,
1541+
notes.Reason, VD->getDescriptiveKind(), *note.ObjCName);
15141542

1515-
if (attr->getLParenLoc().isValid())
1516-
note.fixItReplace({ attr->getLParenLoc(), attr->getRParenLoc() },
1517-
newNameString);
1518-
else
1519-
note.fixItInsertAfter(attr->getLocation(), newNameString);
1543+
auto fixIt =
1544+
VD->diagnose(diag::fixit_attr_objc_name_changed_by_access_note);
1545+
fixDeclarationObjCName(fixIt, VD, oldName, *note.ObjCName);
15201546
}
15211547
else if (attr->getName() != *note.ObjCName) {
15221548
auto behavior = ctx.LangOpts.getAccessNoteFailureLimit();
1523-
diagnoseAtAttrOrDecl(attr, VD,
1524-
diag::attr_objc_name_conflicts_with_access_note,
1525-
notes.Reason, VD->getDescriptiveKind(),
1526-
*note.ObjCName, *attr->getName())
1549+
1550+
VD->diagnose(diag::attr_objc_name_conflicts_with_access_note,
1551+
notes.Reason, VD->getDescriptiveKind(), *attr->getName(),
1552+
*note.ObjCName)
1553+
.highlight(attr->getRangeWithAt())
15271554
.limitBehavior(behavior);
15281555
}
15291556
}
@@ -1538,24 +1565,31 @@ void swift::diagnoseAttrsAddedByAccessNote(SourceFile &SF) {
15381565
if (!SF.getASTContext().LangOpts.shouldRemarkOnAccessNoteSuccess())
15391566
return;
15401567

1541-
for (auto declAndAttr : SF.AttrsAddedByAccessNotes) {
1542-
auto VD = std::get<0>(declAndAttr);
1543-
auto attr = std::get<1>(declAndAttr);
1544-
1545-
if (attr->isInvalid()) continue;
1546-
assert(attr->getAddedByAccessNote());
1547-
1548-
bool isModifier = attr->isDeclModifier();
1549-
1550-
auto reason = VD->getModuleContext()->getAccessNotes().Reason;
1551-
VD->diagnose(diag::attr_added_by_access_note, reason, isModifier,
1552-
attr->getAttrName(), VD->getDescriptiveKind());
1568+
for (auto declAndAttrs : SF.AttrsAddedByAccessNotes) {
1569+
auto D = declAndAttrs.getFirst();
1570+
SmallVector<DeclAttribute *, 4> sortedAttrs;
1571+
llvm::append_range(sortedAttrs, declAndAttrs.getSecond());
1572+
1573+
// Filter out invalid attributes.
1574+
sortedAttrs.erase(
1575+
llvm::remove_if(sortedAttrs, [](DeclAttribute *attr) {
1576+
assert(attr->getAddedByAccessNote());
1577+
return attr->isInvalid();
1578+
}), sortedAttrs.end());
1579+
if (sortedAttrs.empty()) continue;
1580+
1581+
// Sort attributes by name.
1582+
llvm::sort(sortedAttrs, [](DeclAttribute * first, DeclAttribute * second) {
1583+
return first->getAttrName() < second->getAttrName();
1584+
});
1585+
sortedAttrs.erase(std::unique(sortedAttrs.begin(), sortedAttrs.end()),
1586+
sortedAttrs.end());
15531587

1554-
SmallString<64> attrString;
1555-
llvm::raw_svector_ostream os(attrString);
1556-
attr->print(os, VD);
1557-
VD->diagnose(diag::fixit_attr_added_by_access_note, isModifier)
1558-
.fixItInsert(VD->getAttributeInsertionLoc(isModifier), attrString);
1588+
diagnoseChangesByAccessNote(D, sortedAttrs, diag::attr_added_by_access_note,
1589+
diag::fixit_attr_added_by_access_note,
1590+
[=](InFlightDiagnostic diag, StringRef code) {
1591+
diag.fixItInsert(D->getAttributeInsertionLoc(/*isModifier=*/true), code);
1592+
});
15591593
}
15601594
}
15611595

0 commit comments

Comments
 (0)