Skip to content

Commit 3d91d7f

Browse files
authored
Merge pull request swiftlang#34794 from xedin/rdar-71356981
[TypeChecker] Find outermost paren or tuple while checking invalid `i…
2 parents e46ab4b + 607f49d commit 3d91d7f

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

lib/Sema/PreCheckExpr.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,12 +1056,49 @@ namespace {
10561056
if (isa<SequenceExpr>(parent))
10571057
return finish(true, expr);
10581058

1059+
SourceLoc lastInnerParenLoc;
1060+
// Unwrap to the outermost paren in the sequence.
1061+
if (isa<ParenExpr>(parent)) {
1062+
for (;;) {
1063+
auto nextParent = parents.find(parent);
1064+
if (nextParent == parents.end())
1065+
break;
1066+
1067+
// e.g. `foo((&bar), x: ...)`
1068+
if (isa<TupleExpr>(nextParent->second)) {
1069+
lastInnerParenLoc = cast<ParenExpr>(parent)->getLParenLoc();
1070+
parent = nextParent->second;
1071+
break;
1072+
}
1073+
1074+
// e.g. `foo(((&bar))`
1075+
if (isa<ParenExpr>(nextParent->second)) {
1076+
lastInnerParenLoc = cast<ParenExpr>(parent)->getLParenLoc();
1077+
parent = nextParent->second;
1078+
continue;
1079+
}
1080+
1081+
break;
1082+
}
1083+
}
1084+
10591085
if (isa<TupleExpr>(parent) || isa<ParenExpr>(parent)) {
10601086
auto call = parents.find(parent);
10611087
if (call != parents.end()) {
10621088
if (isa<ApplyExpr>(call->getSecond()) ||
1063-
isa<UnresolvedMemberExpr>(call->getSecond()))
1089+
isa<UnresolvedMemberExpr>(call->getSecond())) {
1090+
// If outermost paren is associated with a call or
1091+
// a member reference, it might be valid to have `&`
1092+
// before all of the parens.
1093+
if (lastInnerParenLoc.isValid()) {
1094+
auto &DE = getASTContext().Diags;
1095+
auto diag = DE.diagnose(expr->getStartLoc(),
1096+
diag::extraneous_address_of);
1097+
diag.fixItExchange(expr->getLoc(), lastInnerParenLoc);
1098+
}
1099+
10641100
return finish(true, expr);
1101+
}
10651102

10661103
if (isa<SubscriptExpr>(call->getSecond())) {
10671104
getASTContext().Diags.diagnose(

test/Constraints/lvalues.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,23 @@ func testWritePrefixIterator() {
266266
var underflow = (1..<10).makeIterator()
267267
var (writtenCount, afterLastWritten) = a.writePrefix(from: underflow) // expected-error {{passing value of type 'IndexingIterator<(Range<Int>)>' to an inout parameter requires explicit '&'}} {{62-62=&}}
268268
}
269+
270+
// rdar://problem/71356981 - wrong error message for state passed as inout with ampersand within parentheses
271+
func look_through_parens_when_checking_inout() {
272+
struct Point {
273+
var x: Int = 0
274+
var y: Int = 0
275+
}
276+
277+
func modifyPoint(_ point: inout Point, _: Int = 42) {}
278+
func modifyPoint(_ point: inout Point, msg: String) {}
279+
func modifyPoint(source: inout Point) {}
280+
281+
var point = Point(x: 0, y: 0)
282+
modifyPoint((&point)) // expected-error {{use of extraneous '&}} {{16-17=(}} {{15-16=&}}
283+
modifyPoint(((&point))) // expected-error {{use of extraneous '&}} {{17-18=(}} {{15-16=&}}
284+
modifyPoint(source: (&point)) // expected-error {{use of extraneous '&}} {{24-25=(}} {{23-24=&}}
285+
modifyPoint(source: ((&point))) // expected-error {{use of extraneous '&}} {{25-26=(}} {{23-24=&}}
286+
modifyPoint((&point), 0) // expected-error {{use of extraneous '&}} {{16-17=(}} {{15-16=&}}
287+
modifyPoint((&point), msg: "") // expected-error {{use of extraneous '&}} {{16-17=(}} {{15-16=&}}
288+
}

test/expr/expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ func inoutTests(_ arr: inout Int) {
841841

842842
inoutTests((&x, 24).0) // expected-error {{use of extraneous '&'}}
843843

844-
inoutTests((&x)) // expected-error {{use of extraneous '&'}}
844+
inoutTests((&x)) // expected-error {{use of extraneous '&'}} {{15-16=(}} {{14-15=&}}
845845
inoutTests(&x)
846846

847847
// <rdar://problem/17489894> inout not rejected as operand to assignment operator

0 commit comments

Comments
 (0)