@@ -28,6 +28,19 @@ module VirtualDispatch {
2828 not result .hasName ( "IUnknown" )
2929 }
3030
31+ /**
32+ * Helper predicate for `getAViableTarget`, which computes the viable targets for
33+ * virtual calls based on the qualifier type.
34+ */
35+ private Function getAViableVirtualCallTarget ( Class qualifierType , MemberFunction staticTarget ) {
36+ exists ( Class qualifierSubType |
37+ result = getAPossibleImplementation ( staticTarget ) and
38+ qualifierType = qualifierSubType .getABaseClass * ( ) and
39+ mayInherit ( qualifierSubType , result ) and
40+ not cannotInherit ( qualifierSubType , result )
41+ )
42+ }
43+
3144 /**
3245 * Gets a viable target for the given function call.
3346 *
@@ -42,18 +55,9 @@ module VirtualDispatch {
4255 * If `c` is not a virtual call, the result will be `c.getTarget()`.
4356 */
4457 Function getAViableTarget ( Call c ) {
45- exists ( Function staticTarget | staticTarget = c .getTarget ( ) |
46- if c .( FunctionCall ) .isVirtual ( ) and staticTarget instanceof MemberFunction
47- then
48- exists ( Class qualifierType , Class qualifierSubType |
49- result = getAPossibleImplementation ( staticTarget ) and
50- qualifierType = getCallQualifierType ( c ) and
51- qualifierType = qualifierSubType .getABaseClass * ( ) and
52- mayInherit ( qualifierSubType , result ) and
53- not cannotInherit ( qualifierSubType , result )
54- )
55- else result = staticTarget
56- )
58+ if c .( FunctionCall ) .isVirtual ( ) and c .getTarget ( ) instanceof MemberFunction
59+ then result = getAViableVirtualCallTarget ( getCallQualifierType ( c ) , c .getTarget ( ) )
60+ else result = c .getTarget ( )
5761 }
5862
5963 /** Holds if `f` is declared in `c` or a transitive base class of `c`. */
0 commit comments