Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ predicate cmpWithLinearBound(
* For example, if `t` is a signed 32-bit type then holds if `lb` is
* `-2^31` and `ub` is `2^31 - 1`.
*/
private predicate typeBounds(ArithmeticType t, float lb, float ub) {
private predicate typeBounds0(ArithmeticType t, float lb, float ub) {
exists(IntegralType integralType, float limit |
integralType = t and limit = 2.pow(8 * integralType.getSize())
|
Expand All @@ -423,6 +423,42 @@ private predicate typeBounds(ArithmeticType t, float lb, float ub) {
t instanceof FloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
}

/**
* Gets the underlying type for an enumeration `e`.
*
* If the enumeration does not have an explicit type we approximate it using
* the following rules:
* - The result type is always `signed`, and
* - if the largest value fits in an `int` the result is `int`. Otherwise, the
* result is `long`.
*/
private IntegralType getUnderlyingTypeForEnum(Enum e) {
result = e.getExplicitUnderlyingType()
or
not e.hasExplicitUnderlyingType() and
result.isSigned() and
exists(IntType intType |
if max(e.getAnEnumConstant().getValue().toFloat()) >= 2.pow(8 * intType.getSize() - 1)
then result instanceof LongType
else result = intType
)
}

/**
* Holds if `lb` and `ub` are the lower and upper bounds of the unspecified
* type `t`.
*
* For example, if `t` is a signed 32-bit type then holds if `lb` is
* `-2^31` and `ub` is `2^31 - 1`.
*
* Unlike `typeBounds0`, this predicate also handles `Enum` types.
*/
private predicate typeBounds(Type t, float lb, float ub) {
typeBounds0(t, lb, ub)
or
typeBounds0(getUnderlyingTypeForEnum(t), lb, ub)
}

private Type stripReference(Type t) {
if t instanceof ReferenceType then result = t.(ReferenceType).getBaseType() else result = t
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ private module BoundsEstimate {
float getBoundsLimit() {
// This limit is arbitrary, but low enough that it prevents timeouts on
// specific observed customer databases (and the in the tests).
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment text has a grammatical typo: "(and the in the tests)" reads incorrectly. Consider changing it to "(and in the tests)" (or similar).

Suggested change
// specific observed customer databases (and the in the tests).
// specific observed customer databases (and in the tests).

Copilot uses AI. Check for mistakes.
result = 2.0.pow(40)
result = 2.0.pow(29)
}

/** Gets the maximum number of bounds possible for `t` when widening is used. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,67 @@
| minmax.c:26:37:26:37 | x | 1 |
| minmax.c:26:40:26:40 | y | 2 |
| minmax.c:26:43:26:43 | z | 0 |
| missing_bounds.cpp:40:5:40:20 | x | 0 |
| missing_bounds.cpp:40:5:40:20 | x | 0 |
| missing_bounds.cpp:41:5:41:20 | x | 0 |
| missing_bounds.cpp:41:5:41:20 | x | 0 |
| missing_bounds.cpp:42:5:42:20 | x | 0 |
| missing_bounds.cpp:42:5:42:20 | x | 0 |
| missing_bounds.cpp:43:5:43:20 | x | 0 |
| missing_bounds.cpp:43:5:43:20 | x | 0 |
| missing_bounds.cpp:44:5:44:20 | x | 0 |
| missing_bounds.cpp:44:5:44:20 | x | 0 |
| missing_bounds.cpp:45:5:45:20 | x | 0 |
| missing_bounds.cpp:45:5:45:20 | x | 0 |
| missing_bounds.cpp:46:5:46:20 | x | 0 |
| missing_bounds.cpp:46:5:46:20 | x | 0 |
| missing_bounds.cpp:47:5:47:20 | x | 0 |
| missing_bounds.cpp:47:5:47:20 | x | 0 |
| missing_bounds.cpp:48:5:48:20 | x | 0 |
| missing_bounds.cpp:48:5:48:20 | x | 0 |
| missing_bounds.cpp:49:5:49:20 | x | 0 |
| missing_bounds.cpp:49:5:49:20 | x | 0 |
| missing_bounds.cpp:50:5:50:20 | x | 0 |
| missing_bounds.cpp:50:5:50:20 | x | 0 |
| missing_bounds.cpp:51:5:51:20 | x | 0 |
| missing_bounds.cpp:51:5:51:20 | x | 0 |
| missing_bounds.cpp:52:5:52:20 | x | 0 |
| missing_bounds.cpp:52:5:52:20 | x | 0 |
| missing_bounds.cpp:53:5:53:20 | x | 0 |
| missing_bounds.cpp:53:5:53:20 | x | 0 |
| missing_bounds.cpp:54:5:54:20 | x | 0 |
| missing_bounds.cpp:54:5:54:20 | x | 0 |
| missing_bounds.cpp:55:5:55:20 | x | 0 |
| missing_bounds.cpp:55:5:55:20 | x | 0 |
| missing_bounds.cpp:56:5:56:20 | x | 0 |
| missing_bounds.cpp:56:5:56:20 | x | 0 |
| missing_bounds.cpp:57:5:57:20 | x | 0 |
| missing_bounds.cpp:57:5:57:20 | x | 0 |
| missing_bounds.cpp:58:5:58:20 | x | 0 |
| missing_bounds.cpp:58:5:58:20 | x | 0 |
| missing_bounds.cpp:59:5:59:20 | x | 0 |
| missing_bounds.cpp:59:5:59:20 | x | 0 |
| missing_bounds.cpp:60:5:60:20 | x | 0 |
| missing_bounds.cpp:60:5:60:20 | x | 0 |
| missing_bounds.cpp:61:5:61:20 | x | 0 |
| missing_bounds.cpp:61:5:61:20 | x | 0 |
| missing_bounds.cpp:62:5:62:20 | x | 0 |
| missing_bounds.cpp:62:5:62:20 | x | 0 |
| missing_bounds.cpp:63:5:63:20 | x | 0 |
| missing_bounds.cpp:63:5:63:20 | x | 0 |
| missing_bounds.cpp:64:5:64:20 | x | 0 |
| missing_bounds.cpp:64:5:64:20 | x | 0 |
| missing_bounds.cpp:65:5:65:21 | x | 0 |
| missing_bounds.cpp:65:5:65:21 | x | 0 |
| missing_bounds.cpp:66:5:66:21 | x | 0 |
| missing_bounds.cpp:66:5:66:21 | x | 0 |
| missing_bounds.cpp:67:5:67:21 | x | 0 |
| missing_bounds.cpp:67:5:67:21 | x | 0 |
| missing_bounds.cpp:68:5:68:21 | x | 0 |
| missing_bounds.cpp:68:5:68:21 | x | 0 |
| missing_bounds.cpp:69:5:69:21 | x | 0 |
| missing_bounds.cpp:69:5:69:21 | x | 0 |
| missing_bounds.cpp:72:12:72:12 | x | 0 |
| test.c:8:5:8:9 | count | -2147483648 |
| test.c:8:13:8:17 | count | -2147483648 |
| test.c:10:10:10:14 | count | -2147483648 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
enum MY_ENUM {
A = 0x1,
B = 0x2,
C = 0x4,
D = 0x8,
E = 0x10,
F = 0x20,
G = 0x40,
H = 0x80,
I = 0x100,
J = 0x200,
L = 0x400,
M = 0x800,
N = 0x1000,
O = 0x2000,
P = 0x4000,
Q = 0x8000,
R = 0x10000,
S = 0x20000,
T = 0x40000,
U = 0x80000,
V = 0x100000,
W = 0x200000,
X = 0x400000,
Y = 0x800000,
Z = 0x1000000,
AA = 0x2000000,
AB = 0x4000000,
AC = 0x8000000,
AD = 0x10000000,
AE = 0x20000000
};

typedef unsigned int MY_ENUM_FLAGS;

MY_ENUM_FLAGS check_and_subs(MY_ENUM_FLAGS x)
{

#define CHECK_AND_SUB(flag) if ((x & flag) == flag) { x -= flag; }
CHECK_AND_SUB(A);
CHECK_AND_SUB(B);
CHECK_AND_SUB(C);
CHECK_AND_SUB(D);
CHECK_AND_SUB(E);
CHECK_AND_SUB(F);
CHECK_AND_SUB(G);
CHECK_AND_SUB(H);
CHECK_AND_SUB(I);
CHECK_AND_SUB(J);
CHECK_AND_SUB(L);
CHECK_AND_SUB(M);
CHECK_AND_SUB(N);
CHECK_AND_SUB(O);
CHECK_AND_SUB(P);
CHECK_AND_SUB(Q);
CHECK_AND_SUB(R);
CHECK_AND_SUB(S);
CHECK_AND_SUB(T);
CHECK_AND_SUB(U);
CHECK_AND_SUB(V);
CHECK_AND_SUB(W);
CHECK_AND_SUB(X);
CHECK_AND_SUB(Y);
CHECK_AND_SUB(Z);
CHECK_AND_SUB(AA);
CHECK_AND_SUB(AB);
CHECK_AND_SUB(AC);
CHECK_AND_SUB(AD);
CHECK_AND_SUB(AE);
#undef CHECK_AND_SUB

return x;
}
Loading
Loading