@@ -47,7 +47,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
47
47
}
48
48
val targs = (0 until targsSize).map(x => new ErazedType ()).toList
49
49
val args = ctx.definitions.ArrayOf (ctx.definitions.StringType ) :: Nil
50
- val call = CallInfoWithContext (tpe, targs, args, OuterTargs .empty, None , None )
50
+ val call = CallInfoWithContext (tpe, targs, args, OuterTargs .empty, None , None , isErased = false )
51
51
entryPoints(call) = entryPointId
52
52
reachableMethods += call
53
53
val t = ref(s.owner).tpe
@@ -81,10 +81,10 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
81
81
}
82
82
if (! clas.is(JavaDefined ) && clas.is(Module )) {
83
83
val fields = clas.classInfo.decls.filter(x => ! x.is(Method ) && ! x.isType)
84
- val parent = Some (CallInfoWithContext (x.tp.select(clas.primaryConstructor), x.tp.baseArgInfos(clas), Nil , x.outerTargs, None , None ))
84
+ val parent = Some (CallInfoWithContext (x.tp.select(clas.primaryConstructor), x.tp.baseArgInfos(clas), Nil , x.outerTargs, None , None , isErased = false ))
85
85
reachableMethods ++= fields.map {
86
86
fieldSym =>
87
- CallInfoWithContext (x.tp.select(fieldSym), Nil , Nil , x.outerTargs, parent, None )
87
+ CallInfoWithContext (x.tp.select(fieldSym), Nil , Nil , x.outerTargs, parent, None , isErased = false )
88
88
}
89
89
}
90
90
}
@@ -189,7 +189,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
189
189
}.apply(OuterTargs .empty, tp)
190
190
}
191
191
192
- private def instantiateCallSite (caller : CallInfoWithContext , rec : Type , callee : CallInfo , types : Traversable [TypeWithContext ]): Traversable [CallInfoWithContext ] = {
192
+ private def instantiateCallSite (caller : CallInfoWithContext , rec : Type , callee : CallInfo , types : Traversable [TypeWithContext ], isErased : Boolean = false ): Traversable [CallInfoWithContext ] = {
193
193
194
194
lazy val someCaller = Some (caller)
195
195
lazy val someCallee = Some (callee)
@@ -200,6 +200,10 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
200
200
val calleeSymbol = callee.call.termSymbol.asTerm
201
201
val callerSymbol = caller.call.termSymbol
202
202
203
+ def mkCallInfoWithContext (call : Type , targs : List [Type ], args : List [Type ], outerTargs : OuterTargs ) = {
204
+ CallInfoWithContext (call, targs, args, outerTargs, someCaller, someCallee, isErased)
205
+ }
206
+
203
207
val tpamsOuter = caller.call.widen match {
204
208
case t : PolyType =>
205
209
OuterTargs .empty.addAll(callerSymbol, t.paramNames, caller.targs)
@@ -309,10 +313,10 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
309
313
assert(call.exists)
310
314
t.underlying.select(call)
311
315
}
312
- CallInfoWithContext (preciseSelectCall, targs, args, outerTargs, someCaller, someCallee ) :: Nil
316
+ mkCallInfoWithContext (preciseSelectCall, targs, args, outerTargs) :: Nil
313
317
case t : ClosureType if calleeSymbol.name eq t.implementedMethod.name =>
314
318
val methodSym = t.meth.meth.symbol.asTerm
315
- CallInfoWithContext (TermRef .withFixedSym(t.underlying, methodSym.name, methodSym), targs, t.meth.env.map(_.tpe) ++ args, outerTargs ++ t.outerTargs, someCaller, someCallee ) :: Nil
319
+ mkCallInfoWithContext (TermRef .withFixedSym(t.underlying, methodSym.name, methodSym), targs, t.meth.env.map(_.tpe) ++ args, outerTargs ++ t.outerTargs) :: Nil
316
320
case AndType (tp1, tp2) =>
317
321
dispatchCalls(tp1).toSet.intersect(dispatchCalls(tp2).toSet)
318
322
case _ =>
@@ -330,7 +334,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
330
334
alt <- tp.tp.member(calleeSymbol.name).altsWith(p => p.asSeenFrom(tp.tp).matches(calleeSymbol.asSeenFrom(tp.tp)))
331
335
if alt.exists
332
336
} yield {
333
- CallInfoWithContext (tp.tp.select(alt.symbol), targs, args, outerTargs ++ tp.outerTargs, someCaller, someCallee )
337
+ mkCallInfoWithContext (tp.tp.select(alt.symbol), targs, args, outerTargs ++ tp.outerTargs)
334
338
}
335
339
}
336
340
@@ -355,7 +359,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
355
359
(uncastedSig.paramTypess.flatten zip castedSig.paramTypess.flatten) foreach (x => addCast(x._2, x._1))
356
360
addCast(uncastedSig.finalResultType, castedSig.finalResultType)
357
361
358
- CallInfoWithContext (tp.tp.select(alt.symbol), targs, args, outerTargs ++ tp.outerTargs, someCaller, someCallee )
362
+ mkCallInfoWithContext (tp.tp.select(alt.symbol), targs, args, outerTargs ++ tp.outerTargs)
359
363
}
360
364
}
361
365
@@ -380,7 +384,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
380
384
Nil
381
385
case NoPrefix => // inner method
382
386
assert(calleeSymbol.is(ParamAccessor ) || calleeSymbol.owner.is(Method ) || calleeSymbol.owner.isLocalDummy)
383
- CallInfoWithContext (TermRef .withFixedSym(caller.call.normalizedPrefix, calleeSymbol.name, calleeSymbol), targs, args, outerTargs, someCaller, someCallee ) :: Nil
387
+ mkCallInfoWithContext (TermRef .withFixedSym(caller.call.normalizedPrefix, calleeSymbol.name, calleeSymbol), targs, args, outerTargs) :: Nil
384
388
385
389
case t if calleeSymbol.isConstructor =>
386
390
@@ -418,7 +422,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
418
422
propagateTargs(receiver).select(calleeSymbol)
419
423
}
420
424
421
- CallInfoWithContext (call, targs, args, outerTargs, someCaller, someCallee ) :: Nil
425
+ mkCallInfoWithContext (call, targs, args, outerTargs) :: Nil
422
426
423
427
// super call in a class (know target precisely)
424
428
case st : SuperType =>
@@ -430,7 +434,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
430
434
val thisTpePropagated = propagateTargs(thisTpe)
431
435
432
436
433
- CallInfoWithContext (TermRef .withFixedSym(thisTpePropagated, targetMethod.name, targetMethod), targs, args, outerTargs, someCaller, someCallee ) :: Nil
437
+ mkCallInfoWithContext (TermRef .withFixedSym(thisTpePropagated, targetMethod.name, targetMethod), targs, args, outerTargs) :: Nil
434
438
435
439
// super call in a trait
436
440
case t if calleeSymbol.is(SuperAccessor ) =>
@@ -452,7 +456,7 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
452
456
if (s.nonEmpty) {
453
457
val parentMethod = ResolveSuper .rebindSuper(x.tp.widenDealias.classSymbol, calleeSymbol).asTerm
454
458
// todo: outerTargs are here defined in terms of location of the subclass. Is this correct?
455
- CallInfoWithContext (TermRef .withFixedSym(t, parentMethod.name, parentMethod), targs, args, outerTargs, someCaller, someCallee ) :: Nil
459
+ mkCallInfoWithContext (TermRef .withFixedSym(t, parentMethod.name, parentMethod), targs, args, outerTargs) :: Nil
456
460
457
461
} else Nil
458
462
}
@@ -461,14 +465,16 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
461
465
val dropUntil = thisType.tref.classSymbol
462
466
var currentThis = caller.call.normalizedPrefix
463
467
var currentOwner = caller.call.termSymbol.owner
464
- while ((currentOwner ne dropUntil) && (currentThis ne NoType )) {
465
- if (! currentOwner.is(Method ))
466
- currentThis = currentThis.normalizedPrefix
467
- currentOwner = currentOwner.owner.enclosingClass
468
+ if (! dropUntil.is(Trait )) {
469
+ while ((currentOwner ne dropUntil) && (currentThis ne NoType )) {
470
+ if (! currentOwner.is(Method ))
471
+ currentThis = currentThis.normalizedPrefix
472
+ currentOwner = currentOwner.owner.enclosingClass
473
+ }
468
474
}
469
475
if (currentThis.derivesFrom(thisType.cls)) {
470
476
if (calleeSymbol.is(Private )) {
471
- CallInfoWithContext (TermRef .withFixedSym(currentThis, calleeSymbol.name, calleeSymbol), targs, args, outerTargs, someCaller, someCallee ) :: Nil
477
+ mkCallInfoWithContext (TermRef .withFixedSym(currentThis, calleeSymbol.name, calleeSymbol), targs, args, outerTargs) :: Nil
472
478
} else {
473
479
val fullThisType = AndType .apply(currentThis, thisType.tref)
474
480
dispatchCalls(propagateTargs(fullThisType))
@@ -548,60 +554,69 @@ class CallGraphBuilder(collectedSummaries: Map[Symbol, MethodSummary], mode: Int
548
554
if (defn.isPrimitiveClass(argType.classSymbol) || isJavaClass(argType.widenDealias.classSymbol)) {
549
555
Set .empty
550
556
} else {
551
- def potentialCall (decl : Symbol ) = {
552
- def paramTypes = decl.info.paramTypess.flatten
553
- val call = new TermRefWithFixedSym (argType, decl.name.asTermName, decl.asTerm)
554
- val targs = call.widenDealias match {
555
- case call : PolyType =>
556
- def erasedBounds (tp : TypeBounds ): Type = tp.hi match {
557
- case RefinedType (parent, refinedName, refinedInfo : TypeBounds ) =>
558
- RefinedType (parent, refinedName, erasedBounds(refinedInfo))
559
- case t => t
560
- }
561
- call.paramBounds.map(erasedBounds)
557
+ def potentialCall (decl : Symbol ): Option [CallInfo ] = {
558
+ if (! decl.owner.is(JavaDefined ) && decl.isTerm && ! decl.isConstructor && decl.name != nme.COMPANION_MODULE_METHOD &&
559
+ decl.name != nme.isInstanceOf_ && decl.name != nme.asInstanceOf_ && decl.name != nme.synchronized_ && decl.name != nme.getClass_) {
560
+ None
561
+ } else {
562
+ def paramTypes = decl.info.paramTypess.flatten
562
563
563
- case _ => Nil
564
- }
564
+ val call = new TermRefWithFixedSym (argType, decl.name.asTermName, decl.asTerm)
565
+ val targs = call.widenDealias match {
566
+ case call : PolyType =>
567
+ def erasedBounds (tp : TypeBounds ): Type = tp.hi match {
568
+ case RefinedType (parent, refinedName, refinedInfo : TypeBounds ) =>
569
+ RefinedType (parent, refinedName, erasedBounds(refinedInfo))
570
+ case t => t
571
+ }
565
572
566
- def isDefinedInJavaClass (sym : Symbol ) =
567
- sym.owner == defn.AnyClass || sym.owner.is(JavaDefined )
573
+ call.paramBounds.map(erasedBounds)
568
574
569
- val definedInJavaClass : Boolean =
570
- isDefinedInJavaClass(decl) || decl.allOverriddenSymbols.exists(isDefinedInJavaClass)
575
+ case _ => Nil
576
+ }
571
577
572
- argType match {
573
- case argType : PreciseType =>
574
- if (! definedInJavaClass) Nil
575
- else List (CallInfo (call, targs, paramTypes))
578
+ def isDefinedInJavaClass (sym : Symbol ) =
579
+ sym.owner == defn.AnyClass || sym.owner.is(JavaDefined )
576
580
577
- case _ =>
578
- val argTypeWiden = argType.widenDealias
579
- lazy val sym = argTypeWiden.classSymbol.requiredMethod(decl.name, paramTypes)
580
- if (! argTypeWiden.member(decl.name).exists || ! definedInJavaClass || (sym.isEffectivelyFinal && isDefinedInJavaClass(decl))) Nil
581
- else List (CallInfo (TermRef (argType, sym), targs, paramTypes))
581
+ val definedInJavaClass : Boolean =
582
+ isDefinedInJavaClass(decl) || decl.allOverriddenSymbols.exists(isDefinedInJavaClass)
582
583
584
+ argType match {
585
+ case argType : PreciseType =>
586
+ if (! definedInJavaClass) None
587
+ else Some (CallInfo (call, targs, paramTypes))
588
+
589
+ case _ =>
590
+ val argTypeWiden = argType.widenDealias
591
+ lazy val sym = argTypeWiden.classSymbol.requiredMethod(decl.name, paramTypes)
592
+ if (! argTypeWiden.member(decl.name).exists || ! definedInJavaClass || (sym.isEffectivelyFinal && isDefinedInJavaClass(decl))) None
593
+ else Some (CallInfo (TermRef (argType, sym), targs, paramTypes))
594
+
595
+ }
583
596
}
584
597
}
585
598
586
- for {
587
- decl <- allDecls(argType)
588
- if decl.isTerm && ! decl.isConstructor && decl.name != nme.COMPANION_MODULE_METHOD
589
- if decl.name != nme.isInstanceOf_ && decl.name != nme.asInstanceOf_ && decl.name != nme.synchronized_
590
- callInfo <- potentialCall(decl)
591
- } yield callInfo
599
+ allDecls(argType).flatMap(potentialCall)
592
600
}
593
601
}
594
602
595
- // FIXME java method could potentially call this.xyz()
596
- // addAllPotentialCallsFor(method.call.normalizedPrefix)
603
+ def filterParams (params : List [Type ]) = {
604
+ val parents = method.parents
605
+ params.distinct.filter(param => ! parents.exists(_.call.normalizedPrefix == param))
606
+ }
607
+
608
+ val collapsedMethod =
609
+ if (method.isErased) method.parent.get else method
610
+
597
611
for {
598
- rec <- method.argumentsPassed.distinct
612
+ rec <- filterParams(method.call.normalizedPrefix :: method.argumentsPassed.distinct)
613
+ if ! collapsedMethod.addAndHasErasedType(rec.widenDealias)
599
614
potentialCall <- allPotentialCallsFor(rec)
600
- if method .getOutEdges(potentialCall).isEmpty
615
+ if collapsedMethod .getOutEdges(potentialCall).isEmpty
601
616
} {
602
- val nw = instantiateCallSite(method , rec, potentialCall, instantiatedTypes)
617
+ val nw = instantiateCallSite(collapsedMethod , rec, potentialCall, instantiatedTypes, isErased = true )
603
618
reachableMethods ++= nw
604
- method .addOutEdges(potentialCall, nw)
619
+ collapsedMethod .addOutEdges(potentialCall, nw)
605
620
}
606
621
}
607
622
0 commit comments