@@ -130,14 +130,39 @@ private newtype TDefOrUseImpl =
130130 Operand iteratorAddress , BaseSourceVariableInstruction container , int indirectionIndex
131131 ) {
132132 isIteratorUse ( container , iteratorAddress , _, indirectionIndex )
133+ } or
134+ TFinalParameterUse ( Parameter p , int indirectionIndex ) {
135+ // Avoid creating parameter nodes if there is no definitions of the variable other than the initializaion.
136+ exists ( SsaInternals0:: Def def |
137+ def .getSourceVariable ( ) .getBaseVariable ( ) .( BaseIRVariable ) .getIRVariable ( ) .getAst ( ) = p and
138+ not def .getValue ( ) .asInstruction ( ) instanceof InitializeParameterInstruction
139+ ) and
140+ // If the type is modifiable
141+ exists ( CppType cppType |
142+ cppType .hasUnspecifiedType ( p .getUnspecifiedType ( ) , _) and
143+ isModifiableAt ( cppType , indirectionIndex + 1 )
144+ ) and
145+ (
146+ exists ( Indirection indirection |
147+ indirection .getType ( ) = p .getUnspecifiedType ( ) and
148+ indirectionIndex = [ 1 .. indirection .getNumberOfIndirections ( ) ]
149+ )
150+ or
151+ // Array types don't have indirections. So we need to special case them here.
152+ exists ( Cpp:: ArrayType arrayType , CppType cppType |
153+ arrayType = p .getUnspecifiedType ( ) and
154+ cppType .hasUnspecifiedType ( arrayType , _) and
155+ indirectionIndex = [ 1 .. countIndirectionsForCppType ( cppType ) ]
156+ )
157+ )
133158 }
134159
135160abstract private class DefOrUseImpl extends TDefOrUseImpl {
136161 /** Gets a textual representation of this element. */
137162 abstract string toString ( ) ;
138163
139164 /** Gets the block of this definition or use. */
140- abstract IRBlock getBlock ( ) ;
165+ final IRBlock getBlock ( ) { this . hasIndexInBlock ( result , _ ) }
141166
142167 /** Holds if this definition or use has index `index` in block `block`. */
143168 abstract predicate hasIndexInBlock ( IRBlock block , int index ) ;
@@ -222,8 +247,6 @@ abstract class DefImpl extends DefOrUseImpl {
222247
223248 override string toString ( ) { result = "DefImpl" }
224249
225- override IRBlock getBlock ( ) { result = this .getAddressOperand ( ) .getUse ( ) .getBlock ( ) }
226-
227250 override Cpp:: Location getLocation ( ) { result = this .getAddressOperand ( ) .getUse ( ) .getLocation ( ) }
228251
229252 final override predicate hasIndexInBlock ( IRBlock block , int index ) {
@@ -258,42 +281,55 @@ private class IteratorDef extends DefImpl, TIteratorDef {
258281}
259282
260283abstract class UseImpl extends DefOrUseImpl {
261- Operand operand ;
262284 int ind ;
263285
264286 bindingset [ ind]
265287 UseImpl ( ) { any ( ) }
266288
267- Operand getOperand ( ) { result = operand }
289+ /** Gets the node associated with this use. */
290+ abstract Node getNode ( ) ;
268291
269292 override string toString ( ) { result = "UseImpl" }
270293
271- final override predicate hasIndexInBlock ( IRBlock block , int index ) {
272- operand .getUse ( ) = block .getInstruction ( index )
273- }
294+ /** Gets the indirection index of this use. */
295+ final override int getIndirectionIndex ( ) { result = ind }
274296
275- final override IRBlock getBlock ( ) { result = operand .getUse ( ) .getBlock ( ) }
297+ /** Gets the number of loads that precedence this use. */
298+ abstract int getIndirection ( ) ;
276299
277- final override Cpp:: Location getLocation ( ) { result = operand .getLocation ( ) }
300+ /**
301+ * Holds if this use is guaranteed to read the
302+ * associated variable.
303+ */
304+ abstract predicate isCertain ( ) ;
305+ }
278306
279- override int getIndirectionIndex ( ) { result = ind }
307+ abstract private class OperandBasedUse extends UseImpl {
308+ Operand operand ;
280309
281- abstract int getIndirection ( ) ;
310+ bindingset [ ind]
311+ OperandBasedUse ( ) { any ( ) }
282312
283- abstract predicate isCertain ( ) ;
313+ final override predicate hasIndexInBlock ( IRBlock block , int index ) {
314+ operand .getUse ( ) = block .getInstruction ( index )
315+ }
316+
317+ final override Cpp:: Location getLocation ( ) { result = operand .getLocation ( ) }
284318}
285319
286- private class DirectUse extends UseImpl , TUseImpl {
320+ private class DirectUse extends OperandBasedUse , TUseImpl {
287321 DirectUse ( ) { this = TUseImpl ( operand , ind ) }
288322
289323 override int getIndirection ( ) { isUse ( _, operand , _, result , ind ) }
290324
291325 override BaseSourceVariableInstruction getBase ( ) { isUse ( _, operand , result , _, ind ) }
292326
293327 override predicate isCertain ( ) { isUse ( true , operand , _, _, ind ) }
328+
329+ override Node getNode ( ) { nodeHasOperand ( result , operand , ind ) }
294330}
295331
296- private class IteratorUse extends UseImpl , TIteratorUse {
332+ private class IteratorUse extends OperandBasedUse , TIteratorUse {
297333 BaseSourceVariableInstruction container ;
298334
299335 IteratorUse ( ) { this = TIteratorUse ( operand , container , ind ) }
@@ -303,6 +339,49 @@ private class IteratorUse extends UseImpl, TIteratorUse {
303339 override BaseSourceVariableInstruction getBase ( ) { result = container }
304340
305341 override predicate isCertain ( ) { none ( ) }
342+
343+ override Node getNode ( ) { nodeHasOperand ( result , operand , ind ) }
344+ }
345+
346+ class FinalParameterUse extends UseImpl , TFinalParameterUse {
347+ Parameter p ;
348+
349+ FinalParameterUse ( ) { this = TFinalParameterUse ( p , ind ) }
350+
351+ Parameter getParameter ( ) { result = p }
352+
353+ override Node getNode ( ) {
354+ result .( FinalParameterNode ) .getParameter ( ) = p and
355+ result .( FinalParameterNode ) .getIndirectionIndex ( ) = ind
356+ }
357+
358+ override int getIndirection ( ) { result = ind + 1 }
359+
360+ override predicate isCertain ( ) { any ( ) }
361+
362+ override predicate hasIndexInBlock ( IRBlock block , int index ) {
363+ exists ( ReturnInstruction return |
364+ block .getInstruction ( index ) = return and
365+ return .getEnclosingFunction ( ) = p .getFunction ( )
366+ )
367+ }
368+
369+ override Cpp:: Location getLocation ( ) {
370+ // Parameters can have multiple locations. When there's a unique location we use
371+ // that one, but if multiple locations exist we default to an unknown location.
372+ result = unique( | | p .getLocation ( ) )
373+ or
374+ not exists ( unique( | | p .getLocation ( ) ) ) and
375+ result instanceof UnknownDefaultLocation
376+ }
377+
378+ override BaseSourceVariableInstruction getBase ( ) {
379+ exists ( InitializeParameterInstruction init |
380+ init .getParameter ( ) = p and
381+ // This is always a `VariableAddressInstruction`
382+ result = init .getAnOperand ( ) .getDef ( )
383+ )
384+ }
306385}
307386
308387/**
@@ -331,14 +410,7 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
331410 )
332411}
333412
334- private predicate useToNode ( UseOrPhi use , Node nodeTo ) {
335- exists ( UseImpl useImpl |
336- useImpl = use .asDefOrUse ( ) and
337- nodeHasOperand ( nodeTo , useImpl .getOperand ( ) , useImpl .getIndirectionIndex ( ) )
338- )
339- or
340- nodeTo .( SsaPhiNode ) .getPhiNode ( ) = use .asPhi ( )
341- }
413+ private predicate useToNode ( UseOrPhi use , Node nodeTo ) { nodeTo = use .getNode ( ) }
342414
343415pragma [ noinline]
344416predicate outNodeHasAddressAndIndex (
@@ -609,6 +681,8 @@ class Phi extends TPhi, SsaDefOrUse {
609681 final override Location getLocation ( ) { result = phi .getBasicBlock ( ) .getLocation ( ) }
610682
611683 override string toString ( ) { result = "Phi" }
684+
685+ SsaPhiNode getNode ( ) { result .getPhiNode ( ) = phi }
612686}
613687
614688class UseOrPhi extends SsaDefOrUse {
@@ -621,6 +695,12 @@ class UseOrPhi extends SsaDefOrUse {
621695 final override Location getLocation ( ) {
622696 result = this .asDefOrUse ( ) .getLocation ( ) or result = this .( Phi ) .getLocation ( )
623697 }
698+
699+ final Node getNode ( ) {
700+ result = this .( Phi ) .getNode ( )
701+ or
702+ result = this .asDefOrUse ( ) .( UseImpl ) .getNode ( )
703+ }
624704}
625705
626706class Def extends DefOrUse {
0 commit comments