@@ -183,62 +183,24 @@ class AssignableWrite extends AssignableAccess {
183183 }
184184}
185185
186- private cached module AssignableDefinitionImpl {
187- cached newtype TAssignableDefinition =
188- TAssignmentDefinition ( Assignment a ) {
189- not a .getLValue ( ) instanceof TupleExpr
190- }
191- or
192- TTupleAssignmentDefinition ( AssignExpr ae , Expr leaf ) {
193- exists ( TupleExpr te |
194- ae .getLValue ( ) = te and
195- te .getAnArgument + ( ) = leaf and
196- // `leaf` is either an assignable access or a local variable declaration
197- not leaf instanceof TupleExpr
198- )
199- }
200- or
201- TOutRefDefinition ( AssignableAccess aa ) {
202- aa .isOutArgument ( )
203- or
204- isRelevantRefCall ( _, aa )
205- }
206- or
207- TMutationDefinition ( MutatorOperation mo )
208- or
209- TLocalVariableDefinition ( LocalVariableDeclExpr lvde ) {
210- not lvde .hasInitializer ( ) and
211- not exists ( getTupleSource ( TTupleAssignmentDefinition ( _, lvde ) ) ) and
212- not lvde = any ( IsPatternExpr ipe ) .getVariableDeclExpr ( ) and
213- not lvde = any ( TypeCase tc ) .getVariableDeclExpr ( )
214- }
215- or
216- TImplicitParameterDefinition ( Parameter p ) {
217- exists ( Callable c |
218- p = c .getAParameter ( ) |
219- c .hasBody ( ) or
220- c .( Constructor ) .hasInitializer ( )
221- )
222- }
223- or
224- TAddressOfDefinition ( AddressOfExpr aoe )
225- or
226- TIsPatternDefinition ( IsPatternExpr ipe )
227- or
228- TTypeCasePatternDefinition ( TypeCase tc )
229- or
230- TInitializer ( Assignable a , Expr e ) {
231- e = a .( Field ) .getInitializer ( ) or
232- e = a .( Property ) .getInitializer ( )
233- }
186+ /** INTERNAL: Do not use. */
187+ module AssignableInternal {
188+ private predicate tupleAssignmentDefinition ( AssignExpr ae , Expr leaf ) {
189+ exists ( TupleExpr te |
190+ ae .getLValue ( ) = te and
191+ te .getAnArgument + ( ) = leaf and
192+ // `leaf` is either an assignable access or a local variable declaration
193+ not leaf instanceof TupleExpr
194+ )
195+ }
234196
235197 /**
236198 * Holds if `ae` is a tuple assignment, and `left` is a sub expression
237199 * on the left-hand side of the assignment, with corresponding
238200 * right-hand side `right`.
239201 */
240202 private predicate tupleAssignmentPair ( AssignExpr ae , Expr left , Expr right ) {
241- exists ( TTupleAssignmentDefinition ( ae , _) ) and
203+ tupleAssignmentDefinition ( ae , _) and
242204 left = ae .getLValue ( ) and
243205 right = ae .getRValue ( )
244206 or
@@ -249,16 +211,6 @@ private cached module AssignableDefinitionImpl {
249211 )
250212 }
251213
252- /**
253- * Gets the source expression assigned in tuple definition `def`, if any.
254- */
255- cached Expr getTupleSource ( TTupleAssignmentDefinition def ) {
256- exists ( AssignExpr ae , Expr leaf |
257- def = TTupleAssignmentDefinition ( ae , leaf ) |
258- tupleAssignmentPair ( ae , leaf , result )
259- )
260- }
261-
262214 /**
263215 * Holds if the `ref` assignment to `aa` via call `c` is relevant.
264216 */
@@ -341,19 +293,6 @@ private cached module AssignableDefinitionImpl {
341293 not result = TImplicitParameterDefinition ( _)
342294 }
343295
344- /**
345- * Holds if the `ref` assignment to `aa` via call `c` is uncertain.
346- */
347- cached predicate isUncertainRefCall ( Call c , AssignableAccess aa ) {
348- isRelevantRefCall ( c , aa )
349- and
350- exists ( ControlFlow:: BasicBlock bb , Parameter p |
351- isAnalyzableRefCall ( c , aa , p ) |
352- parameterReachesWithoutDef ( p , bb ) and
353- bb .getLastNode ( ) = p .getCallable ( ) .getExitPoint ( )
354- )
355- }
356-
357296 /**
358297 * Holds if `p` is an analyzable `ref` parameter and there is a path from the
359298 * entry point of `p`'s callable to basic block `bb` without passing through
@@ -378,51 +317,137 @@ private cached module AssignableDefinitionImpl {
378317 bb .getANode ( ) = getAnAnalyzableRefDef ( _, _, p ) .getAControlFlowNode ( )
379318 }
380319
381- // Not defined by dispatch in order to avoid too conservative negative recursion error
382- cached Assignable getTarget ( AssignableDefinition def ) {
383- result = def .getTargetAccess ( ) .getTarget ( )
384- or
385- exists ( Expr leaf |
386- def = TTupleAssignmentDefinition ( _, leaf ) |
387- result = leaf .( LocalVariableDeclExpr ) .getVariable ( )
388- )
389- or
390- def = any ( AssignableDefinitions:: ImplicitParameterDefinition p |
391- result = p .getParameter ( )
392- )
393- or
394- def = any ( AssignableDefinitions:: LocalVariableDefinition decl |
395- result = decl .getDeclaration ( ) .getVariable ( )
396- )
397- or
398- def = any ( AssignableDefinitions:: IsPatternDefinition is |
399- result = is .getDeclaration ( ) .getVariable ( )
400- )
401- or
402- def = any ( AssignableDefinitions:: TypeCasePatternDefinition case |
403- result = case .getDeclaration ( ) .getVariable ( )
404- )
405- or
406- def = any ( AssignableDefinitions:: InitializerDefinition init |
407- result = init .getAssignable ( )
408- )
409- }
320+ private cached module Cached {
321+ cached newtype TAssignableDefinition =
322+ TAssignmentDefinition ( Assignment a ) {
323+ not a .getLValue ( ) instanceof TupleExpr
324+ }
325+ or
326+ TTupleAssignmentDefinition ( AssignExpr ae , Expr leaf ) {
327+ tupleAssignmentDefinition ( ae , leaf )
328+ }
329+ or
330+ TOutRefDefinition ( AssignableAccess aa ) {
331+ aa .isOutArgument ( )
332+ or
333+ isRelevantRefCall ( _, aa )
334+ }
335+ or
336+ TMutationDefinition ( MutatorOperation mo )
337+ or
338+ TLocalVariableDefinition ( LocalVariableDeclExpr lvde ) {
339+ not lvde .hasInitializer ( ) and
340+ not exists ( getTupleSource ( TTupleAssignmentDefinition ( _, lvde ) ) ) and
341+ not lvde = any ( IsPatternExpr ipe ) .getVariableDeclExpr ( ) and
342+ not lvde = any ( TypeCase tc ) .getVariableDeclExpr ( )
343+ }
344+ or
345+ TImplicitParameterDefinition ( Parameter p ) {
346+ exists ( Callable c |
347+ p = c .getAParameter ( ) |
348+ c .hasBody ( ) or
349+ c .( Constructor ) .hasInitializer ( )
350+ )
351+ }
352+ or
353+ TAddressOfDefinition ( AddressOfExpr aoe )
354+ or
355+ TIsPatternDefinition ( IsPatternExpr ipe )
356+ or
357+ TTypeCasePatternDefinition ( TypeCase tc )
358+ or
359+ TInitializer ( Assignable a , Expr e ) {
360+ e = a .( Field ) .getInitializer ( ) or
361+ e = a .( Property ) .getInitializer ( )
362+ }
410363
411- // Not defined by dispatch in order to avoid too conservative negative recursion error
412- cached AssignableAccess getTargetAccess ( AssignableDefinition def ) {
413- def = TAssignmentDefinition ( any ( Assignment a | a .getLValue ( ) = result ) )
414- or
415- def = TTupleAssignmentDefinition ( _, result )
416- or
417- def = TOutRefDefinition ( result )
418- or
419- def = TMutationDefinition ( any ( MutatorOperation mo | mo .getOperand ( ) = result ) )
420- or
421- def = TAddressOfDefinition ( any ( AddressOfExpr aoe | aoe .getOperand ( ) = result ) )
364+ /**
365+ * Gets the source expression assigned in tuple definition `def`, if any.
366+ */
367+ cached Expr getTupleSource ( TTupleAssignmentDefinition def ) {
368+ exists ( AssignExpr ae , Expr leaf |
369+ def = TTupleAssignmentDefinition ( ae , leaf ) |
370+ tupleAssignmentPair ( ae , leaf , result )
371+ )
372+ }
373+
374+ /**
375+ * Holds if the `ref` assignment to `aa` via call `c` is uncertain.
376+ */
377+ cached predicate isUncertainRefCall ( Call c , AssignableAccess aa ) {
378+ isRelevantRefCall ( c , aa )
379+ and
380+ exists ( ControlFlow:: BasicBlock bb , Parameter p |
381+ isAnalyzableRefCall ( c , aa , p ) |
382+ parameterReachesWithoutDef ( p , bb ) and
383+ bb .getLastNode ( ) = p .getCallable ( ) .getExitPoint ( )
384+ )
385+ }
386+
387+ // Not defined by dispatch in order to avoid too conservative negative recursion error
388+ cached Assignable getTarget ( AssignableDefinition def ) {
389+ result = def .getTargetAccess ( ) .getTarget ( )
390+ or
391+ exists ( Expr leaf |
392+ def = TTupleAssignmentDefinition ( _, leaf ) |
393+ result = leaf .( LocalVariableDeclExpr ) .getVariable ( )
394+ )
395+ or
396+ def = any ( AssignableDefinitions:: ImplicitParameterDefinition p |
397+ result = p .getParameter ( )
398+ )
399+ or
400+ def = any ( AssignableDefinitions:: LocalVariableDefinition decl |
401+ result = decl .getDeclaration ( ) .getVariable ( )
402+ )
403+ or
404+ def = any ( AssignableDefinitions:: IsPatternDefinition is |
405+ result = is .getDeclaration ( ) .getVariable ( )
406+ )
407+ or
408+ def = any ( AssignableDefinitions:: TypeCasePatternDefinition case |
409+ result = case .getDeclaration ( ) .getVariable ( )
410+ )
411+ or
412+ def = any ( AssignableDefinitions:: InitializerDefinition init |
413+ result = init .getAssignable ( )
414+ )
415+ }
416+
417+ // Not defined by dispatch in order to avoid too conservative negative recursion error
418+ cached AssignableAccess getTargetAccess ( AssignableDefinition def ) {
419+ def = TAssignmentDefinition ( any ( Assignment a | a .getLValue ( ) = result ) )
420+ or
421+ def = TTupleAssignmentDefinition ( _, result )
422+ or
423+ def = TOutRefDefinition ( result )
424+ or
425+ def = TMutationDefinition ( any ( MutatorOperation mo | mo .getOperand ( ) = result ) )
426+ or
427+ def = TAddressOfDefinition ( any ( AddressOfExpr aoe | aoe .getOperand ( ) = result ) )
428+ }
429+
430+ /**
431+ * Gets the argument for the implicit `value` parameter in the accessor call
432+ * `ac`, if any.
433+ */
434+ cached Expr getAccessorCallValueArgument ( AccessorCall ac ) {
435+ exists ( AssignExpr ae |
436+ tupleAssignmentDefinition ( ae , ac ) |
437+ tupleAssignmentPair ( ae , ac , result )
438+ )
439+ or
440+ exists ( Assignment a |
441+ ac = a .getLValue ( ) |
442+ result = a .getRValue ( ) and
443+ not a .( AssignOperation ) .hasExpandedAssignment ( )
444+ )
445+ }
422446 }
447+ import Cached
423448}
424449
425- private import AssignableDefinitionImpl
450+ private import AssignableInternal
426451
427452/**
428453 * An assignable definition.
0 commit comments