Non-directives

Discussion in 'C Programming' started by Eric Sosman, Sep 10, 2013.

  1. Eric Sosman

    Eric Sosman Guest

    It seems to me the topic has come up before, but it doesn't
    seem to me the question was ever answered satisfactorily:

    What is a preprocessing non-directive?

    6.10p1 describes its syntax, 6.10p3 states a requirement
    (but not a constraint), a footnote to 6.10p11 asserts that a
    non-directive is in fact a directive -- and that is all the
    Standard says about the matter until it repeats itself in
    Appendix A.

    The (C99) Rationale says that non-directives are not
    implementation-defined but are "strictly" defined, and mumbles
    something about placeholders for intermediate translation states
    having "no associated semantics in this phase."

    So: Can anyone explain what a non-directive is, does,
    or is for? Is

    #import <stdio.h>

    .... a non-directive?
     
    Eric Sosman, Sep 10, 2013
    #1
    1. Advertisements

  2. Eric Sosman

    James Kuyper Guest

    Yes.

    The key thing to understand is that what qualifies as a non-directive is
    defined by the standard, but there is no standard-defined behavior
    associated with them. As such, a non-directive is something that has a
    similarity to directives, but can be used to implement non-conforming
    extensions. In that regard, there's a certain amount of overlap with
    #pragma directives.

    The fact that they are classified as directives means that everything
    that the standard says about directives in general, rather than about
    specific directives, applies to non-directives as well. This is
    particularly important with respect to conditional compilation
    (6.10.1p6). Non-directives get skipped or processed, depending which
    part of a #if, #ifdef, #ifndef, or #elif they are in - they don't
    interfere with the interpretation of those constructs. That allows them
    to be protected against mis-interpretation by fully conforming
    implementations by suitable use of #if, et. al.
     
    James Kuyper, Sep 10, 2013
    #2
    1. Advertisements

  3. Eric Sosman

    Eric Sosman Guest

    Thanks, James. It's plausible, but I'm not entirely
    convinced you're right. The Rationale (non-normative, of
    course) says

    Neither /text-line/ nor /non-directive/ is implementation
    defined. They are strictly defined as sequences of pp-tokens
    followed by new-line. Each of these rules represents a
    placeholder for an intermediate state in the phases of
    translation, and is expressed as a non-terminal since it
    has no associated semantics at this phase.

    However, these sequences of pp-tokens are still subject to
    normal processing in the subsequent phases of translation.

    On re-reading, it seems this may mean non-directives are
    pp-token sequences that get macro-replaced in Phase 4 but are
    not otherwise preprocessed: They don't affect preprocessor
    operation ("no semantics"), and are not removed. "Normal
    processing" will convert the non-directive's pp-tokens to
    tokens in Phase 7, and the parser will then report a syntax
    error (the # token alone is sufficient offense against the
    grammar).

    So: Is "non-directive" just a way of describing how an
    erroneous preprocessor construct gets turned into a syntax
    error?
     
    Eric Sosman, Sep 10, 2013
    #3
  4. Eric Sosman

    James Kuyper Guest

    "The preprocessing tokens within a preprocessing directive are not
    subject to macro expansion unless otherwise stated." (6.10p7)

    It is "otherwise stated" that macro expansion applies to the controlling
    condition of #if and #elif (6.10.1p4).

    Both #include and #line have two forms for which no macro replacement
    applies, but can be used in a more general form for which macro
    replacement is not only allowed, but strongly recommended - the behavior
    is undefined if macro replacement doesn't convert the general form to
    one of the other two forms. (6.10.2p4, 6.10.4p5)

    Since it is NOT "otherwise stated", macro expansion does not apply to
    non-directives, #define, #undef, #error, or null directives, nor to
    #pragma directives where #pragma is immediately followed by a STDC
    token. It is not explicitly stated that macro expansion is allowed for
    other #pragma directives, but "behave in an implementation-defined
    manner" certainly allows the implementation to say that it does, which I
    think qualifies as "otherwise stated". If it doesn't count, then the
    references to "prior to any macro expansion" in 6.10.6 don't make sense.
    "... All preprocessing directives are then deleted." (5.1.1.2p4)

    Keep in mind that non-directives, despite the implications of their
    names, are pre-processing directives (footnote 172), and are therefore
    covered by both 6.10p7 and 5.1.1.2p4. It is specifically for the purpose
    of making such things work that the definition of "pre-processing
    directive" (6.10p2) was not made more restrictive.
     
    James Kuyper, Sep 10, 2013
    #4
  5. Eric Sosman

    Tim Rentsch Guest

    My reading of the Standard is that a 'non-directive' is a
    preprocessing directive, and having one in program source
    (assuming it isn't skipped by a preprocessing conditional)
    is undefined behavior. Reasoning given below.
    (Presumably you meant 6.10.3p11 for the footnote.)

    The statements in 6.10p3 are meant as restrictions on the definition
    of the language, not as restrictions on programs. That is, the
    statement "A non-directive shall not begin with any of the directive
    names appearing in the syntax" means that any preprocessor line that
    does begin with one of those directive names is not to be taken (by
    an implementation) as a non-directive.

    Yes. Based on the syntax, 6.10 p3, and the footnote in 6.10.3 p11,
    it seems clear such a line is a non-directive, and is meant to be
    a preprocessing directive despite the name.

    An indirect argument that non-directives are undefined behavior
    goes as follows. Clearly the behavior of non-directive lines is
    not implementation-defined, since nothing says so. Hence the
    behavior must either be defined or be undefined. If the behavior
    were defined, then such a line would have to do the same thing in
    all conforming implementations. Observing that in fact such lines
    behave differently in different implementations, the behavior must
    therefore be undefined.

    A direct argument that non-directives are undefined behavior goes as
    follows. 5.1.1.2 p4 says "Preprocessing directives are executed".
    The semantics of executing a non-directive is not defined anywhere.
    Hence under section 4 p2 the behavior upon attempting to execute
    a non-directive is undefined.
     
    Tim Rentsch, Sep 22, 2013
    #5
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.