@@ -304,33 +304,80 @@ private module GuardsInput implements
304304 pragma [ inline]
305305 predicate parameterMatch ( ParameterPosition ppos , ArgumentPosition apos ) { ppos = apos }
306306
307- final private class FinalFunction = G:: Function ;
307+ private newtype TNonOverridableMethod =
308+ TMethod ( G:: Function function , int resultIndex ) {
309+ exists ( function .getFuncDecl ( ) ) and
310+ (
311+ function .getNumResult ( ) = 0 and resultIndex = - 1
312+ or
313+ resultIndex in [ 0 .. function .getNumResult ( ) - 1 ]
314+ )
315+ }
308316
309317 /**
310- * A declared function or concrete method.
318+ * A result of a declared function or concrete method, or its normal
319+ * completion when it has no results.
311320 *
312321 * Calls are restricted separately to calls whose syntactic target is this
313322 * function or method, excluding interface dispatch.
314323 */
315- class NonOverridableMethod extends FinalFunction {
316- NonOverridableMethod ( ) {
317- exists ( super .getFuncDecl ( ) ) and
318- super .getNumResult ( ) <= 1
324+ class NonOverridableMethod extends TNonOverridableMethod {
325+ G:: Function getFunction ( ) { this = TMethod ( result , _) }
326+
327+ int getResultIndex ( ) { this = TMethod ( _, result ) }
328+
329+ string toString ( ) {
330+ result = this .getFunction ( ) .toString ( ) + " result " + this .getResultIndex ( ) .toString ( )
319331 }
320332
321- Parameter getParameter ( ParameterPosition ppos ) { result = super .getParameter ( ppos ) }
333+ int getNumParameter ( ) { result = this .getFunction ( ) .getNumParameter ( ) }
334+
335+ Parameter getParameter ( ParameterPosition ppos ) {
336+ result = this .getFunction ( ) .getParameter ( ppos )
337+ }
338+
339+ /**
340+ * Holds if every return maps one expression to each result position.
341+ *
342+ * Otherwise, the shared wrapper analysis would treat a partial set of
343+ * return expressions as exhaustive.
344+ */
345+ private predicate hasOnlyPositionMappedReturns ( ) {
346+ forall ( G:: ReturnStmt ret | ret .getEnclosingFunction ( ) = this .getFunction ( ) .getFuncDecl ( ) |
347+ ret .getNumExpr ( ) = this .getFunction ( ) .getNumResult ( )
348+ )
349+ }
322350
323351 /** Gets an expression being returned by this function. */
324352 Expr getAReturnExpr ( ) {
325353 exists ( G:: ReturnStmt ret |
326- ret .getEnclosingFunction ( ) = super .getFuncDecl ( ) and
327- result = ret .getExpr ( )
354+ this .getResultIndex ( ) >= 0 and
355+ this .hasOnlyPositionMappedReturns ( ) and
356+ ret .getEnclosingFunction ( ) = this .getFunction ( ) .getFuncDecl ( ) and
357+ result = ret .getExpr ( this .getResultIndex ( ) )
328358 )
329359 }
330360 }
331361
332- private predicate nonOverridableCall ( G:: CallExpr call , NonOverridableMethod m ) {
333- call .getTarget ( ) = m
362+ private predicate extractedCallResult ( Expr use , G:: CallExpr call , int resultIndex ) {
363+ exists ( GoSsa:: SsaDefinition def , IR:: ExtractTupleElementInstruction extract |
364+ use = def .getVariable ( ) .getAUse ( ) .( IR:: EvalInstruction ) .getExpr ( ) and
365+ def .( GoSsa:: SsaExplicitDefinition ) .getInstruction ( ) = extract and
366+ extract .extractsElement ( IR:: evalExprInstruction ( call ) , resultIndex )
367+ )
368+ }
369+
370+ private predicate nonOverridableCall (
371+ Expr resultExpr , G:: CallExpr call , NonOverridableMethod method
372+ ) {
373+ call .getTarget ( ) = method .getFunction ( ) and
374+ (
375+ method .getFunction ( ) .getNumResult ( ) <= 1 and
376+ resultExpr = call
377+ or
378+ method .getFunction ( ) .getNumResult ( ) > 1 and
379+ extractedCallResult ( resultExpr , call , method .getResultIndex ( ) )
380+ )
334381 }
335382
336383 private predicate hasExplicitReceiverArgument ( G:: CallExpr call ) {
@@ -352,28 +399,32 @@ private module GuardsInput implements
352399 )
353400 }
354401
355- class NonOverridableMethodCall extends Expr instanceof G:: CallExpr {
356- NonOverridableMethodCall ( ) { nonOverridableCall ( this , _) }
402+ class NonOverridableMethodCall extends Expr {
403+ NonOverridableMethodCall ( ) { nonOverridableCall ( this , _, _) }
404+
405+ private G:: CallExpr getCall ( ) { nonOverridableCall ( this , result , _) }
357406
358- NonOverridableMethod getMethod ( ) { nonOverridableCall ( this , result ) }
407+ NonOverridableMethod getMethod ( ) { nonOverridableCall ( this , _ , result ) }
359408
360409 Expr getArgument ( ArgumentPosition apos ) {
361- (
362- not hasExplicitReceiverArgument ( this ) and
410+ exists ( G:: CallExpr call | call = this .getCall ( ) |
363411 (
364- apos = - 1 and
365- result = getDirectReceiverArgument ( this , this .getMethod ( ) )
412+ not hasExplicitReceiverArgument ( call ) and
413+ (
414+ apos = - 1 and
415+ result = getDirectReceiverArgument ( call , this .getMethod ( ) )
416+ or
417+ apos != - 1 and
418+ result = call .getArgument ( apos )
419+ )
366420 or
367- apos != - 1 and
368- result = super .getArgument ( apos )
421+ hasExplicitReceiverArgument ( call ) and
422+ result = call .getArgument ( apos + 1 )
423+ ) and
424+ not (
425+ call .hasImplicitVarargs ( ) and
426+ apos = this .getMethod ( ) .getNumParameter ( ) - 1
369427 )
370- or
371- hasExplicitReceiverArgument ( this ) and
372- result = super .getArgument ( apos + 1 )
373- ) and
374- not (
375- super .hasImplicitVarargs ( ) and
376- apos = this .getMethod ( ) .getNumParameter ( ) - 1
377428 )
378429 }
379430 }
@@ -413,8 +464,8 @@ private module LogicInput implements GuardsImpl::LogicInputSig {
413464
414465 predicate implicitReturnDefinition ( GuardsInput:: NonOverridableMethod method , SsaDefinition def ) {
415466 exists ( IR:: ReadResultInstruction read |
416- method .getNumResult ( ) = 1 and
417- read .reads ( method .getResult ( 0 ) ) and
467+ method .getResultIndex ( ) >= 0 and
468+ read .reads ( method .getFunction ( ) . getResult ( method . getResultIndex ( ) ) ) and
418469 def .getVariable ( ) .getAUse ( ) = read
419470 )
420471 }
0 commit comments