"error: invalid preprocessing directive #DEFINE"

Discussion in 'C Programming' started by alien, Oct 4, 2009.

  1. alien

    Richard Bos Guest

    It is a non-directive. Since no meaning is defined for non-directives,
    they have undefined behaviour. Therefore, if the implementation can show
    that a non-directive will be reached, it is allowed to reject the source
    code entirely.

    Richard Bos, Oct 7, 2009
    1. Advertisements

  2. Or it an silently ignore it, which is the problem.
    Keith Thompson, Oct 7, 2009
    1. Advertisements

  3. Assuming the intent is to allow implementation-specific preprocessor
    directives, making the behavior undefined even if it's unreachable
    would make it nearly useless.

    For example, suppose Foo C supports a "#include_once" directive:

    #ifdef __FOO_C__
    #include_once "blah.h"
    #include "blah.h"

    The obvious intent is that the #include_once directive will be seen
    only by the Foo C compiler.

    I still dislike what seems to be the intent; if an implementation
    doesn't support "#include_once", a diagnostic should be mandatory for
    that implementation.
    Keith Thompson, Oct 7, 2009
  4. alien

    jameskuyper Guest

    For a pre-processing directive "will be reached" means that it
    survives conditional compilation.
    jameskuyper, Oct 7, 2009
  5. alien

    James Kuyper Guest

    The standard never defines what the term "reached" means, it only uses
    the term in contexts where it refers to something that happens a run
    time, not compile time. It does not use the term when explaining
    undefined behavior.

    What it does say is that behavior is undefined "upon use of a
    nonportable or erroneous program construct or of erroneous data," a
    sufficiently vague statement that the Committee has had to resolve some
    defect reports based upon uncertainties about what precisely constitutes
    a "use"; those rulings indicate that for most kinds of undefined
    behavior, "use" requires that execution of the program must be
    guaranteed (absent the undefined behavior) to reach the relevant line of

    However, Undefined behavior associated with preprocessing necessarily
    involves a "use" that occurs at compile time, not run time.

    The standard does specify that if conditional compilation causes a group
    of lines to be skipped, "directives are processed only through the name
    that determines the directive in order to keep track of the level of
    nested conditionals; the rest of the directives’ preprocessing tokens
    are ignored, as are the other preprocessing tokens in the group." In
    that case, the standard defines exactly what happens to such lines, so
    it is not possible to claim undefined behavior "by the omission of any
    explicit definition of behavior".
    James Kuyper, Oct 8, 2009
  6. alien

    Tim Rentsch Guest

    Yes, as I already explained two days earlier in my followup
    Tim Rentsch, Oct 8, 2009
  7. alien

    Tim Rentsch Guest

    Do you mean open as to whether non-directives are undefined
    behavior, or whether non-directives were meant to be undefined
    behavior? The case for non-directives being undefined behavior
    seems pretty cut-and-dried, since no definition is given for
    what happens when they are "executed".
    Tim Rentsch, Oct 8, 2009
  8. alien

    Tim Rentsch Guest

    The behavior in such cases is covered, just as it is for #include,
    etc, in 6.10.1p6 -- defined to skip the directive if __FOO_C__ has
    not been #define'd.
    Tim Rentsch, Oct 8, 2009
  9. alien

    Tim Rentsch Guest

    You mean you don't consider my speculations and guesses to
    have as much value as comments from someone who actually
    knows what's going on? I'm crushed. :)

    I would second a motion to propose such a change as
    part of C1X. Possibly I would change my mind about
    whether the change should be adopted after hearing
    the discussion, but I'd like to hear the discussion
    Tim Rentsch, Oct 8, 2009
  10. alien

    Tim Rentsch Guest

    The /simplest/ way would be to add a statement saying that a
    diagnostic is mandatory. Changing the syntax would mean
    making a number of other changes in the subsequent text
    of 6.10 and 6.10.x

    It seems clear that the point is to make non-directives be considered
    similarly to other preprocessing directives, eg, should be deleted at
    the end of phase 4, should be illegal in multi-line macro calls, etc.
    Just because their behavior isn't defined doesn't mean that there is
    no value in putting in clues of this sort. The Standard is read by
    humans, not computers.
    Tim Rentsch, Oct 8, 2009
  11. As James said, the standard doesn't use the word "reached" in this context,
    but you can see the idea in the description of #error (C99 4p4):

    The implementation shall not successfully translate a
    preprocessing translation unit containing a #error preprocessing
    directive unless it is part of a group skipped by conditional
    Keith Thompson, Oct 8, 2009
  12. The simplest way would be to make it a constraint violation; the
    requirement for a diagnostic would fall out of that.

    Explicitly stating that a constraint is required would add a fourth
    special case to the existing things that require diagnostics: syntax
    errors, constraint violations, and #error.
    Keith Thompson, Oct 8, 2009
  13. alien

    Richard Bos Guest

    It is obvious from the requirements for the #error directive (spec. the
    one in section 4), even though the phrasing used may be different. (Note
    that I did not write "reached upon execution", and in fact meant
    "reached during translation").

    Richard Bos, Oct 8, 2009
  14. alien

    Tim Rentsch Guest

    I'm not sure I agree; more below.
    The word 'constraint', especially as defined in 3.8p1, doesn't
    describe the situation with non-directive very well. Making
    executing a non-directive be a constraint violation would require
    issuing a diagnostic, but this rule isn't so much a "restriction" as
    a "prohibition". It seems likely that this same reasoning (or
    similar reasoning) is why '#error' is defined as requiring a
    diagnostic, rather than being identified as under a Constraints

    I understand the desire not to add more cases (be they special or
    otherwise) to the set of things that require a diagnostic. At the
    same time, it's not a good idea to lump something in with an existing
    category, just for the sake of convenience, if it doesn't really fit
    in that category. In my opinion the situation with 'non-directive'
    is different enough from other conditions identified as Constraints
    to think that this term may not be appropriate here. To say this
    another way, I think the situation with 'non-directive' is more like
    '#error' than it is like a constraint violation; if the Standard is
    going to be consistent in how it uses terminology, then either both
    '#error' and 'non-directive' should be constraint violations or
    neither should be [assuming that we want 'non-directive' to require a
    diagnostic, which I'm taking as a given for the sake of discussion].
    I think I understand the reasoning that went into the decision on how
    to handle '#error'; since the same reasoning seems to apply to
    'non-directive', unless there's an argument I haven't thought of yet,
    then just giving an explicit statement that a diagnostic must be
    issued seems like the better course.

    Returning to the larger issue, maybe the best way to clear up what's
    going on with 'non-directive' would be to write a 'Recommended
    practice' paragraph or two saying that encountering a 'non-directive'
    should produce a diagnostic message, perhaps depending on a compiler
    option that allows some implementation-specific preprocessing
    directives. There is some precedent for such a provision, namely, (and for convenience here it is):

    The implementation should produce a diagnostic message if a
    hexadecimal constant cannot be represented exactly in its
    evaluation format; the implementation should then proceed
    with the translation of the program.

    Of course the specific wording for 'non-directive' would be
    very different, but the general approach might be a good
    idea here considering the current state of affairs.
    Tim Rentsch, Oct 9, 2009
  15. I disagree. I think the main reason #error is handled separately is
    that, unlike a constraint error, it requires the compilation to fail.
    Another reason, I suppose, is that #error is something you'd write

    I still think that a "non-directive" should be treated as a
    constraint violation. Or the grammar production for "non-directive"
    could just be dropped, making it a syntax error. The result would
    be the same either way.

    There are two reasons a non-directive might appear in a program:

    1. It's an implementation-specific extension. Consider a core
    language extension like "short float". A conforming implementation
    must issue a diagnostic for "short float"; it can then accept the
    translation unit anyway and do what it likes with the the semantics.
    And it can also provide a non-conforming mode in which it doesn't
    issue the diagnostic; the conforming mode is still there to warn
    you that it's not portable.

    I can think of no good reason why a preprocessor extension like, say,
    "#include_once", should be treated any differently.

    2. It's a typo. If I accidentally type "#elsif" rather than "#elif",
    the compiler IMHO should be *required* to diagnose the error.
    Even if the compiler "helpfully" treats "#elsif" as a synonym for
    "#elif", I want to know that my code isn't portable. (I think most
    compilers already do, so requiring it wouldn't be a burden.)

    Keith Thompson, Oct 9, 2009
  16. alien

    Tim Rentsch Guest

    The most important thing, and the point we're most in agreement
    on, is that the Standard would be improved if the question of
    how 'non-directive's are treated were addressed more explicitly
    and directly. After/if there is some level of consensus for
    doing something, then we can take up again the question of
    just what explicit requirements are most appropriate.
    Tim Rentsch, Oct 12, 2009
  17. IMHO, there's no reason not to consider what the requirements
    should be. Making the requirements more explicit and making them
    "good" are two somewhat separate issues, but I have no problem
    considering both issues simultaneously.

    If the committee were to decide to make a change in this area, they
    probably wouldn't (a) decide to make it more explicit and then (b)
    wait for more feedback on what to do.
    Keith Thompson, Oct 12, 2009
  18. alien

    Tim Rentsch Guest

    It seems counterproductive to argue with someone who is
    basically on the same side as I am. That's really all
    I was trying to say.
    Tim Rentsch, Oct 12, 2009
  19. Are you sure about that? As far as I know, DMR never wrote a preprocessor.
    The original Unix cpp was written by John Reiser.
    lawrence.jones, Oct 14, 2009
    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.