The Standard neither defines nor uses the term "source program".
Section 5.1.1.1, titled "Program Structure", establishes that
programs are made up of separately compiled translations units,
and that translation units comprise, after preprocessing, the
contents of all included headers and included source files. The
text in 5.1.1.2 p4 makes clear that included headers are
processed in exactly the same manner as included source files.
Your claim is inconsistent with the text of the Standard.
> An analogy here is the library. A C library linked with the
> user's translation units is part of the translated and linked
> program, but it is not part of the C program source that is
> subject to the semantic descriptions. It need not even be written
> in C.
The analogy is faulty because the Standard does describe, in
detail, how included headers are processed, but does not give
such detail for library components. Compare 5.1.1.2 p4 and
5.1.1.2 p8. The analogy is thus irrelevant to the question
of how headers are processed.
>> 3. The content of headers is not C code (or needn't be
>> interpreted or interpretable as C code).
>
> This is correct, and is allowed by the "as if" principle in spite
> of 5.1.1.2 (which says that a header is processed from translation
> phase 1).
Your understanding of the "as if" principle, to use your phrase,
is flawed. See below.
> So #include <stdio.h> can simply flip some bits in a compiler to
> open access to ready made symbolic data structures which provide
> declarations. (And those data structures can be prepared in ways
> that don't require the processing of C source, such as by hand, or
> using a notation which is not C.)
This conclusion is based on a false assumption, and so
incorrect. See below.
>> 4. Implementations can do anything they choose upon
>> encountering a #include for a header (or equivalently
>> they can process the contents of a header any way
>> they choose).
>
> Yes, keeping in mind the introductory note that header refers to
> "standard header".
>
>> 5. What is done for a #include'd header need not be
>> documented.
>
> This is correct, and examples of this abound. Implemenations
> commonly have headers which are internal, yet accessible via the
> #include mechanism.
You are offering a proof by example, but the examples don't
matter - only what is said in the Standard matters. Any header
provided by an implementation that is #include'able qualifies as
an extension to what the Standard describes, and section 4 p8
requires implementations to document all extensions. Your
position is inconsistent with the text of the Standard.
>> 9. If I believe that what happens when a header is #include'd
>> is defined the Standard, then I don't understand what the
>> Standard is saying (and implicitly that you do).
>>
>> Is this a fair recitation of what your claims are?
>
> Pretty much.
>
>>
>> Let's take these points one by one.
>>
>> Point 1. Headers can be part of an implementation but they don't
>> have to be. Under 6.10.2 p2, where headers are searched for and
>> how they are identified is implementation-defined. If I can
>> arrange to put a header in one of the places the implementation
>> searches, which on my system I certainly can, then that header
>> will be found by a #include <whatever.h> even though <whatever.h>
>> is not part of the implmentation.
>
> I would say that you are sticking the proverbial fork in the
> toaster by doing that. This use case is not interesting to me.
> I'm concerned with the case that #include <something.h> appears in
> the progarm, and no arrangement was made to sneak such a header
> into the place which is searched by the #include <...>.
My position is that non-standard headers may be, but needn't
necessarily be, part of an implementation. Your position is that
all headers, either standard or non-standard, are always part of
said implementation. Whether this case if of interest to you or
not, it proves my point. So either you didn't understand what
point I was making, or your logic is flawed.
> There is no requirement that this be possible to do. The places
> searched by <...> could be some read-only, non-user-serviceable
> part.
That is irrelevant since it is possible to do in some cases,
which proves my point that even though headers may be part of an
implementation, they need not be part of said impementation.
(Morever they may be part of one implementation but not another
on the same system.)
>> However, if a header /is/ part of an implementation (and not a
>> standard header), then it qualifies as an extension, and under
>> section 4 p8 all extensions must be documented.
>
> This does not help you. For example, void main(void) { }
> could be considerd an extension, and documented.
>
> Or the effect of fflush(stddin).
Your logic is screwy. The Standard requires all extensions to be
documented. Here is section 4 p8 in its entirety:
An implementation shall be accompanied by a document that
defines all implementation-defined and locale-specific
characteristics and all extensions.
Notice the phrase, "all extensions". The existence of other
documented extensions doesn't remove the obligation to document
non-standard headers, if they are part of the implementation.
Any non-standard header not documented therefore cannot be part
of a conforming implementation.
> Moreover, as stated already, implementations often have undocumented
> headers which are easily found, and are reachable by #include.
Again, giving existing implementations as examples is irrelevant.
The only thing that matters is what the Standard has to say on
the subject.
> Using those headers is not only undefined behavior in the ISO C
> standard sense, it is undefined by the implementation also; it is
> reliance upon undocumented behavior.
A completely unsupported statement. The issue here is exactly
the point under discussion, so you are simply begging the
question. If you can't offer any Standard citations supporting
your comments there is no reason anyone should believe them.
>> To say that
>> another way, if an implementation does /not/ document some
>> particular (non-standard) header, then that header cannot be
>> part of the implementation.
>
> That is incorrect. That header is not part of the documented
> interface to the implementation. It may be a key component of
> the implementation such that it if is tampered with or removed,
> the implementation breaks.
Even if the last predicate is true, it doesn't remove the
obligation to document all extensions. One of three things
is always true regarding any non-standard header: (1) the
implementation documents the header; (2) the header is not
part of the implementation; or (3) the implementation is
not a conforming implementation of C. No other cases are
possible. Feel free to re-read section 4, "Conformance".
>> Point 2. Section 5.1.1.1 p1 makes clear that any #include'd
>> headers are part of, after pre-processing, the corresponding
>> translation unit, and therefore part of the C program.
>
> 5.1.1.1 does not state that that program has a well-defined
> behavior after including an unknown header.
It doesn't need to because 5.1.1.2 defines the behavior.
Furthermore the Standard never gives an explicit statement,
except non-normatively in a few examples of specific code, that
behavior under certain circumstances is defined. To do so is
redundant when the text gives the definition.
>> Point 3. Section 5.1.1.2 p1 part 4 makes clear that #include'd
>> headers are processed in exactly the same way as #include'd
>> soure files. That is, the Standard requires the implementation
>> to treat them as C code.
>
> "C code" is a troublesome term, as I pointed out elsethread.
>
> As a synonym for "material acceptable to an implementation" it is
> not a suitable choice, because material acceptable to an
> implementation may not resemble C.
Are you being obtuse? To treat something as C code is to
interpret it according to the rules of 5.1.1.1, 5.1.1.2, etc,
with all the same semantics as what the Standard decribes
for the C language. To quote from the Abstract:
This International Standard specifies the form and
establishes the interpretation of programs expressed in
the programming language C.
The sections 5.1.1.1 and 5.1.1.2 make clear that any content that
was #include'ed, whether from a header or a source file, is
treated in exactly the same way as a physical source file that is
given at the top level, ie, not #include'ed.
> I believe that 5.1.1.2 is subject to the latitude between abstract
> machine and actual implementation.
You are mistaken. The section 5.1.2.3, titled Program Execution,
gives in paragraph 1 the statement about an abstract machine.
(This section is part of 5.1.2, titled Execution Environments.)
The entire section 5.1.2 has no bearing on section 5.1.1, which
is solely about program translation, not program execution.
> Moreover, that is completely moot. Whether or not headers must be
> processed exactly as stated (read as text from translation phase
> 1) or not (could be binary files or just data structures in a
> compiler)
The claim here (specifically Point 3) is that how headers are
processed is well-defined, and that is true for all headers with
5.1.1.1 and 5.1.1.2 giving the (top level of) the definition.
You have offered no evidence to support the last parenthetical
phrasee - again begging the question.
> it doesn't rescue the claim that the behavior is
> well-defined for any header whatsoever.
>
> Either way, the proverbial header can make the proverbial demons
> fly out of your nose.
More unsupported statements, and again begging the question.
>> Point 4. Section 6.10.2 p2 says where headers are looked for
>> and how they are identified. Section 5.1.1.2 explains how they
>> must be processed. How a #include'd header is processed is just
>> as constrained, and just as defined, as #include'ing a source
>> file.
>
> My point has never revolved around any notion that the mechanism
> of inclusion is not well-defined.
Why do you keep bringing it up then?
> An easy analogy can be made here to other features, like calling a
> function, declaring a function or dereferencing a pointer.
>
> There are aspects of "void main(void) { }" or "fflush(stdin)"
> which have a well-defined description.
These comments are related to the next point, so I will
fold any responses in to those for the next section.
(There were no responses given to Points 5, 7, or 8.)
>> Point 6. No one disagrees that, if the contents of a header are
>> ill-formed then undefined behavior can result.
>
> If the contents of a header can be ill-formed or nonexistent in
> any conforming implementation, then its use is not behavior which
> is defined in the standard.
You seem to think that's synonymous with undefined behavior.
It isn't. See section 3.4.3 for the definition.
> Some aspects of the inclusion of that header are covered by
> semantic description, but not the overall operation.
>
> #include <unistd.h>
> /* X */
>
> is not required anywhere in the standard to successfully bring in
> some material, and then continue scanning at point /* X */.
That's true, but that doesn't make the #include line undefined
behavior. The #include line might _result_ in undefined
behavior, depending on the contents of <unistd.h>, but the
#include line itself is defined, not undefined. Furthermore
you snipped out the important follow-on Point 8, which
explains that if the content of <unistd.h> is well-formed,
then the behavior of #include <unistd.h> is well-defined,
in which case scanning must continue at point /* X */.
So either you don't understand my position or you are
misrepresenting it.
> I do not dispute that #include <X> is a kind of operator, and X is
> is operand, and that the operator denotes a search for something
> identified by X.
>
> Your point rests on the very incorrect notion that since there
> *can* exist content behind X defined by some implementations as a
> documented extenion, the behavior is not undefined.
Again begging the question. Either that or you are confused
about the logic involved.
Your position is that #include <unistd.h> is always undefined
behavior. My position is that #include <unistd.h> is defined
behavior if the contents of <unistd.h> is well-formed. Note that
these positions are in conflict: they can't both be true.
A good analogy here is the behavior of a call to scanf().
Depending on the arguments supplied, and the state of the input
stream, a call to scanf() can result in undefined behavior. That
doesn't mean all calls to scanf() are undefined behavior -- some
of them are, others are not. Similarly a #include <unistd.h>
might result in undefined behavior, but that doesn't mean having
a #include <unistd.h> is always undefined behavior: whether it
is or not depends on the contents of <unistd.h> (and also it
being there, which doesn't matter here since that is covered by
a constraint violation).
>> Point 9. In every point you have raised, I have responded
>> with a citation from the Standard supporting my position and
>> contradicting yours. If you can't support your position(s)
>> with some specific citations from the Standard
>
> Of course I cannot!
>
> If a behavior is undefined because it is not defined anywhere in
> the standard (not because it is a violation of a requirement, or
> explicitly described as undefined behavior), we cannot cite the
> section which makes it undefined, because there is no such
> section.
I've explained repeatedly that the semantics of such #include's
is defined in 5.1.1.1, 5.1.1.2, etc.
> If you think some text does define the meaning of #include
> <unistd.h> (the complete meaning, beyond just the mechanism of
> searching for a header), then please cite that.
The meaning is determined by the contents of the header. See
the above analogy with scanf().
> The sections you have referenced so far do not help you, because
> you're ultimately appealing to the wrong principle that content
> made available by specific implementations as a documented
> extension somehow back-propagates a definition of behavior to the
> standard; i.e. that "gcc-defined", "POSIX-defined" or
> "Ubuntu-defined" or "Intel-defined" amount to "standard defined".
Once again you have failed to give even one citation from the
Standard supporting your various positions. In contrast I have
given a citation for nearly every point responded to.
Considering all the above, I think one of two things is true (or
possibly both points are true, but no matter). Either you are
confused about the meaning of the phrase "undefined behavior", or
you have just made up your mind and are attempting to supply a
Proof by Repeated Assertion. So I hope if you respond you'll
have something new to offer rather than just more unsupported
statements.