@@ -9,6 +9,24 @@ import csharp
99 */
1010module Ssa {
1111 private import internal.SsaImpl as SsaImpl
12+ private import semmle.code.csharp.internal.Location
13+
14+ pragma [ nomagic]
15+ private predicate assignableDefinitionLocalScopeVariable (
16+ AssignableDefinition ad , LocalScopeVariable v , Callable c
17+ ) {
18+ ad .getTarget ( ) = v and
19+ ad .getEnclosingCallable ( ) = c
20+ }
21+
22+ pragma [ nomagic]
23+ private predicate localScopeSourceVariable (
24+ SourceVariables:: LocalScopeSourceVariable sv , LocalScopeVariable v , Callable c1 , Callable c2
25+ ) {
26+ sv .getAssignable ( ) = v and
27+ sv .getEnclosingCallable ( ) = c1 and
28+ v .getCallable ( ) = c2
29+ }
1230
1331 /**
1432 * A variable that can be SSA converted.
@@ -34,11 +52,10 @@ module Ssa {
3452 or
3553 // Local variable declaration without initializer
3654 not exists ( result .getTargetAccess ( ) ) and
37- this =
38- any ( SourceVariables:: LocalScopeSourceVariable v |
39- result .getTarget ( ) = v .getAssignable ( ) and
40- result .getEnclosingCallable ( ) = v .getEnclosingCallable ( )
41- )
55+ exists ( LocalScopeVariable v , Callable c |
56+ assignableDefinitionLocalScopeVariable ( result , v , c ) and
57+ localScopeSourceVariable ( this , v , c , _)
58+ )
4259 }
4360
4461 /**
@@ -507,9 +524,7 @@ module Ssa {
507524 override Element getElement ( ) { result = ad .getElement ( ) }
508525
509526 override string toString ( ) {
510- if this .getADefinition ( ) instanceof AssignableDefinitions:: ImplicitParameterDefinition
511- then result = SsaImpl:: getToStringPrefix ( this ) + "SSA param(" + this .getSourceVariable ( ) + ")"
512- else result = SsaImpl:: getToStringPrefix ( this ) + "SSA def(" + this .getSourceVariable ( ) + ")"
527+ result = SsaImpl:: getToStringPrefix ( this ) + "SSA def(" + this .getSourceVariable ( ) + ")"
513528 }
514529
515530 override Location getLocation ( ) { result = ad .getLocation ( ) }
@@ -537,7 +552,7 @@ module Ssa {
537552
538553 /**
539554 * An SSA definition representing the implicit initialization of a variable
540- * at the beginning of a callable. Either the variable is a local scope variable
555+ * at the beginning of a callable. Either a parameter, a local scope variable
541556 * captured by the callable, or a field or property accessed inside the callable.
542557 */
543558 class ImplicitEntryDefinition extends ImplicitDefinition {
@@ -551,7 +566,7 @@ module Ssa {
551566 /** Gets the callable that this entry definition belongs to. */
552567 final Callable getCallable ( ) { result = this .getBasicBlock ( ) .getCallable ( ) }
553568
554- override Callable getElement ( ) { result = this .getCallable ( ) }
569+ override Element getElement ( ) { result = this .getCallable ( ) }
555570
556571 override string toString ( ) {
557572 if this .getSourceVariable ( ) .getAssignable ( ) instanceof LocalScopeVariable
@@ -566,6 +581,54 @@ module Ssa {
566581 override Location getLocation ( ) { result = this .getCallable ( ) .getLocation ( ) }
567582 }
568583
584+ private module NearestLocationInput implements NearestLocationInputSig {
585+ class C = ImplicitParameterDefinition ;
586+
587+ predicate relevantLocations ( ImplicitParameterDefinition def , Location l1 , Location l2 ) {
588+ not def .getBasicBlock ( ) instanceof ControlFlow:: BasicBlocks:: EntryBlock and
589+ l1 = def .getParameter ( ) .getALocation ( ) and
590+ l2 = def .getBasicBlock ( ) .getLocation ( )
591+ }
592+ }
593+
594+ pragma [ nomagic]
595+ private predicate implicitEntryDef ( ImplicitEntryDefinition def , SourceVariable v , Callable c ) {
596+ v = def .getSourceVariable ( ) and
597+ c = def .getCallable ( )
598+ }
599+
600+ /**
601+ * An SSA definition representing the implicit initialization of a parameter
602+ * at the beginning of a callable.
603+ */
604+ class ImplicitParameterDefinition extends ImplicitEntryDefinition {
605+ private Parameter p ;
606+
607+ ImplicitParameterDefinition ( ) {
608+ exists ( SourceVariable sv , Callable c |
609+ implicitEntryDef ( this , sv , c ) and
610+ localScopeSourceVariable ( sv , p , _, c )
611+ )
612+ }
613+
614+ /** Gets the parameter that this entry definition represents. */
615+ Parameter getParameter ( ) { result = p }
616+
617+ override Element getElement ( ) { result = this .getParameter ( ) }
618+
619+ override string toString ( ) {
620+ result = SsaImpl:: getToStringPrefix ( this ) + "SSA param(" + this .getParameter ( ) + ")"
621+ }
622+
623+ override Location getLocation ( ) {
624+ not NearestLocation< NearestLocationInput > :: nearestLocation ( this , _, _) and
625+ result = p .getLocation ( )
626+ or
627+ // multi-bodied method: use matching parameter location
628+ NearestLocation< NearestLocationInput > :: nearestLocation ( this , result , _)
629+ }
630+ }
631+
569632 /**
570633 * An SSA definition representing the potential definition of a variable
571634 * via a call.
0 commit comments