ISO/ IEC JTC1/SC22/WG14 N790

SC22/WG14 N790





The meaning of "implementation-defined"

Clive D.W. Feather

clive@demon.net

1997-10-21





Abstract

========



N732 proposed new definitions for "undefined" and "implementation-defined",

and added a new term "implementation-limited". It then proposed that various

items that are currently implementation-defined should become implementation-

limited.



After discussion at the Menlo Park meeting, it was agreed that the new

definitions of "undefined" and "implementation-defined" were useful, though

some adjustments were required. However, the new "implementation-limited"

concept was disliked; instead, case-by-case changes should be made to the

body of the Standard.





Discussion

==========



The Standard defines two significant terms:



    3.11 Implementation-defined behavior



    Behavior, for a correct program construct and correct

    data, that depends on the characteristics of the

    implementation and that each implementation shall document.



    3.19 Unspecified behavior



    Behavior, for a correct program construct and correct

    data, for which this International Standard explicitly

    imposes no requirements.



First consider the term "unspecified behavior". Most commentators on

the Standard are of the opinion that this has the following

properties:

(1) There are a number of possible courses of actions, or the behavior

    is one that generates a result and then has a number of possible

    results.

(2) The implementation can make any of the available choices, and can

    make different choices at different places or times.

(3) The implementation need not document its choices.

(4) No matter what choice the implementation makes, it cannot affect

    anything outside the range of that choice. If a value has to be

    chosen, it must be a valid value for that type.



Property number 4 is the interesting one: it is usually taken to mean

that the implementation cannot generate a spurious signal, branch to

a random place in the code, or choose a trap representation. All of

these, of course, are valid "undefined behavior".



This interpretation, and particularly property number 4, is usually

assumed to be what is meant by:



    for a correct program construct and correct data



At this point, it should be noted that these words are not perhaps

the best ever written. It has been claimed, in other contexts, that

they mean that the construct must be correct, and if it is not the

implementation is not constrained. Since that interpretation would

make unspecified behavior indistinguishable from undefined behaviour,

I reject it. But the wording should be improved.



Now consider the definition of "implementation-defined behavior".

Clearly, this is similar to unspecified behavior, but carries the

words:



    that depends on the characteristics of the

    implementation and that each implementation shall document



The most obvious reading is that property 3 above does not apply,

and should be replaced by:



(3A) The implementation must document its choices.



Given the similarities in wording otherwise, I conclude that it was

intended that properties 1, 2, and 4 still apply.





There are a number of places that are "implementation-defined behavior"

but where it is desirable to give the implementation more flexibility,

including the ability to violate property 4. Rather than introduce a new

concept, these places have been specifically identified and new wording

suggested.





Proposal

========

Part 1

------

Replace 3.19 ("unspecified behavior") with:



    3.19 Unspecified behavior



    Behavior where this International Standard provides two or more

    possibilities and imposes no requirements on which is chosen in any

    instance. An otherwise correct program, operating on correct data,

    containing unspecified behaviour shall nonetheless be a correct program

    and act in accordance with subclause 5.1.2.3.



Replace 3.11 ("implementation-defined behavior") with:



    3.11 Implementation-defined behavior



    Unspecified behavior where each implementation shall document

    how the choice is made.



Part 2

------

In 6.3.2.4 (Structure and union members) paragraph 5, change:



    With one exception, if the value of a member of a union object is

    used when the most recent store to the object was to a different

    member, the behaviour is implementation-defined. One special

    guarantee is made ...



to



 |  If the value of a member of a union object is used when the most

 |  recent store to the object was to a member with a different type:

 |  if the two types are compatible, or are differently qualified versions

 |  of compatible types, or the value is one that is required to have the

 |  same representation in the two types, then the value retrieved is the

 |  same as the value that was stored. Otherwise, with one exception, the

 |  value retrieved is determined by the object representation as

 |  described in subclause 6.1.2.8, and might be a trap representation

 |  (in which case the behavior is undefined). One special guarantee is

    made ...



Part 3

------

Change 6.8.6 (Pragma directive) paragraph 1 from:



    A preprocessing directive of the form

        # pragma pp-tokens/opt new-line

    where the preprocessing token STDC does not immediately follow the

    pragma on the directive causes the implementation to behave in an

    implementation-defined manner. Any such pragma that is not recognized

    by the implementation is ignored.



to:



    A preprocessing directive of the form

        # pragma pp-tokens/opt new-line

    where the preprocessing token STDC does not immediately follow the

    pragma on the directive causes the implementation to behave in a

    manner which it shall document. The behavior might cause translation

    to fail or the resulting program to behave in a non-conforming manner.



and add at the end of the subclause:



    Recommended practice:



    Any pragma, not beginning with STDC, that the implementation does not

    have a specific meaning for should be ignored.



In subclause 6.8.9 (Pragma operator), change:



    ... The original four preprocessing tokens in the unary operator

    expression are replaced by the (possibly empty) implementation-defined

    sequence of preprocessing-tokens that result from that execution.



to:



    ... The original four preprocessing tokens in the unary operator

    expression are removed.



[6.8.6 doesn't allow for preprocessing-tokens being added.]



Part 4

------

In subclause 7.13.4.4 (The tmpnam function) paragraph 3, change:



    If it is called more than TMP_MAX times, the behavior is

    implementation-defined.



to:



    If it is called more than TMP_MAX times, the behavior is undefined.



Part 5

------

In the various *scanf functions, p conversion specifier, delete the words



    The interpretation of the input item is implementation-defined.



Part 6

------

In subclause 7.13.11.4 (The perror function) paragraph 2, change:



    The contents of the error message strings are the same as those

    returned by the /strerror/ function with argument /errno/, which

    are implementation-defined.



to:



    The contents of the error message strings are the same as those

 |  returned by the /strerror/ function with argument /errno/.



[They are locale-specific, not implementation-defined.]



Part 7

------

In subclause 7.14.4.5 (The system function), change paragraphs 2 and 3

from:



    Description



    The /system/ function passes the string pointed to by /string/ to

    the host environment to be executed by a /command processor/ in an

    implementation-defined manner. A null pointer may be used for

    /string/ to inquire whether a command processor exists.



    Returns



    If the argument is a null pointer, the /system/ function returns

    nonzero only if a command processor is available. If the argument

    is not a null pointer, the /system/ function returns an implementation-

    defined value.



to:



    Description



    If /string/ is a null pointer, the /system/ function determines whether

    the host environment has a /command processor/. If /string/ is not a

    null pointer, the /system/ function passes the string pointed to by

    /string/ to that command processor to be executed in a manner which

    the implementation shall document; this might then cause the program

    calling /system/ to behave in a non-conforming manner or to terminate.



    Returns



    If the argument is a null pointer, the /system/ function returns

    nonzero only if a command processor is available. If the argument

    is not a null pointer and the /system/ function does return, it

    returns an implementation-defined value.



Part 8

------

In subclause 6.3 (Expressions) paragraph 4, change:



    These operators return values that depend on the internal

    representations of integers, and thus have implementation-defined

    aspects for signed types.



to:



    These operators return values that depend on the internal

    representations of integers, and have implementation-defined and

    undefined aspects for signed types.