Skip to content

Commit b10e5de

Browse files
authored
Merge pull request #20354 from xedin/rdar-45825806
[ASTVerifier] Fix pre-check to look at subscript arguments
2 parents bbc81ba + 17b04ba commit b10e5de

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,24 @@ struct is_apply_expr
8585
std::is_same<Ty, DotSyntaxCallExpr>::value ||
8686
std::is_same<Ty, ConstructorRefCallExpr>::value> {};
8787

88+
template <typename Ty>
89+
struct is_subscript_expr
90+
: public std::integral_constant<
91+
bool, std::is_same<Ty, SubscriptExpr>::value ||
92+
std::is_same<Ty, DynamicSubscriptExpr>::value> {};
93+
8894
template <typename Ty>
8995
struct is_autoclosure_expr
9096
: public std::integral_constant<bool,
9197
std::is_same<Ty, AutoClosureExpr>::value> {
9298
};
9399

94100
template <typename Ty>
95-
struct is_apply_or_autoclosure_expr
96-
: public std::integral_constant<
97-
bool, is_apply_expr<Ty>::value || is_autoclosure_expr<Ty>::value> {};
101+
struct is_apply_subscript_or_autoclosure_expr
102+
: public std::integral_constant<bool, is_apply_expr<Ty>::value ||
103+
is_subscript_expr<Ty>::value ||
104+
is_autoclosure_expr<Ty>::value> {
105+
};
98106

99107
template <typename Verifier, typename Kind>
100108
std::pair<bool, Expr *> dispatchVisitPreExprHelper(
@@ -112,6 +120,22 @@ std::pair<bool, Expr *> dispatchVisitPreExprHelper(
112120
return {false, node};
113121
}
114122

123+
template <typename Verifier, typename Kind>
124+
std::pair<bool, Expr *> dispatchVisitPreExprHelper(
125+
Verifier &V,
126+
typename std::enable_if<
127+
is_subscript_expr<typename std::remove_pointer<Kind>::type>::value,
128+
Kind>::type node) {
129+
if (V.shouldVerify(node)) {
130+
// Record any inout_to_pointer or array_to_pointer that we see in
131+
// the proper position.
132+
V.maybeRecordValidPointerConversion(node, node->getIndex());
133+
return {true, node};
134+
}
135+
V.cleanup(node);
136+
return {false, node};
137+
}
138+
115139
template <typename Verifier, typename Kind>
116140
std::pair<bool, Expr *> dispatchVisitPreExprHelper(
117141
Verifier &V,
@@ -131,7 +155,7 @@ std::pair<bool, Expr *> dispatchVisitPreExprHelper(
131155
template <typename Verifier, typename Kind>
132156
std::pair<bool, Expr *> dispatchVisitPreExprHelper(
133157
Verifier &V, typename std::enable_if<
134-
!is_apply_or_autoclosure_expr<
158+
!is_apply_subscript_or_autoclosure_expr<
135159
typename std::remove_pointer<Kind>::type>::value,
136160
Kind>::type node) {
137161
if (V.shouldVerify(node)) {

test/Constraints/subscript.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,15 @@ func rdar_45819956() {
132132
_ = s[takesPtr: &i]
133133
// expected-error@-1 {{cannot pass an inout argument to a subscript; use 'withUnsafeMutablePointer' to explicitly convert argument to a pointer}}
134134
}
135+
136+
// rdar://problem/45825806 - [SR-7190] Array-to-pointer in subscript arg crashes compiler
137+
func rdar_45825806() {
138+
struct S {
139+
subscript(takesPtr ptr: UnsafePointer<Int>) -> Int {
140+
get { return 0 }
141+
}
142+
}
143+
144+
let s = S()
145+
_ = s[takesPtr: [1, 2, 3]] // Ok
146+
}

0 commit comments

Comments
 (0)