diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt index 5c08b4bfc03..61dffa450ac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt @@ -39,10 +39,7 @@ import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BindingContextUtils -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -1481,6 +1478,16 @@ class ControlFlowProcessor(private val trace: BindingTrace) { when (receiver) { is ImplicitReceiver -> { + if (callElement is KtCallExpression) { + val declaration = receiver.declarationDescriptor + if (declaration is ClassDescriptor) { + val fakeDescriptor = getFakeDescriptorForObject(declaration) + val calleeExpression = callElement.calleeExpression + if (fakeDescriptor != null && calleeExpression != null) { + builder.read(calleeExpression, AccessTarget.Declaration(fakeDescriptor), emptyMap()) + } + } + } receiverValues = receiverValues.plus(createSyntheticValue(callElement, MagicKind.IMPLICIT_RECEIVER), receiver) } is ExpressionReceiver -> { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java index 9ee131b6f4f..551a0a3f910 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/PseudocodeUtil.java @@ -91,7 +91,12 @@ public class PseudocodeUtil { public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference, @NotNull BindingContext bindingContext) { KtElement element = null; if (instruction instanceof ReadValueInstruction) { - element = ((ReadValueInstruction) instruction).getElement(); + ReadValueInstruction readValueInstruction = (ReadValueInstruction) instruction; + AccessTarget target = readValueInstruction.getTarget(); + if (target instanceof AccessTarget.Declaration) { + return ((AccessTarget.Declaration) target).getDescriptor(); + } + element = readValueInstruction.getElement(); } else if (instruction instanceof WriteValueInstruction) { element = ((WriteValueInstruction) instruction).getLValue(); diff --git a/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.instructions b/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.instructions index dd8ad526b5c..932d69157c1 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.instructions +++ b/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.instructions @@ -26,18 +26,19 @@ L0: v(ANOTHER(foo());) magic[FAKE_INITIALIZER](ANOTHER(foo());) -> w(ANOTHER|) - magic[IMPLICIT_RECEIVER](foo()) -> + r(foo, Companion) -> + magic[IMPLICIT_RECEIVER](foo()) -> mark(foo()) - call(foo(), foo|) -> + call(foo(), foo|) -> mark((foo())) - call((foo()), |) -> + call((foo()), |) -> v(companion object { fun foo() = 42 }) - magic[FAKE_INITIALIZER](companion object { fun foo() = 42 }) -> - w(Companion|) + magic[FAKE_INITIALIZER](companion object { fun foo() = 42 }) -> + w(Companion|) L1: - NEXT:[] + NEXT:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.values b/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.values index d998d0467f8..2c0f6a884c9 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.values +++ b/compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.values @@ -8,15 +8,16 @@ enum class EE(val x: Int) { } } --------------------- - : Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> - : EE NEW: magic[FAKE_INITIALIZER](INSTANCE(Companion.foo()),) -> - : EE NEW: magic[FAKE_INITIALIZER](ANOTHER(foo());) -> - : EE.Companion NEW: magic[IMPLICIT_RECEIVER](foo()) -> - : EE.Companion NEW: magic[FAKE_INITIALIZER](companion object { fun foo() = 42 }) -> -Companion : EE.Companion NEW: r(Companion) -> -foo() : Int NEW: call(foo(), foo|) -> -Companion.foo() : Int COPY -(Companion.foo()) : * NEW: call((Companion.foo()), |) -> -foo() : Int NEW: call(foo(), foo|) -> -(foo()) : * NEW: call((foo()), |) -> + : Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> + : EE.Companion NEW: magic[FAKE_INITIALIZER](companion object { fun foo() = 42 }) -> + : EE NEW: magic[FAKE_INITIALIZER](INSTANCE(Companion.foo()),) -> + : EE NEW: magic[FAKE_INITIALIZER](ANOTHER(foo());) -> + : EE.Companion NEW: magic[IMPLICIT_RECEIVER](foo()) -> +Companion : EE.Companion NEW: r(Companion) -> +foo() : Int NEW: call(foo(), foo|) -> +Companion.foo() : Int COPY +(Companion.foo()) : * NEW: call((Companion.foo()), |) -> +foo : * NEW: r(foo, Companion) -> +foo() : Int NEW: call(foo(), foo|) -> +(foo()) : * NEW: call((foo()), |) -> ===================== diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumCompanionInterdependence.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumCompanionInterdependence.kt index a4dce9846c1..5e385f6333e 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumCompanionInterdependence.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/enumCompanionInterdependence.kt @@ -40,7 +40,7 @@ enum class EnumCompanion1(val x: Int) { } // Also should be reported for implicit receiver enum class EnumCompanion2(val x: Int) { - INSTANCE(foo()); // TODO + INSTANCE(foo()); companion object { fun foo() = 42