[all-commits] [llvm/llvm-project] 4417a7: [ExprConstant] Treat `&*p` as not a dereference in...
Akira Hatanaka via All-commits
all-commits at lists.llvm.org
Thu Jun 4 19:05:36 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 4417a7501aae8a9b8d3ffee1d491540a0858cc29
https://github.com/llvm/llvm-project/commit/4417a7501aae8a9b8d3ffee1d491540a0858cc29
Author: Akira Hatanaka <ahatanak at gmail.com>
Date: 2026-06-05 (Fri, 05 Jun 2026)
Changed paths:
M clang/lib/AST/ByteCode/Compiler.cpp
M clang/lib/AST/ExprConstant.cpp
M clang/test/Sema/static-init.c
Log Message:
-----------
[ExprConstant] Treat `&*p` as not a dereference in C constant initializers (#201483)
In C, [C11 6.5.3.2p3] specifies that when the operand of unary `&` is
the result of a unary `*` operator, neither operator is evaluated and
the result is as if both were omitted. So `&*p` yields the pointer value
`p` without performing a dereference, and forming it is well-defined
even when `p` is null (e.g. `&*(int *)0`).
The constant evaluator did not honor this: it evaluated the `*` as a
real lvalue access and diagnosed a null dereference as undefined
behavior. This went unnoticed for ordinary scalar initializers, which
use the relaxed `Expr::isConstantInitializer()` check, but a bit-field
initializer is evaluated via `EvaluateAsInt()` with `SE_NoSideEffects`,
so the same expression was rejected there with "initializer element is
not a compile-time constant":
```
struct S { long v : 8; };
const struct S s = { .v = (long)&*(int *)0 }; // error
const long x = (long)&*(int *)0; // accepted
```
Handle `&*p` in `PointerExprEvaluator::VisitUnaryAddrOf` (and the
corresponding `UO_AddrOf` case in the bytecode interpreter) by
evaluating the pointer operand directly in C.
Fixes #197846.
rdar://158774335
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list