Skip to content

Commit b2571c8

Browse files
committed
C++: IR: Fix performance of value-init ranges
On a snapshot of Postgres, evaluation of `getNextExplicitlyInitializedElementAfter#fff#antijoin_rhs#1` took forever, preventing the computation of the IR. I haven't been able to reproduce it with a small test case, but the implementation of `getNextExplicitlyInitializedElementAfter` was fragile because it called the inline predicate `ArrayAggregateLiteral.isInitialized`. It also seemed inefficient that `getNextExplicitlyInitializedElementAfter` was computed for many values of its parameters that were never needed by the caller. This commit replaces `getNextExplicitlyInitializedElementAfter` with a new predicate named `getEndOfValueInitializedRange`, which should have the same behavior but a more efficient implementation. It uses a helper predicate `getNextExplicitlyInitializedElementAfter`, which shares its name with the now-deleted predicate but has behavior that I think matches the name.
1 parent 4051e34 commit b2571c8

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ newtype TTranslatedElement =
270270
not ignoreExpr(initList) and
271271
isFirstValueInitializedElementInRange(initList, elementIndex) and
272272
elementCount =
273-
getNextExplicitlyInitializedElementAfter(initList, elementIndex) -
273+
getEndOfValueInitializedRange(initList, elementIndex) -
274274
elementIndex
275275
} or
276276
// The initialization of a base class from within a constructor.
@@ -322,23 +322,28 @@ newtype TTranslatedElement =
322322

323323
/**
324324
* Gets the index of the first explicitly initialized element in `initList`
325-
* whose index is greater than `afterElementIndex`. If there are no remaining
326-
* explicitly initialized elements in `initList`, the result is the total number
327-
* of elements in the array being initialized.
325+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
326+
* is a first value-initialized element in a value-initialized range in
327+
* `initList`. If there are no remaining explicitly initialized elements in
328+
* `initList`, the result is the total number of elements in the array being
329+
* initialized.
328330
*/
329-
private int getNextExplicitlyInitializedElementAfter(
330-
ArrayAggregateLiteral initList, int afterElementIndex) {
331-
if exists(int x |
332-
x > afterElementIndex and
333-
exists(initList.getElementExpr(x)))
334-
then (
335-
if exists(initList.getElementExpr(afterElementIndex + 1))
336-
then result = afterElementIndex + 1
337-
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1))
338-
else
339-
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and
340-
// required for binding
341-
initList.isInitialized(afterElementIndex)
331+
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
332+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
333+
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
334+
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
335+
}
336+
337+
/**
338+
* Gets the index of the first explicitly initialized element in `initList`
339+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
340+
* is a first value-initialized element in a value-initialized range in
341+
* `initList`.
342+
*/
343+
private int getNextExplicitlyInitializedElementAfter(
344+
ArrayAggregateLiteral initList, int afterElementIndex) {
345+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
346+
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
342347
}
343348

344349
/**

0 commit comments

Comments
 (0)