[swift-evolution] [Review] SE-0055 Make unsafe pointer nullability explicit using Optional
Jordan Rose
jordan_rose at apple.com
Wed Mar 30 13:00:41 CDT 2016
> On Mar 30, 2016, at 3:11 , Jeremy Pereira via swift-evolution <swift-evolution at swift.org> wrote:
>
>
>> On 25 Mar 2016, at 23:00, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>>
>>> In the low level world, there is no such thing as an invalid address; both 0x0 and ~0x0 are perfectly valid byte pointers. So using something else than 0x0 for Swift invalid pointer just shuffle the problem around.
>>
>> Let me state it this way: You cannot write a fully-conforming C compiler for a platform which does not have some way to represent an invalid pointer.
>
> This is not true.
>
> In both C99 and C11, the result of dereferencing an invalid pointer (of which the null pointer is one example) is undefined behaviour. This means it is perfectly fine for the null pointer to be represented by a bit pattern that is also a valid address and for the compiler not to bother generating a check that the pointer is not null.
Clever! I worked through this for the benefit of the list:
C11 6.3.2.3p3: If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
C11 6.3.2.3p4: Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
So there must be at least one bit pattern recognizable as a null pointer…
C11 6.5.3.2p1: The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the 'register' storage-class specifier.
C11 6.5.3.2p3: […] Otherwise [when not using [] or *], the result is a pointer to the object or function designated by its operand.
…and it must not have the same representation as a bit pattern of an object or function declared in C…
C11 6.5.3.2p4: If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
C11 6.3.2.1p1: An lvalue is an expression (with an object type other than 'void') that potentially designates an object; if an lvalue does not designate an object when it is evaluated, the behavior is undefined.
…but as you say there's nothing stopping a particular compiler from giving the dereference defined behavior.
However, what this can't do is remove its use as a sentinel value. For example:
C11 7.24.5.1p3: The 'memchr' function returns a pointer to the located character, or a null pointer if the character does not occur in the object.
So ultimately I see Swift as being just as compatible as C in this case. Both languages designate a certain bit pattern for use as a placeholder. Swift is a little more aggressive in keeping you from loading from it, but on such a platform the standard library could certainly expose a "safely load from this optional pointer" builtin, which could then perhaps be exposed as a member on "Optional where Wrapped: _Pointer". (I'm not sure if that's the best way to do it, but it's an idea.)
As Chris has said previously, both Clang and LLVM themselves have a lot of assumptions about what can and can't be done with a null pointer, so porting to any such platform would include a fair amount of work simply extricating that logic and placing it behind a flag.
Best,
Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160330/5605b769/attachment.html>
More information about the swift-evolution
mailing list