Skip to content

Commit b65580c

Browse files
authored
Merge pull request #26247 from DougGregor/property-wrapper-crash-fixes-5.1
[5.1] [SE-0258] Fix a few more crashes involving property wrappers in invalid code
2 parents 2a2b5b0 + 6d4c245 commit b65580c

File tree

6 files changed

+60
-10
lines changed

6 files changed

+60
-10
lines changed

lib/AST/Decl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5838,16 +5838,16 @@ Expr *swift::findOriginalPropertyWrapperInitialValue(VarDecl *var,
58385838

58395839
// ... producing a value of the same nominal type as the innermost
58405840
// property wrapper.
5841-
if (call->getType()->getAnyNominal() != innermostNominal)
5841+
if (!call->getType() ||
5842+
call->getType()->getAnyNominal() != innermostNominal)
58425843
return { true, E };
58435844

58445845
// Find the implicit initialValue argument.
58455846
if (auto tuple = dyn_cast<TupleExpr>(call->getArg())) {
58465847
ASTContext &ctx = innermostNominal->getASTContext();
58475848
for (unsigned i : range(tuple->getNumElements())) {
5848-
if ((tuple->getElementName(i) == ctx.Id_wrappedValue ||
5849-
tuple->getElementName(i) == ctx.Id_initialValue) &&
5850-
tuple->getElementNameLoc(i).isInvalid()) {
5849+
if (tuple->getElementName(i) == ctx.Id_wrappedValue ||
5850+
tuple->getElementName(i) == ctx.Id_initialValue) {
58515851
initArg = tuple->getElement(i);
58525852
return { false, E };
58535853
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2566,14 +2566,22 @@ bool OutOfOrderArgumentFailure::diagnoseAsError() {
25662566
SourceLoc diagLoc = firstRange.Start;
25672567

25682568
auto addFixIts = [&](InFlightDiagnostic diag) {
2569+
// Don't add Fix-Its if one of the ranges is outside of the argument
2570+
// list, which can happen when we're splicing together an argument list
2571+
// from multiple sources.
2572+
auto &SM = getASTContext().SourceMgr;
2573+
auto argsRange = tuple->getSourceRange();
2574+
if (!SM.rangeContains(argsRange, firstRange) ||
2575+
!SM.rangeContains(argsRange, secondRange))
2576+
return;
2577+
25692578
diag.highlight(firstRange).highlight(secondRange);
25702579

25712580
// Move the misplaced argument by removing it from one location and
25722581
// inserting it in another location. To maintain argument comma
25732582
// separation, since the argument is always moving to an earlier index
25742583
// the preceding comma and whitespace is removed and a new trailing
25752584
// comma and space is inserted with the moved argument.
2576-
auto &SM = getASTContext().SourceMgr;
25772585
auto text = SM.extractText(
25782586
Lexer::getCharSourceRangeFromSourceRange(SM, firstRange));
25792587

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,8 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
654654
wrapperAttrs[i]->getTypeLoc().getLoc(),
655655
wrapperType, ctx);
656656

657+
SourceLoc startLoc = wrapperAttrs[i]->getTypeLoc().getSourceRange().Start;
658+
657659
// If there were no arguments provided for the attribute at this level,
658660
// call `init(wrappedValue:)` directly.
659661
auto attr = wrapperAttrs[i];
@@ -664,8 +666,10 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
664666
argName = init->getFullName().getArgumentNames()[0];
665667
}
666668

667-
initializer = CallExpr::createImplicit(
668-
ctx, typeExpr, {initializer}, {argName});
669+
initializer = CallExpr::create(
670+
ctx, typeExpr, startLoc, {initializer}, {argName},
671+
{initializer->getStartLoc()}, initializer->getEndLoc(),
672+
nullptr, /*implicit=*/true);
669673
continue;
670674
}
671675

@@ -675,7 +679,7 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
675679
SmallVector<SourceLoc, 4> elementLocs;
676680
elements.push_back(initializer);
677681
elementNames.push_back(ctx.Id_wrappedValue);
678-
elementLocs.push_back(SourceLoc());
682+
elementLocs.push_back(initializer->getStartLoc());
679683

680684
if (auto tuple = dyn_cast<TupleExpr>(attr->getArg())) {
681685
for (unsigned i : range(tuple->getNumElements())) {
@@ -690,8 +694,9 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
690694
elementLocs.push_back(SourceLoc());
691695
}
692696

693-
initializer = CallExpr::createImplicit(
694-
ctx, typeExpr, elements, elementNames);
697+
initializer = CallExpr::create(
698+
ctx, typeExpr, startLoc, elements, elementNames, elementLocs,
699+
attr->getArg()->getEndLoc(), nullptr, /*implicit=*/true);
695700
}
696701

697702
return initializer;

test/decl/var/property_wrappers.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,18 @@ struct TestAlias {
903903
@Alias var foo = 17
904904
}
905905

906+
// rdar://problem/52969503 - crash due to invalid source ranges in ill-formed
907+
// code.
908+
@propertyWrapper
909+
struct Wrap52969503<T> {
910+
var wrappedValue: T
911+
912+
init(blah: Int, wrappedValue: T) { }
913+
}
914+
915+
struct Test52969503 {
916+
@Wrap52969503(blah: 5) var foo: Int = 1 // expected-error{{argument 'blah' must precede argument 'wrappedValue'}}
917+
}
906918

907919

908920
//
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
public struct Use { @Wrap var value: some Doubl = 1.0 }
3+
@propertyWrapper public struct Wrap { public var wrappedValue: Double }
4+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
protocol MyBindableObject {}
3+
4+
@propertyWrapper
5+
struct MyBinding<T> where T : MyBindableObject {
6+
public var wrappedV: T
7+
public var wrapperValue: MyBinding<T> {
8+
return self
9+
}
10+
public init(initialValue: T) {
11+
self.value = initialValue
12+
}
13+
}
14+
class BeaconDetector: MyBindableObject {
15+
struct ContentView {
16+
@MyBinding var detector = BeaconDetector()
17+
func foo() {
18+
_ = detector.undefined == 1
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)