-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
audit analysis of undefined values; make it clear when undefined is allowed or not #1947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
docs
enhancement
Solving this issue will likely involve adding new logic or components to the codebase.
Milestone
Comments
This was referenced Feb 14, 2019
Documentation may need updating to closely resemble what's actually happens in LLVM. In particular,
phrase is suspicious and may mislead users. Suggested example: const warn = @import("std").debug.warn;
fn get_zero() u32 {
var x : u32 = undefined;
return x & ~x;
}
pub fn main() void {
if (get_zero() == 0) {
warn("Y\n");
} else {
warn("N\n");
}
}
|
Merged
4 tasks
Related: #8056 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
docs
enhancement
Solving this issue will likely involve adding new logic or components to the codebase.
In IR analysis, right now Zig is inconsistent about the semantics of an operation with an undefined value. This issue is to make the rules clear how it is supposed to work. Note that undefined values are different from undefined behavior.
T
takes up the same store size as a normal value of typeT
, and exists as any bit pattern within that store size. Thus by looking only within the store size of an undefined value it may be impossible to tell that it is an undefined value.u8(undefined)
, in memory, could be any combination of bits that fits in@sizeOf(u8)
, which is1
. The valuebool(undefined)
, in memory, could be any combination of bits that fits in@sizeOf(bool)
, which is also1
. So even though the only valid bit patterns of the typebool
are0b00000000
and0b00000001
, when the value is undefined, the byte which represents the storage of theu1
value could be anything, including0b00000010
,0b10101010
, or0b11111111
. Therefore, because undefined values semantically represent an extra state, it is an incorrect assumption that an undefined value with typeT
has a value which is in the set of valid values for typeT
.+%
operator. Note that for slicing operator, if the start is0
, the pointer value is not read, which makes this expression defined:(([*]u8)(undefined))[0..0]
. Another example is@ptrCast(*i32, (*u32)(undefined))
. Although 0x0 is not a valid bit pattern for the type*u32
, 0x0 is a possible bit pattern within the store size of*u32
, and so this expression is capable of producing an invalid bit pattern for the result type. However@ptrCast
is defined to have no possible undefined behavior because it is a no-op on the bit pattern.comptime
, and caught at runtime if debug safety feature: runtime undefined value detection #211 is solved. For example, the condition of anif
expression.@intCast(u8, u16(undefined))
. Another example: the+
operator. However if one of the operands of+
iscomptime
-known to be0
, and the other is an undefined value the result is an undefined value because there exists no bit pattern added to0
that causes overflow.Every IR instruction analysis code should be audited and tests added to enforce this behavior, especially for
comptime
code.Also these rules should be made clear in the language reference.
The text was updated successfully, but these errors were encountered: