Control-Flow: Generate instruction for left-hand side of invalid assignments
#KT-8390 Fixed
This commit is contained in:
@@ -585,7 +585,15 @@ public class JetControlFlowProcessor {
|
|||||||
accessTarget = getDeclarationAccessTarget(left);
|
accessTarget = getDeclarationAccessTarget(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
recordWrite(left, accessTarget, rhsDeferredValue.invoke(), receiverValues, parentExpression);
|
if (accessTarget == AccessTarget.BlackBox.INSTANCE$ && !(left instanceof JetProperty)) {
|
||||||
|
generateInstructions(left);
|
||||||
|
createSyntheticValue(left, MagicKind.VALUE_CONSUMER, left);
|
||||||
|
}
|
||||||
|
|
||||||
|
PseudoValue rightValue = rhsDeferredValue.invoke();
|
||||||
|
PseudoValue rValue =
|
||||||
|
rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS);
|
||||||
|
builder.write(parentExpression, left, rValue, accessTarget, receiverValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateArrayAssignment(
|
private void generateArrayAssignment(
|
||||||
@@ -663,24 +671,6 @@ public class JetControlFlowProcessor {
|
|||||||
return argumentValues;
|
return argumentValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordWrite(
|
|
||||||
@NotNull JetExpression left,
|
|
||||||
@NotNull AccessTarget target,
|
|
||||||
@Nullable PseudoValue rightValue,
|
|
||||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
|
||||||
@NotNull JetExpression parentExpression
|
|
||||||
) {
|
|
||||||
if (target == AccessTarget.BlackBox.INSTANCE$) {
|
|
||||||
List<PseudoValue> values = ContainerUtil.createMaybeSingletonList(rightValue);
|
|
||||||
builder.magic(parentExpression, parentExpression, values, defaultTypeMap(values), MagicKind.UNSUPPORTED_ELEMENT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PseudoValue rValue =
|
|
||||||
rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS);
|
|
||||||
builder.write(parentExpression, left, rValue, target, receiverValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) {
|
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall<?> resolvedCall) {
|
||||||
if (builder.getBoundValue(arrayAccessExpression) != null) return;
|
if (builder.getBoundValue(arrayAccessExpression) != null) return;
|
||||||
mark(arrayAccessExpression);
|
mark(arrayAccessExpression);
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ L0:
|
|||||||
magic[FAKE_INITIALIZER](c: C) -> <v0>
|
magic[FAKE_INITIALIZER](c: C) -> <v0>
|
||||||
w(c|<v0>)
|
w(c|<v0>)
|
||||||
2 mark({ this = c })
|
2 mark({ this = c })
|
||||||
r(c) -> <v1>
|
r(this, <this>) -> <v1>
|
||||||
magic[UNSUPPORTED_ELEMENT](this = c|<v1>) -> <v2>
|
magic[VALUE_CONSUMER](this|<v1>) -> <v2>
|
||||||
|
r(c) -> <v3>
|
||||||
|
w(this|<v3>)
|
||||||
L1:
|
L1:
|
||||||
1 <END> NEXT:[<SINK>]
|
1 <END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
@@ -4,7 +4,10 @@ fun Int.bar(c: C) {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
<v0>: {<: [ERROR : C]} NEW: magic[FAKE_INITIALIZER](c: C) -> <v0>
|
<v0>: {<: [ERROR : C]} NEW: magic[FAKE_INITIALIZER](c: C) -> <v0>
|
||||||
c <v1>: * NEW: r(c) -> <v1>
|
<v2>: * NEW: magic[VALUE_CONSUMER](this|<v1>) -> <v2>
|
||||||
this = c <v2>: * NEW: magic[UNSUPPORTED_ELEMENT](this = c|<v1>) -> <v2>
|
this <v1>: * COPY
|
||||||
{ this = c } <v2>: * COPY
|
this <v1>: * NEW: r(this, <this>) -> <v1>
|
||||||
|
c <v3>: * NEW: r(c) -> <v3>
|
||||||
|
this = c !<v4>: *
|
||||||
|
{ this = c } !<v4>: * COPY
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ fun foo() {
|
|||||||
L0:
|
L0:
|
||||||
1 <START>
|
1 <START>
|
||||||
2 mark({ x = "" })
|
2 mark({ x = "" })
|
||||||
|
magic[UNRESOLVED_CALL](x) -> <v0>
|
||||||
|
magic[VALUE_CONSUMER](x|<v0>) -> <v1>
|
||||||
mark("")
|
mark("")
|
||||||
r("") -> <v0>
|
r("") -> <v2>
|
||||||
magic[UNSUPPORTED_ELEMENT](x = ""|<v0>) -> <v1>
|
w(x|<v2>)
|
||||||
L1:
|
L1:
|
||||||
1 <END> NEXT:[<SINK>]
|
1 <END> NEXT:[<SINK>]
|
||||||
error:
|
error:
|
||||||
<ERROR> PREV:[]
|
<ERROR> PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> PREV:[<ERROR>, <END>]
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
=====================
|
=====================
|
||||||
@@ -3,7 +3,9 @@ fun foo() {
|
|||||||
x = ""
|
x = ""
|
||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
"" <v0>: * NEW: r("") -> <v0>
|
<v1>: * NEW: magic[VALUE_CONSUMER](x|<v0>) -> <v1>
|
||||||
x = "" <v1>: * NEW: magic[UNSUPPORTED_ELEMENT](x = ""|<v0>) -> <v1>
|
x <v0>: * NEW: magic[UNRESOLVED_CALL](x) -> <v0>
|
||||||
{ x = "" } <v1>: * COPY
|
"" <v2>: * NEW: r("") -> <v2>
|
||||||
|
x = "" !<v3>: *
|
||||||
|
{ x = "" } !<v3>: * COPY
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ class D() {
|
|||||||
fun foo(): Unit {}
|
fun foo(): Unit {}
|
||||||
|
|
||||||
fun cannotBe() {
|
fun cannotBe() {
|
||||||
var <!UNUSED_VARIABLE!>i<!>: Int = 5
|
var i: Int = 5
|
||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>z<!> = 30;
|
<!UNRESOLVED_REFERENCE!>z<!> = 30;
|
||||||
<!VARIABLE_EXPECTED!>""<!> = "";
|
<!VARIABLE_EXPECTED!>""<!> = "";
|
||||||
|
|||||||
@@ -26,3 +26,7 @@ fun get(p: Any) {
|
|||||||
|
|
||||||
fun set(p: Any) {
|
fun set(p: Any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun foo(s: String) {
|
||||||
|
s.<!UNRESOLVED_REFERENCE!>xxx<!> = 1
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
internal fun f(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int, /*2*/ c: kotlin.Int = ...): kotlin.Unit
|
internal fun f(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int, /*2*/ c: kotlin.Int = ...): kotlin.Unit
|
||||||
|
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
|
||||||
internal fun get(/*0*/ p: kotlin.Any): kotlin.Unit
|
internal fun get(/*0*/ p: kotlin.Any): kotlin.Unit
|
||||||
internal fun set(/*0*/ p: kotlin.Any): kotlin.Unit
|
internal fun set(/*0*/ p: kotlin.Any): kotlin.Unit
|
||||||
internal fun kotlin.Any.get(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.PropertyMetadata): kotlin.String
|
internal fun kotlin.Any.get(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.PropertyMetadata): kotlin.String
|
||||||
|
|||||||
Reference in New Issue
Block a user