Pseudocode: Replace UnsupportedElementInstruction with UNSUPPORTED_ELEMENT magic.
Generate UNSUPPORTED_ELEMENT for assignments with unresolved left-han side
This commit is contained in:
@@ -160,7 +160,4 @@ public interface JetControlFlowBuilder {
|
||||
@NotNull PseudoValue rValue,
|
||||
@NotNull AccessTarget target,
|
||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues);
|
||||
|
||||
// Other
|
||||
void unsupported(JetElement element);
|
||||
}
|
||||
|
||||
@@ -242,11 +242,6 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
|
||||
getDelegateBuilder().returnNoValue(returnExpression, subroutine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported(JetElement element) {
|
||||
getDelegateBuilder().unsupported(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(
|
||||
@NotNull JetElement assignment,
|
||||
|
||||
@@ -458,7 +458,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
Map<PseudoValue, ReceiverValue> receiverValues = SmartFMap.emptyMap();
|
||||
AccessTarget accessTarget = AccessTarget.BlackBox.INSTANCE$;
|
||||
boolean unsupported = false;
|
||||
if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) {
|
||||
accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left));
|
||||
if (accessTarget instanceof AccessTarget.Call) {
|
||||
@@ -468,17 +467,8 @@ public class JetControlFlowProcessor {
|
||||
else if (left instanceof JetProperty) {
|
||||
accessTarget = getDeclarationAccessTarget(left);
|
||||
}
|
||||
else {
|
||||
unsupported = true;
|
||||
}
|
||||
|
||||
PseudoValue rhsValue = rhsDeferredValue.invoke();
|
||||
if (unsupported) {
|
||||
builder.unsupported(parentExpression); // TODO
|
||||
}
|
||||
else {
|
||||
recordWrite(left, accessTarget, rhsValue, receiverValues, parentExpression);
|
||||
}
|
||||
recordWrite(left, accessTarget, rhsDeferredValue.invoke(), receiverValues, parentExpression);
|
||||
}
|
||||
|
||||
private void generateArrayAssignment(
|
||||
@@ -558,9 +548,13 @@ public class JetControlFlowProcessor {
|
||||
@NotNull Map<PseudoValue, ReceiverValue> receiverValues,
|
||||
@NotNull JetExpression parentExpression
|
||||
) {
|
||||
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
|
||||
if (descriptor != null) {
|
||||
PseudoValue rValue = rightValue != null ? rightValue : createSyntheticValue(parentExpression, MagicKind.UNRECOGNIZED_WRITE_RHS);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1097,7 +1091,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
else {
|
||||
generateInstructions(receiverExpression);
|
||||
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_OPERATION, receiverExpression);
|
||||
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,7 +1203,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
else {
|
||||
visitJetElement(expression);
|
||||
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_OPERATION, left);
|
||||
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,6 +1397,11 @@ public class JetControlFlowProcessor {
|
||||
builder.magic(specifier, specifier, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) {
|
||||
// Do not generate UNSUPPORTED_ELEMENT here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDelegationSpecifierList(@NotNull JetDelegationSpecifierList list) {
|
||||
list.acceptChildren(this);
|
||||
@@ -1425,13 +1424,14 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitJetElement(@NotNull JetElement element) {
|
||||
builder.unsupported(element);
|
||||
createNonSyntheticValue(element, MagicKind.UNSUPPORTED_ELEMENT);
|
||||
}
|
||||
|
||||
private boolean generateCall(@Nullable JetElement callElement) {
|
||||
if (callElement == null) return false;
|
||||
return checkAndGenerateCall(callElement, getResolvedCall(callElement, trace.getBindingContext()));
|
||||
}
|
||||
|
||||
private boolean checkAndGenerateCall(@NotNull JetElement callElement, @Nullable ResolvedCall<?> resolvedCall) {
|
||||
if (resolvedCall == null) {
|
||||
builder.compilationError(callElement, "No resolved call");
|
||||
|
||||
-5
@@ -386,11 +386,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
assert pop instanceof TryFinallyBlockInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsupported(JetElement element) {
|
||||
add(new UnsupportedElementInstruction(element, getCurrentScope()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
|
||||
pseudocode.repeatPart(startLabel, finishLabel);
|
||||
|
||||
-4
@@ -62,10 +62,6 @@ public open class InstructionVisitor() {
|
||||
visitInstruction(instruction)
|
||||
}
|
||||
|
||||
public open fun visitUnsupportedElementInstruction(instruction: UnsupportedElementInstruction) {
|
||||
visitInstructionWithNext(instruction)
|
||||
}
|
||||
|
||||
public open fun visitSubroutineExit(instruction: SubroutineExitInstruction) {
|
||||
visitInstruction(instruction)
|
||||
}
|
||||
|
||||
-4
@@ -64,10 +64,6 @@ public abstract class InstructionVisitorWithResult<R>() {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
|
||||
public open fun visitUnsupportedElementInstruction(instruction: UnsupportedElementInstruction): R {
|
||||
return visitInstructionWithNext(instruction)
|
||||
}
|
||||
|
||||
public open fun visitSubroutineExit(instruction: SubroutineExitInstruction): R {
|
||||
return visitInstruction(instruction)
|
||||
}
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ public enum class MagicKind {
|
||||
VALUE_CONSUMER
|
||||
// unrecognized operations
|
||||
UNRESOLVED_CALL
|
||||
UNSUPPORTED_OPERATION
|
||||
UNSUPPORTED_ELEMENT
|
||||
UNRECOGNIZED_WRITE_RHS
|
||||
FAKE_INITIALIZER
|
||||
}
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.cfg.pseudocode.instructions.special
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.LexicalScope
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionImpl
|
||||
|
||||
public class UnsupportedElementInstruction(
|
||||
element: JetElement,
|
||||
lexicalScope: LexicalScope
|
||||
) : InstructionWithNext(element, lexicalScope) {
|
||||
override fun accept(visitor: InstructionVisitor) {
|
||||
visitor.visitUnsupportedElementInstruction(this)
|
||||
}
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R {
|
||||
return visitor.visitUnsupportedElementInstruction(this)
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"unsupported(" + element + " : " + render(element) + ")"
|
||||
|
||||
override fun createCopy(): InstructionImpl =
|
||||
UnsupportedElementInstruction(element, lexicalScope)
|
||||
}
|
||||
-1
@@ -21,7 +21,6 @@ L0:
|
||||
v(b: Int)
|
||||
magic[FAKE_INITIALIZER](b: Int) -> <v1>
|
||||
w(b|<v1>)
|
||||
unsupported(DELEGATOR_SUPER_CLASS : T)
|
||||
L1:
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
|
||||
@@ -31,13 +31,12 @@ class B : A {
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
unsupported(DELEGATOR_SUPER_CLASS : A)
|
||||
L1:
|
||||
<END> NEXT:[<SINK>]
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== foo ==
|
||||
override fun foo() = 10
|
||||
|
||||
@@ -10,11 +10,11 @@ L0:
|
||||
w(c|<v0>)
|
||||
2 mark({ this = c })
|
||||
r(c) -> <v1>
|
||||
unsupported(BINARY_EXPRESSION : this = c)
|
||||
magic[UNSUPPORTED_ELEMENT](this = c|<v1>) -> <v2>
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>]
|
||||
1 <END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -3,6 +3,8 @@ fun Int.bar(c: C) {
|
||||
this = c
|
||||
}
|
||||
---------------------
|
||||
<v0>: {<: [ERROR : C]} NEW: magic[FAKE_INITIALIZER](c: C) -> <v0>
|
||||
c <v1>: * NEW: r(c) -> <v1>
|
||||
<v0>: {<: [ERROR : C]} NEW: magic[FAKE_INITIALIZER](c: C) -> <v0>
|
||||
c <v1>: * NEW: r(c) -> <v1>
|
||||
this = c <v2>: * NEW: magic[UNSUPPORTED_ELEMENT](this = c|<v1>) -> <v2>
|
||||
{ this = c } <v2>: * COPY
|
||||
=====================
|
||||
|
||||
@@ -11,11 +11,11 @@ L0:
|
||||
2 mark({ s. })
|
||||
mark(s.)
|
||||
r(s) -> <v1>
|
||||
magic[UNSUPPORTED_OPERATION](s.|<v1>) -> <v2>
|
||||
magic[UNSUPPORTED_ELEMENT](s.|<v1>) -> <v2>
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>]
|
||||
1 <END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -3,8 +3,8 @@ fun foo(s: String) {
|
||||
s.
|
||||
}
|
||||
---------------------
|
||||
<v0>: String NEW: magic[FAKE_INITIALIZER](s: String) -> <v0>
|
||||
s <v1>: * NEW: r(s) -> <v1>
|
||||
s. <v2>: * NEW: magic[UNSUPPORTED_OPERATION](s.|<v1>) -> <v2>
|
||||
{ s. } <v2>: * COPY
|
||||
<v0>: String NEW: magic[FAKE_INITIALIZER](s: String) -> <v0>
|
||||
s <v1>: * NEW: r(s) -> <v1>
|
||||
s. <v2>: * NEW: magic[UNSUPPORTED_ELEMENT](s.|<v1>) -> <v2>
|
||||
{ s. } <v2>: * COPY
|
||||
=====================
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
== foo ==
|
||||
fun foo() {
|
||||
x = ""
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
2 mark({ x = "" })
|
||||
mark("")
|
||||
r("") -> <v0>
|
||||
magic[UNSUPPORTED_ELEMENT](x = ""|<v0>) -> <v1>
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,3 @@
|
||||
fun foo() {
|
||||
x = ""
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
== foo ==
|
||||
fun foo() {
|
||||
x = ""
|
||||
}
|
||||
---------------------
|
||||
"" <v0>: * NEW: r("") -> <v0>
|
||||
x = "" <v1>: * NEW: magic[UNSUPPORTED_ELEMENT](x = ""|<v0>) -> <v1>
|
||||
{ x = "" } <v1>: * COPY
|
||||
=====================
|
||||
@@ -24,6 +24,8 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.Instruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionWithNext;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.MagicInstruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.MagicKind;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.*;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.*;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
@@ -155,7 +157,7 @@ public class CFGraphToDotFilePrinter {
|
||||
else if (node instanceof NondeterministicJumpInstruction) {
|
||||
shape = "Mdiamond";
|
||||
}
|
||||
else if (node instanceof UnsupportedElementInstruction) {
|
||||
else if (node instanceof MagicInstruction && ((MagicInstruction) node).getKind() == MagicKind.UNSUPPORTED_ELEMENT) {
|
||||
shape = "box, fillcolor=red, style=filled";
|
||||
}
|
||||
else if (node instanceof LocalFunctionDeclarationInstruction) {
|
||||
|
||||
@@ -434,6 +434,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unresolvedWriteLHS.kt")
|
||||
public void testUnresolvedWriteLHS() throws Exception {
|
||||
doTest("compiler/testData/cfg/expressions/unresolvedWriteLHS.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unusedExpressionSimpleName.kt")
|
||||
public void testUnusedExpressionSimpleName() throws Exception {
|
||||
doTest("compiler/testData/cfg/expressions/unusedExpressionSimpleName.kt");
|
||||
|
||||
@@ -438,6 +438,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
||||
doTest("compiler/testData/cfg/expressions/unresolvedProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unresolvedWriteLHS.kt")
|
||||
public void testUnresolvedWriteLHS() throws Exception {
|
||||
doTest("compiler/testData/cfg/expressions/unresolvedWriteLHS.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unusedExpressionSimpleName.kt")
|
||||
public void testUnusedExpressionSimpleName() throws Exception {
|
||||
doTest("compiler/testData/cfg/expressions/unusedExpressionSimpleName.kt");
|
||||
|
||||
Reference in New Issue
Block a user