Pseudocode: Replace UnsupportedElementInstruction with UNSUPPORTED_ELEMENT magic.

Generate UNSUPPORTED_ELEMENT for assignments with unresolved left-han side
This commit is contained in:
Alexey Sedunov
2014-07-21 13:45:12 +04:00
parent c32d112e67
commit e11ffb8542
20 changed files with 80 additions and 102 deletions
@@ -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");
@@ -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);
@@ -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)
}
@@ -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)
}
@@ -147,7 +147,7 @@ public enum class MagicKind {
VALUE_CONSUMER
// unrecognized operations
UNRESOLVED_CALL
UNSUPPORTED_OPERATION
UNSUPPORTED_ELEMENT
UNRECOGNIZED_WRITE_RHS
FAKE_INITIALIZER
}
@@ -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)
}
@@ -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");