Skip to content

Commit 056e102

Browse files
committed
constexpr: accept unsigned 32-bit enum constants
1 parent ae71efc commit 056e102

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

docs/design/constexpr_impl_notes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ Additional prototype notes
155155
This is expected ISPC behavior but worth calling out in docs/examples to
156156
avoid surprising users when constexpr enters the picture.
157157

158+
19. Switching enum/array size validation from `Expr::GetConstant()` (LLVM
159+
`ConstantInt`) to `ConstexprEvaluate()` introduced a subtle regression:
160+
unsigned 32-bit values with the high bit set (e.g. `0x80000000`,
161+
`0xffffffff`) were rejected by a signed 32-bit representability check.
162+
The fix was to validate unsigned values via `uint64_t` -> `uint32_t`
163+
truncation when the expression type is unsigned, preserving the previous
164+
behavior while still rejecting >32-bit values.
165+
158166

159167
Planned adjustments
160168
-------------------

src/parse.yy

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3782,18 +3782,32 @@ lGetConstantIntOrSymbol(Expr *expr, std::variant<std::monostate, int, Symbol*> *
37823782
return false;
37833783
}
37843784

3785-
int64_t iv[ISPC_MAX_NVEC];
3786-
int count = ce->GetValues(iv);
3787-
if (count < 1) {
3788-
Error(pos, "%s must be a compile-time integer constant.", usage);
3789-
return false;
3790-
}
3791-
if ((int64_t)((int32_t)iv[0]) != iv[0]) {
3792-
Error(pos, "%s must be representable with a 32-bit integer.", usage);
3793-
return false;
3785+
int resultValue = 0;
3786+
if (type->IsUnsignedType()) {
3787+
uint64_t uv[ISPC_MAX_NVEC];
3788+
int count = ce->GetValues(uv);
3789+
if (count < 1) {
3790+
Error(pos, "%s must be a compile-time integer constant.", usage);
3791+
return false;
3792+
}
3793+
if ((uint64_t)((uint32_t)uv[0]) != uv[0]) {
3794+
Error(pos, "%s must be representable with a 32-bit integer.", usage);
3795+
return false;
3796+
}
3797+
resultValue = (int)(uint32_t)uv[0];
3798+
} else {
3799+
int64_t iv[ISPC_MAX_NVEC];
3800+
int count = ce->GetValues(iv);
3801+
if (count < 1) {
3802+
Error(pos, "%s must be a compile-time integer constant.", usage);
3803+
return false;
3804+
}
3805+
if ((int64_t)((int32_t)iv[0]) != iv[0]) {
3806+
Error(pos, "%s must be representable with a 32-bit integer.", usage);
3807+
return false;
3808+
}
3809+
resultValue = (int)(int32_t)iv[0];
37943810
}
3795-
3796-
int resultValue = type->IsUnsignedType() ? (int)(uint64_t)iv[0] : (int)iv[0];
37973811
value->emplace<int>(resultValue);
37983812
return true;
37993813
}

0 commit comments

Comments
 (0)