@@ -410,6 +410,136 @@ private class BaseAllocationInstruction extends BaseSourceVariableInstruction, A
410410
411411cached
412412private module Cached {
413+ private import semmle.code.cpp.models.interfaces.Iterator as Interfaces
414+ private import semmle.code.cpp.models.implementations.Iterator as Iterator
415+
416+ /**
417+ * Holds if `next` is a instruction with a memory result that potentially
418+ * updates the memory produced by `prev`.
419+ */
420+ private predicate memorySucc ( Instruction prev , Instruction next ) {
421+ prev = next .( ChiInstruction ) .getTotal ( )
422+ or
423+ // Phi inputs can be inexact.
424+ prev = next .( PhiInstruction ) .getAnInputOperand ( ) .getAnyDef ( )
425+ or
426+ prev = next .( CopyInstruction ) .getSourceValue ( )
427+ or
428+ exists ( ReadSideEffectInstruction read |
429+ next = read .getPrimaryInstruction ( ) and
430+ isAdditionalConversionFlow ( _, next ) and
431+ prev = read .getSideEffectOperand ( ) .getAnyDef ( )
432+ )
433+ }
434+
435+ /**
436+ * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
437+ * that is used for a write operation that writes the value `value`. The `memory` instruction
438+ * represents the memory that the IR's SSA analysis determined was read by the call to `operator*`.
439+ *
440+ * The `numberOfLoads` integer represents the number of dereferences this write corresponds to
441+ * on the underlying container that produced the iterator.
442+ */
443+ private predicate isChiAfterIteratorDef (
444+ Instruction memory , Operand iteratorDerefAddress , Node0Impl value , int numberOfLoads
445+ ) {
446+ exists (
447+ BaseSourceVariableInstruction iteratorBase , ReadSideEffectInstruction read ,
448+ Operand iteratorAddress
449+ |
450+ numberOfLoads >= 0 and
451+ isDef ( _, value , iteratorDerefAddress , iteratorBase , numberOfLoads + 2 , 0 ) and
452+ isUse ( _, iteratorAddress , iteratorBase , numberOfLoads + 1 , 0 ) and
453+ iteratorBase .getResultType ( ) instanceof Interfaces:: Iterator and
454+ isDereference ( iteratorAddress .getDef ( ) , read .getArgumentDef ( ) .getAUse ( ) ) and
455+ memory = read .getSideEffectOperand ( ) .getAnyDef ( )
456+ )
457+ }
458+
459+ /**
460+ * Holds if `iterator` is a `StoreInstruction` that stores the result of some function
461+ * returning an iterator into an address computed started at `containerBase`.
462+ *
463+ * For example, given a declaration like `std::vector<int>::iterator it = v.begin()`,
464+ * the `iterator` will be the `StoreInstruction` generated by the write to `it`, and
465+ * `containerBase` will be the address of `v`.
466+ */
467+ private predicate isChiAfterBegin (
468+ BaseSourceVariableInstruction containerBase , StoreInstruction iterator
469+ ) {
470+ exists ( CallInstruction getIterator |
471+ getIterator = iterator .getSourceValue ( ) and
472+ getIterator .getStaticCallTarget ( ) instanceof Iterator:: GetIteratorFunction and
473+ isDef ( _, any ( Node0Impl n | n .asInstruction ( ) = iterator ) , _, _, 1 , 0 ) and
474+ isUse ( _, getIterator .getThisArgumentOperand ( ) , containerBase , 0 , 0 )
475+ )
476+ }
477+
478+ /**
479+ * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
480+ * that is used for a read operation. The `memory` instruction represents the memory that
481+ * the IR's SSA analysis determined was read by the call to `operator*`.
482+ *
483+ * Finally, the `numberOfLoads` integer represents the number of dereferences this read
484+ * corresponds to on the underlying container that produced the iterator.
485+ */
486+ private predicate isChiBeforeIteratorUse (
487+ Operand iteratorDerefAddress , Instruction memory , int numberOfLoads
488+ ) {
489+ exists (
490+ BaseSourceVariableInstruction iteratorBase , LoadInstruction load ,
491+ ReadSideEffectInstruction read
492+ |
493+ numberOfLoads >= 0 and
494+ isUse ( _, iteratorDerefAddress , iteratorBase , numberOfLoads + 2 , 0 ) and
495+ iteratorBase .getResultType ( ) instanceof Interfaces:: Iterator and
496+ read .getPrimaryInstruction ( ) = load .getSourceAddress ( ) and
497+ memory = read .getSideEffectOperand ( ) .getAnyDef ( )
498+ )
499+ }
500+
501+ /**
502+ * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
503+ * that is used for a write operation that writes the value `value` to a container that
504+ * created the iterator. `container` represents the base of the address of the container
505+ * that was used to create the iterator.
506+ */
507+ cached
508+ predicate isIteratorDef (
509+ BaseSourceVariableInstruction container , Operand iteratorDerefAddress , Node0Impl value ,
510+ int numberOfLoads , int indirectionIndex
511+ ) {
512+ exists ( Instruction memory , Instruction begin , int upper , int ind |
513+ isChiAfterIteratorDef ( memory , iteratorDerefAddress , value , numberOfLoads ) and
514+ memorySucc * ( begin , memory ) and
515+ isChiAfterBegin ( container , begin ) and
516+ upper = countIndirectionsForCppType ( container .getResultLanguageType ( ) ) and
517+ ind = numberOfLoads + [ 1 .. upper ] and
518+ indirectionIndex = ind - ( numberOfLoads + 1 )
519+ )
520+ }
521+
522+ /**
523+ * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
524+ * that is used for a read operation to read a value from a container that created the iterator.
525+ * `container` represents the base of the address of the container that was used to create
526+ * the iterator.
527+ */
528+ cached
529+ predicate isIteratorUse (
530+ BaseSourceVariableInstruction container , Operand iteratorDerefAddress , int numberOfLoads ,
531+ int indirectionIndex
532+ ) {
533+ exists ( Instruction begin , Instruction memory , int upper , int ind |
534+ isChiBeforeIteratorUse ( iteratorDerefAddress , memory , numberOfLoads ) and
535+ memorySucc * ( begin , memory ) and
536+ isChiAfterBegin ( container , begin ) and
537+ upper = countIndirectionsForCppType ( container .getResultLanguageType ( ) ) and
538+ ind = numberOfLoads + [ 1 .. upper ] and
539+ indirectionIndex = ind - ( numberOfLoads + 1 )
540+ )
541+ }
542+
413543 /**
414544 * Holds if `op` is a use of an SSA variable rooted at `base` with `ind` number
415545 * of indirections.
0 commit comments