On 03/08/13 20:58, Mcdaniel, Daryl wrote:
> A compiler that optimizes out references to NULL is doing the wrong
> thing.

It depends.

> The ISO/IEC 9899:199409 (C95) language specification says nothing
> about using volatile with NULL.
>
> The language specification does NOT prohibit reading from, writing to,
> or executing a function that is located at, address 0.
> It does prohibit the compiler from placing data or functions at that
> location.
>
> It sounds like clang is broken if it doesn't have an option to disable
> the behavior you are reporting.
> Changing references through a NULL pointer to a trap would be a
> nonstandard extension.

>From ISO C99:

  3.4

  1 behavior
    external appearance or action

  3.4.1

  1 implementation-defined behavior
    unspecified behavior where each implementation documents how the
    choice is made

  2 EXAMPLE An example of implementation-defined behavior is the
    propagation of the high-order bit when a signed integer is shifted
    right.

  3.4.3

  1 undefined behavior
    behavior, upon use of a nonportable or erroneous program construct
    or of erroneous data, for which this International Standard imposes
    no requirements

  2 NOTE Possible undefined behavior ranges from ignoring the situation
    completely with unpredictable results, to behaving during
    translation or program execution in a documented manner
    characteristic of the environment (with or without the issuance of a
    diagnostic message), to terminating a translation or execution (with
    the issuance of a diagnostic message).

  3.4.4

  1 unspecified behavior
    behavior where this International Standard provides two or more
    possibilities and imposes no further requirements on which is chosen
    in any instance

  2 EXAMPLE An example of unspecified behavior is the order in which the
    arguments to a function are evaluated.

  4. Conformance

  2 If a "shall" or "shall not" requirement that appears outside of a
    constraint is violated, the behavior is undefined. Undefined
    behavior is otherwise indicated in this International Standard by
    the words "undefined behavior" or by the omission of any explicit
    definition of behavior. There is no difference in emphasis among
    these three; they all describe "behavior that is undefined".

A platform may define things that the ISO C99 standard leaves undefined;
it can say "SIGSEV" for example. But that doesn't make the program any
more conformant to / any less erroneous in ISO C99.

What the "platform defines" outside of C99 may depend on several factors
at once, for example, compiler options (-fdelete-null-pointer-checks),
SIGSEGV vs. something else etc. (A strict C99-only compiler might even
refuse *not* to break undefined behavior on purpose, and it would be a
perfectly fine (and very useful) C99 compiler.)

Observable behavior will result from several layers of behavior
definitions. When clang is told (with compiler switches or otherwise) to
consider nothing else than ISO C99, then it is free to "implement"
undefined behavior however it wishes, because (a) C99 doesn't cover
those gaps, and (b) clang was told to consider nothing else.

When targeting one specific platform (= knowing and/or controlling all
"layers"), the difference between the C99 terms
"implementation-defined", "unspecified", "undefined" may not be
important; whatever falls "through" C99 might be caught (defined) by
another layer: POSIX, the Single Unix Specification, compiler switches,
compiler documentation, happenstance in compiler source code, operating
system specifics, etc.

The terms are important when the source code is moved to another
platform (compiler upgrade, operating system upgrade, fully foreign
platform), and we only know that the new target "supports C99". Then
bits exploiting "implementation-defined behavior" can be adapted in
accordance with target documentation (there will be documentation).

Unspecified behavior could change without documentation, but we've been
warned: eg. we're free to call functions with arguments, and to evaluate
expressions, but we should write them so that we're happy with whichever
order evaluation takes place in. Using the facility is not a programming
error in itself.

Bits that rely on undefined behavior could break irrevocably, but we've
been told never to do those things *if* we intended to build our program
on another platform that calls itself C99 conformant *and nothing else
in addition*.

(The same thing works with other standards that build upon ISO C99 and
use the same terminology; for example the Single Unix Specification,
Version 3: you can expect the same levels of assurance when moving from
one SUSv3 system to another SUSv3 system, only the precise contents of
each "level" is different than in ISO C99.)

In ISO C99, dereferencing a null pointer is undefined behavior.
(Additionally, the pointer target being volatile-qualified doesn't
change that.)

  6.3.2.3 Pointers

  3 An integer constant expression with the value 0, or such an
    expression cast to type void *, is called a null pointer constant.
    [...] 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.

  6.5.3.2 Address and indirection operators

  4 The unary * operator denotes indirection. If the operand points to a
    function, the result is a function designator; if it points to an
    object, the result is an lvalue designating the object. If the
    operand has type "pointer to type", the result has type "type". If
    an invalid value has been assigned to the pointer, the behavior of
    the unary * operator is undefined.83)

    Footnote 83

      [...] Among the invalid values for dereferencing a pointer by the
      unary * operator are a null pointer, an address inappropriately
      aligned for the type of object pointed to, and the address of an
      object after the end of its lifetime.

  6.5.2.3 Structure and union members

  4 A postfix expression followed by the -> operator and an identifier
    designates a member of a structure or union object. The value is
    that of the named member of the object to which the first expression
    points, and is an lvalue. [...]

(A null pointer cannot point to an object (see 6.3.2.3p3 above),
therefore "nullptr->member" is undefined behavior by omission of any
explicit definition of behavior in 6.5.2.3p4.)


Regarding "address 0":
- not required: all-bits-clear object representation in a null pointer,
- not required: (uintptr_t)(void*)0 == 0 -- supposing uintptr_t is
  supported at all.

They are permitted, naturally:

  6.3.2.3 Pointers

  5 An integer may be converted to any pointer type. Except as
    previously specified, the result is implementation-defined, might
    not be correctly aligned, might not point to an entity of the
    referenced type, and might be a trap representation.56)

  6 Any pointer type may be converted to an integer type. Except as
    previously specified, the result is implementation-defined. If the
    result cannot be represented in the integer type, the behavior is
    undefined. The result need not be in the range of values of any
    integer type.

  Footnote 56

    The mapping functions for converting a pointer to an integer or an
    integer to a pointer are intended to be consistent with the
    addressing structure of the execution environment.

(Footnotes, notes, examples are not normative but informative only --
they don't prescribe, only explain.)

All this is just my opinion of course.

Laszlo

------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to