@@ -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+ resultIndex in [ - 1 .. function .getNumResult ( ) - 1 ]
311+ }
308312
309313 /**
310- * A declared function or concrete method.
314+ * A result of a declared function or concrete method, or its normal completion .
311315 *
312316 * Calls are restricted separately to calls whose syntactic target is this
313317 * function or method, excluding interface dispatch.
314318 */
315- class NonOverridableMethod extends FinalFunction {
316- NonOverridableMethod ( ) {
317- exists ( super .getFuncDecl ( ) ) and
318- super .getNumResult ( ) <= 1
319+ class NonOverridableMethod extends TNonOverridableMethod {
320+ G:: Function getFunction ( ) { this = TMethod ( result , _) }
321+
322+ int getResultIndex ( ) { this = TMethod ( _, result ) }
323+
324+ string toString ( ) {
325+ result = this .getFunction ( ) .toString ( ) + " result " + this .getResultIndex ( ) .toString ( )
319326 }
320327
321- Parameter getParameter ( ParameterPosition ppos ) { result = super .getParameter ( ppos ) }
328+ int getNumParameter ( ) { result = this .getFunction ( ) .getNumParameter ( ) }
329+
330+ Parameter getParameter ( ParameterPosition ppos ) {
331+ result = this .getFunction ( ) .getParameter ( ppos )
332+ }
333+
334+ /**
335+ * Holds if every return maps one expression to each result position.
336+ *
337+ * Otherwise, the shared wrapper analysis would treat a partial set of
338+ * return expressions as exhaustive.
339+ */
340+ private predicate hasOnlyPositionMappedReturns ( ) {
341+ forall ( G:: ReturnStmt ret | ret .getEnclosingFunction ( ) = this .getFunction ( ) .getFuncDecl ( ) |
342+ ret .getNumExpr ( ) = this .getFunction ( ) .getNumResult ( )
343+ )
344+ }
322345
323346 /** Gets an expression being returned by this function. */
324347 Expr getAReturnExpr ( ) {
325348 exists ( G:: ReturnStmt ret |
326- ret .getEnclosingFunction ( ) = super .getFuncDecl ( ) and
327- result = ret .getExpr ( )
349+ this .getResultIndex ( ) >= 0 and
350+ this .hasOnlyPositionMappedReturns ( ) and
351+ ret .getEnclosingFunction ( ) = this .getFunction ( ) .getFuncDecl ( ) and
352+ result = ret .getExpr ( this .getResultIndex ( ) )
328353 )
329354 }
330355 }
331356
332- private predicate nonOverridableCall ( G:: CallExpr call , NonOverridableMethod m ) {
333- call .getTarget ( ) = m
357+ private predicate extractedCallResult ( Expr use , G:: CallExpr call , int resultIndex ) {
358+ exists ( GoSsa:: SsaDefinition def , IR:: ExtractTupleElementInstruction extract |
359+ use = def .getVariable ( ) .getAUse ( ) .( IR:: EvalInstruction ) .getExpr ( ) and
360+ def .( GoSsa:: SsaExplicitDefinition ) .getInstruction ( ) = extract and
361+ extract .extractsElement ( IR:: evalExprInstruction ( call ) , resultIndex )
362+ )
363+ }
364+
365+ private predicate nonOverridableCall (
366+ Expr resultExpr , G:: CallExpr call , NonOverridableMethod method
367+ ) {
368+ call .getTarget ( ) = method .getFunction ( ) and
369+ (
370+ method .getResultIndex ( ) = - 1 and
371+ resultExpr = call
372+ or
373+ method .getResultIndex ( ) = 0 and
374+ method .getFunction ( ) .getNumResult ( ) = 1 and
375+ resultExpr = call
376+ or
377+ method .getResultIndex ( ) >= 0 and
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 )
412+ not hasExplicitReceiverArgument ( call ) and
413+ (
414+ apos = - 1 and
415+ result = getDirectReceiverArgument ( call )
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 = call .getTarget ( ) .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 .getTarget ( ) .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