Skip to content

Commit 78a420d

Browse files
tanadeaujrose-apple
authored andcommitted
Made use of @warn_unused_result a warning with a fixit (#2760)
https://bugs.swift.org/browse/SR-1052
1 parent e62d939 commit 78a420d

16 files changed

+47
-295
lines changed

include/swift/AST/Attr.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ DECL_ATTR(_alignment, Alignment, OnStruct | OnEnum | UserInaccessible, 56)
233233
SIMPLE_DECL_ATTR(rethrows, Rethrows,
234234
OnFunc | OnConstructor | RejectByParser, 57)
235235

236-
DECL_ATTR(warn_unused_result, WarnUnusedResult,
237-
OnFunc | OnConstructor | LongAttribute, 58)
238-
239236
DECL_ATTR(_swift_native_objc_runtime_base, SwiftNativeObjCRuntimeBase,
240237
OnClass | UserInaccessible, 59)
241238

include/swift/AST/Attr.h

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,59 +1079,6 @@ class SynthesizedProtocolAttr : public DeclAttribute {
10791079
}
10801080
};
10811081

1082-
/// The @warn_unused_result attribute, which specifies that we should
1083-
/// receive a warning if a function is called but its result is
1084-
/// unused.
1085-
///
1086-
/// The @warn_unused_result attribute can optionally be provided with
1087-
/// a message and a mutable variant. For example:
1088-
///
1089-
/// \code
1090-
/// struct X {
1091-
/// @warn_unused_result(message: "this string affects your health")
1092-
/// func methodA() -> String { ... }
1093-
///
1094-
/// @warn_unused_result(mutable_variant: "jumpInPlace")
1095-
/// func jump() -> X { ... }
1096-
///
1097-
/// mutating func jumpInPlace() { ... }
1098-
/// }
1099-
/// \endcode
1100-
class WarnUnusedResultAttr : public DeclAttribute {
1101-
/// The optional message.
1102-
const StringRef Message;
1103-
1104-
/// An optional name of the mutable variant of the given method,
1105-
/// which will be suggested as a replacement if it can be called.
1106-
const StringRef MutableVariant;
1107-
1108-
public:
1109-
/// A @warn_unused_result attribute with no options.
1110-
WarnUnusedResultAttr(SourceLoc atLoc, SourceLoc attrLoc, bool implicit)
1111-
: DeclAttribute(DAK_WarnUnusedResult, atLoc, SourceRange(atLoc, attrLoc),
1112-
implicit),
1113-
Message(""), MutableVariant("") { }
1114-
1115-
/// A @warn_unused_result attribute with a message or mutable variant.
1116-
WarnUnusedResultAttr(SourceLoc atLoc, SourceLoc attrLoc, SourceLoc lParenLoc,
1117-
StringRef message, StringRef mutableVariant,
1118-
SourceLoc rParenLoc, bool implicit)
1119-
: DeclAttribute(DAK_WarnUnusedResult, attrLoc,
1120-
SourceRange(atLoc, rParenLoc),
1121-
implicit),
1122-
Message(message), MutableVariant(mutableVariant) { }
1123-
1124-
/// Retrieve the message associated with this attribute.
1125-
StringRef getMessage() const { return Message; }
1126-
1127-
/// Retrieve the name of the mutable variant of this method.
1128-
StringRef getMutableVariant() const { return MutableVariant; }
1129-
1130-
static bool classof(const DeclAttribute *DA) {
1131-
return DA->getKind() == DAK_WarnUnusedResult;
1132-
}
1133-
};
1134-
11351082
/// The @swift3_migration attribute which describes the transformations
11361083
/// required to migrate the given Swift 2.x API to Swift 3.
11371084
class Swift3MigrationAttr : public DeclAttribute {

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,16 +1258,8 @@ ERROR(attr_unowned_expected_rparen,none,
12581258
"expected ')' after specifier for 'unowned'", ())
12591259

12601260
// warn_unused_result
1261-
WARNING(attr_warn_unused_result_expected_name,none,
1262-
"expected parameter 'message' or 'mutable_variant'", ())
1263-
WARNING(attr_warn_unused_result_duplicate_parameter,none,
1264-
"duplicate '%0' parameter; previous value will be ignored", (StringRef))
1265-
ERROR(attr_warn_unused_result_expected_colon,none,
1266-
"expected ':' following '%0' parameter", (StringRef))
1267-
ERROR(attr_warn_unused_result_expected_string,none,
1268-
"expected a string following ':' for '%0' parameter", (StringRef))
1269-
WARNING(attr_warn_unused_result_unknown_parameter,none,
1270-
"unknown parameter '%0' in 'warn_unused_result' attribute", (StringRef))
1261+
WARNING(attr_warn_unused_result_removed,none,
1262+
"'warn_unused_result' attribute behavior is now the default", ())
12711263
ERROR(attr_warn_unused_result_expected_rparen,none,
12721264
"expected ')' after 'warn_unused_result' attribute", ())
12731265

include/swift/AST/PrintOptions.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ struct PrintOptions {
346346
result.SkipPrivateStdlibDecls = true;
347347
result.SkipUnderscoredStdlibProtocols = true;
348348
result.SkipDeinit = true;
349-
result.ExcludeAttrList.push_back(DAK_WarnUnusedResult);
350349
result.ExcludeAttrList.push_back(DAK_DiscardableResult);
351350
result.EmptyLineBetweenMembers = true;
352351
result.ElevateDocCommentFromConformance = true;
@@ -432,7 +431,6 @@ struct PrintOptions {
432431
PO.PrintDocumentationComments = false;
433432
PO.ExcludeAttrList.push_back(DAK_Available);
434433
PO.ExcludeAttrList.push_back(DAK_Swift3Migration);
435-
PO.ExcludeAttrList.push_back(DAK_WarnUnusedResult);
436434
PO.SkipPrivateStdlibDecls = true;
437435
PO.ExplodeEnumCaseDecls = true;
438436
return PO;

include/swift/Serialization/ModuleFormat.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,14 +1376,6 @@ namespace decls_block {
13761376
BCBlob // rename, followed by message
13771377
>;
13781378

1379-
using WarnUnusedResultDeclAttrLayout = BCRecordLayout<
1380-
WarnUnusedResult_DECL_ATTR,
1381-
BCFixed<1>, // implicit flag
1382-
BCVBR<6>, // index at the end of the message,
1383-
BCBlob // blob contains the message and mutating-version
1384-
// strings, separated by the prior index
1385-
>;
1386-
13871379
using SpecializeDeclAttrLayout = BCRecordLayout<
13881380
Specialize_DECL_ATTR,
13891381
BCArray<TypeIDField> // concrete types

lib/AST/Attr.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -446,27 +446,6 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options)
446446
break;
447447
}
448448

449-
case DAK_WarnUnusedResult: {
450-
Printer.printAttrName("@warn_unused_result");
451-
auto *attr = cast<WarnUnusedResultAttr>(this);
452-
bool printedParens = false;
453-
if (!attr->getMessage().empty()) {
454-
Printer << "(message: \"" << attr->getMessage() << "\"";
455-
printedParens = true;
456-
}
457-
if (!attr->getMutableVariant().empty()) {
458-
if (printedParens)
459-
Printer << ", ";
460-
else
461-
Printer << "(";
462-
Printer << "mutable_variant: \"" << attr->getMutableVariant() << "\"";
463-
printedParens = true;
464-
}
465-
if (printedParens)
466-
Printer << ")";
467-
break;
468-
}
469-
470449
case DAK_Specialize: {
471450
Printer << "@" << getAttrName() << "(";
472451
auto *attr = cast<SpecializeAttr>(this);
@@ -585,8 +564,6 @@ StringRef DeclAttribute::getAttrName() const {
585564
return "<<synthesized protocol>>";
586565
case DAK_Swift3Migration:
587566
return "swift3_migration";
588-
case DAK_WarnUnusedResult:
589-
return "warn_unused_result";
590567
case DAK_Specialize:
591568
return "_specialize";
592569
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6314,11 +6314,7 @@ void ClangImporter::Implementation::importAttributes(
63146314
}
63156315

63166316
// Map __attribute__((warn_unused_result)).
6317-
if (ClangDecl->hasAttr<clang::WarnUnusedResultAttr>()) {
6318-
MappedDecl->getAttrs().add(new (C) WarnUnusedResultAttr(SourceLoc(),
6319-
SourceLoc(),
6320-
false));
6321-
} else {
6317+
if (!ClangDecl->hasAttr<clang::WarnUnusedResultAttr>()) {
63226318
if (auto MD = dyn_cast<FuncDecl>(MappedDecl)) {
63236319
if (!MD->getResultType()->isVoid()) {
63246320
MD->getAttrs().add(new (C) DiscardableResultAttr(/*implicit*/true));

lib/Parse/ParseDecl.cpp

Lines changed: 35 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,119 +1087,6 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
10871087
break;
10881088
}
10891089

1090-
case DAK_WarnUnusedResult: {
1091-
// @warn_unused_result with no arguments.
1092-
if (Tok.isNot(tok::l_paren)) {
1093-
auto attr = new (Context) WarnUnusedResultAttr(AtLoc, Loc, false);
1094-
Attributes.add(attr);
1095-
break;
1096-
}
1097-
1098-
// @warn_unused_result with arguments.
1099-
StringRef message;
1100-
StringRef mutableVariant;
1101-
SourceLoc lParenLoc = consumeToken();
1102-
bool invalid = false;
1103-
do {
1104-
// If we see a closing parenthesis,
1105-
if (Tok.is(tok::r_paren))
1106-
break;
1107-
1108-
if (Tok.isNot(tok::identifier)) {
1109-
diagnose(Tok, diag::attr_warn_unused_result_expected_name);
1110-
if (Tok.isNot(tok::r_paren))
1111-
skipUntil(tok::r_paren);
1112-
invalid = true;
1113-
break;
1114-
}
1115-
1116-
// Consume the identifier.
1117-
StringRef name = Tok.getText();
1118-
SourceLoc nameLoc = consumeToken();
1119-
1120-
// Figure out which parameter it is.
1121-
enum class KnownParameter {
1122-
Message,
1123-
MutableVariant
1124-
};
1125-
1126-
Optional<KnownParameter> known
1127-
= llvm::StringSwitch<Optional<KnownParameter>>(name)
1128-
.Case("message", KnownParameter::Message)
1129-
.Case("mutable_variant", KnownParameter::MutableVariant)
1130-
.Default(None);
1131-
1132-
// If we don't have the ':', try the deprecated '='. If that doesn't
1133-
// exist neither, complain.
1134-
if (findAttrValueDelimiter()) {
1135-
consumeToken();
1136-
} else {
1137-
if (known)
1138-
diagnose(Tok, diag::attr_warn_unused_result_expected_colon, name);
1139-
else
1140-
diagnose(Tok, diag::attr_warn_unused_result_unknown_parameter, name);
1141-
continue;
1142-
}
1143-
1144-
// If we don't have a string, complain.
1145-
if (Tok.isNot(tok::string_literal)) {
1146-
diagnose(Tok, diag::attr_warn_unused_result_expected_string, name);
1147-
if (Tok.isNot(tok::r_paren))
1148-
skipUntil(tok::r_paren);
1149-
invalid = true;
1150-
break;
1151-
}
1152-
1153-
// Dig out the string.
1154-
auto string = getStringLiteralIfNotInterpolated(*this, nameLoc, Tok,
1155-
name.str());
1156-
consumeToken(tok::string_literal);
1157-
if (!string) {
1158-
continue;
1159-
}
1160-
1161-
if (!known) {
1162-
diagnose(nameLoc, diag::attr_warn_unused_result_unknown_parameter,
1163-
name);
1164-
continue;
1165-
}
1166-
1167-
StringRef *whichParam;
1168-
switch (*known) {
1169-
case KnownParameter::Message:
1170-
whichParam = &message;
1171-
break;
1172-
1173-
case KnownParameter::MutableVariant:
1174-
whichParam = &mutableVariant;
1175-
break;
1176-
}
1177-
1178-
if (!whichParam->empty()) {
1179-
diagnose(nameLoc, diag::attr_warn_unused_result_duplicate_parameter,
1180-
name);
1181-
}
1182-
1183-
*whichParam = *string;
1184-
} while (consumeIf(tok::comma));
1185-
1186-
// Parse the closing ')'.
1187-
SourceLoc rParenLoc;
1188-
if (Tok.isNot(tok::r_paren)) {
1189-
parseMatchingToken(tok::r_paren, rParenLoc,
1190-
diag::attr_warn_unused_result_expected_rparen,
1191-
lParenLoc);
1192-
}
1193-
if (Tok.is(tok::r_paren)) {
1194-
rParenLoc = consumeToken();
1195-
}
1196-
1197-
Attributes.add(new (Context) WarnUnusedResultAttr(AtLoc, Loc, lParenLoc,
1198-
message, mutableVariant,
1199-
rParenLoc, false));
1200-
break;
1201-
}
1202-
12031090
case DAK_Swift3Migration: {
12041091
if (Tok.isNot(tok::l_paren)) {
12051092
diagnose(Loc, diag::attr_expected_lparen, AttrName,
@@ -1460,6 +1347,41 @@ bool Parser::parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc) {
14601347
.fixItReplace(Tok.getLoc(), "available");
14611348
}
14621349

1350+
1351+
if (DK == DAK_Count && Tok.getText() == "warn_unused_result") {
1352+
// The behavior created by @warn_unused_result is now the default. Emit a
1353+
// Fix-It to remove.
1354+
SourceLoc attrLoc = consumeToken();
1355+
1356+
// @warn_unused_result with no arguments.
1357+
if (Tok.isNot(tok::l_paren)) {
1358+
diagnose(AtLoc, diag::attr_warn_unused_result_removed)
1359+
.fixItRemove(SourceRange(AtLoc, attrLoc));
1360+
1361+
return true;
1362+
}
1363+
1364+
// @warn_unused_result with arguments.
1365+
SourceLoc lParenLoc = consumeToken();
1366+
skipUntil(tok::r_paren);
1367+
1368+
// Parse the closing ')'.
1369+
SourceLoc rParenLoc;
1370+
if (Tok.isNot(tok::r_paren)) {
1371+
parseMatchingToken(tok::r_paren, rParenLoc,
1372+
diag::attr_warn_unused_result_expected_rparen,
1373+
lParenLoc);
1374+
}
1375+
if (Tok.is(tok::r_paren)) {
1376+
rParenLoc = consumeToken();
1377+
}
1378+
1379+
diagnose(AtLoc, diag::attr_warn_unused_result_removed)
1380+
.fixItRemove(SourceRange(AtLoc, rParenLoc));
1381+
1382+
return true;
1383+
}
1384+
14631385
if (DK != DAK_Count && !DeclAttribute::shouldBeRejectedByParser(DK))
14641386
return parseNewDeclAttribute(Attributes, AtLoc, DK);
14651387

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
8080
IGNORED_ATTR(UIApplicationMain)
8181
IGNORED_ATTR(UnsafeNoObjCTaggedPointer)
8282
IGNORED_ATTR(Versioned)
83-
IGNORED_ATTR(WarnUnusedResult)
8483
IGNORED_ATTR(ShowInInterface)
8584
IGNORED_ATTR(DiscardableResult)
8685
#undef IGNORED_ATTR
@@ -692,7 +691,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
692691
void visitPostfixAttr(PostfixAttr *attr) { checkOperatorAttribute(attr); }
693692
void visitPrefixAttr(PrefixAttr *attr) { checkOperatorAttribute(attr); }
694693

695-
void visitWarnUnusedResultAttr(WarnUnusedResultAttr *attr);
696694
void visitSpecializeAttr(SpecializeAttr *attr);
697695
};
698696
} // end anonymous namespace
@@ -1344,43 +1342,6 @@ AttributeChecker::visitSetterAccessibilityAttr(SetterAccessibilityAttr *attr) {
13441342
visitAbstractAccessibilityAttr(attr);
13451343
}
13461344

1347-
void AttributeChecker::visitWarnUnusedResultAttr(WarnUnusedResultAttr *attr) {
1348-
if (!attr->getMutableVariant().empty()) {
1349-
// mutable_variant only makes sense for non-mutating methods where
1350-
// it's possible to have a mutating variant.
1351-
auto func = dyn_cast<FuncDecl>(D);
1352-
if (!func) {
1353-
TC.diagnose(attr->getLocation(),
1354-
diag::attr_warn_unused_result_mutable_variable, 0);
1355-
return;
1356-
}
1357-
1358-
if (!func->getDeclContext()->isTypeContext()) {
1359-
TC.diagnose(attr->getLocation(),
1360-
diag::attr_warn_unused_result_mutable_variable, 1);
1361-
return;
1362-
}
1363-
1364-
if (!func->isInstanceMember()) {
1365-
TC.diagnose(attr->getLocation(),
1366-
diag::attr_warn_unused_result_mutable_variable, 2);
1367-
return;
1368-
}
1369-
1370-
if (func->getExtensionType()->getClassOrBoundGenericClass()) {
1371-
TC.diagnose(attr->getLocation(),
1372-
diag::attr_warn_unused_result_mutable_variable, 3);
1373-
return;
1374-
}
1375-
1376-
if (func->isMutating()) {
1377-
TC.diagnose(attr->getLocation(),
1378-
diag::attr_warn_unused_result_mutable_variable, 4);
1379-
return;
1380-
}
1381-
}
1382-
}
1383-
13841345
/// Check that the @_specialize type list has the correct number of entries.
13851346
/// Resolve each type in the list to a concrete type.
13861347
/// Create a Substitution list mapping each nested archetype to a concrete

lib/Sema/TypeCheckDecl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5376,7 +5376,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
53765376
UNINTERESTING_ATTR(SILStored)
53775377
UNINTERESTING_ATTR(Testable)
53785378

5379-
UNINTERESTING_ATTR(WarnUnusedResult)
53805379
UNINTERESTING_ATTR(WarnUnqualifiedAccess)
53815380
UNINTERESTING_ATTR(DiscardableResult)
53825381

0 commit comments

Comments
 (0)