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