Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #380545 > unrolled thread

Re: Effect of CPP tags

Started byTim Rentsch <tr.17687@z991.linuxsc.com>
First post2024-01-20 14:29 -0800
Last post2024-02-11 17:38 -0800
Articles 14 — 5 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-20 14:29 -0800
    Re: Effect of CPP tags Kaz Kylheku <433-929-6894@kylheku.com> - 2024-01-21 04:46 +0000
      Re: Effect of CPP tags James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-01-21 10:56 -0500
      Re: Effect of CPP tags James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-01-21 12:11 -0500
        Re: Effect of CPP tags Kaz Kylheku <433-929-6894@kylheku.com> - 2024-01-21 17:55 +0000
          Re: Effect of CPP tags James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-01-21 21:57 -0500
            Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-24 07:42 -0800
          Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-31 12:43 -0800
            Re: Effect of CPP tags Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-01-31 13:41 -0800
              Re: Effect of CPP tags David Brown <david.brown@hesbynett.no> - 2024-02-01 09:19 +0100
              Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-03-14 23:11 -0700
                Re: Effect of CPP tags Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-03-14 23:56 -0700
              Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-03-14 23:12 -0700
      Re: Effect of CPP tags Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-02-11 17:38 -0800

#380545 — Re: Effect of CPP tags

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-01-20 14:29 -0800
SubjectRe: Effect of CPP tags
Message-ID<86y1cjiqpu.fsf@linuxsc.com>
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> [...]  Just including <unistd.h> has undefined behavior as far as
> ISO C is concerned, [...]

Not true.  The behavior of #include <unistd.h> is defined in
section 6.10.2 p2.  One of two things is true:  either the header
named is part of the implementation, or it isn't.  If the named
header is part of the implementation, then it constitutes a
language extension, and so it must be documented (and defined).
If the named header is not part of the implementation, it still
must be a header that the implementation can process (because of
the constraint in 6.10.2 p1), and it must be processed the same
way as a header that is part of the implementation (because of
how the behavior is defined in 6.10.2 p2).  Implementations are
not at liberty to do anything they want just because the header
named is not part of the implementation;  such headers must be
processed in just the same way as standard or extension headers,
no matter how it is that they happen to be in the set of places
the implementation has defined (and documented) to hold headers.

[toc] | [next] | [standalone]


#380557

FromKaz Kylheku <433-929-6894@kylheku.com>
Date2024-01-21 04:46 +0000
Message-ID<20240120203343.615@kylheku.com>
In reply to#380545
On 2024-01-20, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>
>> [...]  Just including <unistd.h> has undefined behavior as far as
>> ISO C is concerned, [...]
>
> Not true.  The behavior of #include <unistd.h> is defined in
> section 6.10.2 p2.  One of two things is true:  either the header
> named is part of the implementation, or it isn't.  If the named
> header is part of the implementation, then it constitutes a
> language extension, and so it must be documented (and defined).

The problem with this reasoning is 

1. Implementations in fact have internal headers that are not
documented, and which are not supposed to be included directly. 
You will not get documentation for every single header that
is accessible via #include, and it is not reasonable for ISO C to
require it. I don't see where it does.

2. A documented extension continues to be undefined behavior.
The behavior is "defined", but not "ISO C defined". So even
if all the implementation's internal headers were documented
as extensions, their use would still be UB.

Undefined behavior is for which "this document imposes not
requirements", right?

It is not behavior for which "this document, together with the
ocumentation accompanying a given implementation, imposes
no requirements". Just "this document" (and no other).

If "this document" imposes no requirements, it's "undefined behavior",
no matter who or what imposes additional requirements!

Intuitively, a header which is part of an implementation can do
anything.  For instance #include <pascal.h> can cause the rest of the
translation unit to be analyzed as Pascal syntax, and not C.

An implementation can provide a header <reboot.h>, including
which causes a reboot at compile time, link time, or
execution time.

If such headers happen to exist, what in the standard is violated?

I used to experience a lot of push-back against the above views,
but I'm seeing that people are coming around.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

[toc] | [prev] | [next] | [standalone]


#380571

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2024-01-21 10:56 -0500
Message-ID<uojes7$7nc8$1@dont-email.me>
In reply to#380557
On 1/20/24 23:46, Kaz Kylheku wrote:
> On 2024-01-20, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
...
>> named is part of the implementation, or it isn't. If the named
>> header is part of the implementation, then it constitutes a
>> language extension, and so it must be documented (and defined).
>
> The problem with this reasoning is
> 1. Implementations in fact have internal headers that are not
> documented, and which are not supposed to be included directly. You
> will not get documentation for every single header that
> is accessible via #include, and it is not reasonable for ISO C to
> require it. I don't see where it does.

"An implementation shall be accompanied by a document that defines all
implementation-defined and locale-specific characteristics and all
extensions." 4p9

[toc] | [prev] | [next] | [standalone]


#380573

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2024-01-21 12:11 -0500
Message-ID<uojj7p$8crh$1@dont-email.me>
In reply to#380557
Initially, I accidentally sent my response as private e-mail to Kaz
rather than to the group. With his permission, here's the response he sent:

On 1/21/24 01:37, Kaz Kylheku wrote:
> On 2024-01-20 21:50, James Kuyper wrote:
>> "An implementation shall be accompanied by a document that defines all
>> implementation-defined and locale-specific characteristics and all
>> extensions." 4p9
> That sentence says something subtly different from something like
> "an implementation shall document everything that looks stable enough
> to be an extension".
>
> It is saying that there is required to be a document, and that in
> that document there may be a list of one or more extensions.
>
> The standard is defining the *fact* that this list is exhaustive:
> it comprises all the extensions that are offered in the contract
> between implementor and programmer.
>
> Thus, for instance, if programmers empirically discover a behavior
> which is not defined by ISO C, and which is not in that list,
> it is not an extension. The standard states that that list has
> all the extensions, and that discovered feature is not on it.
>
> The sentence does not require implementors to document,
> as an extension, every header file that is reachable by an #include
> directive.
The standard doesn't provide a definition for "extension", though it
makes many uses of the term, identifying a variety of things as possible
or common extensions to C. What you're saying is, essentially, that
extensions are defined as such by the fact that they are listed as such
in that document. The biggest problem I have with that is that ISO has a
convention that allows them to say just that - all they would have had
to do is put "extension" in italics in 4p9, and that would identify the
sentence in which it occurs as the definition of the term. They didn't
choose to do so. I concede that they might not have thought of doing so.

However, it seems more reasonable to me that whether or not something is
an extension is not supposed to be up to the implementor to decide.
Instead, anything that is an extension must be listed. This would be an
easier interpretation to defend if there were any explicit definition of
"extension" in the standard.

[toc] | [prev] | [next] | [standalone]


#380576

FromKaz Kylheku <433-929-6894@kylheku.com>
Date2024-01-21 17:55 +0000
Message-ID<20240121094637.874@kylheku.com>
In reply to#380573
On 2024-01-21, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
> However, it seems more reasonable to me that whether or not something is
> an extension is not supposed to be up to the implementor to decide.
> Instead, anything that is an extension must be listed. This would be an
> easier interpretation to defend if there were any explicit definition of
> "extension" in the standard.

The implication is that anything that works by accident must be listed
as an extension. If function arguments happen to be evaluated left to
right, with all side effects complete between them, this has to be
listed as an extension. Then in the future when the vendor finds that
inconvenient for further compiler work, they have to take away the
extension.

I don't see how it can not be the implementor's privilege to assert what
is reliable for use and documented, versus what is not.

Unless they have some legal contract with particular customers,
requiring certain things be provided.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

[toc] | [prev] | [next] | [standalone]


#380607

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2024-01-21 21:57 -0500
Message-ID<uoklil$et2j$2@dont-email.me>
In reply to#380576
On 1/21/24 12:55, Kaz Kylheku wrote:
> On 2024-01-21, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> However, it seems more reasonable to me that whether or not something is
>> an extension is not supposed to be up to the implementor to decide.
>> Instead, anything that is an extension must be listed. This would be an
>> easier interpretation to defend if there were any explicit definition of
>> "extension" in the standard.
> 
> The implication is that anything that works by accident must be listed
> as an extension. If function arguments happen to be evaluated left to
> right, with all side effects complete between them, this has to be
> listed as an extension. Then in the future when the vendor finds that
> inconvenient for further compiler work, they have to take away the
> extension.

No, that's unspecified behavior, if 4p9 were intended to be understood
as mandating documentation of all unspecified behavior, it would make
the category of implementation-defined behavior redundant.

Since extensions are also explicitly prohibited from changing the
behavior of strictly conforming code, I think that in order for
something qualify as an extension, it has to define behavior that the
standard leaves undefined. In a certain sense, every implementation
implicitly defines that behavior - whatever it is that actually happens
when the behavior is undefined is that definition. However, I think an
extension should have to be explicitly activated by some deliberate user
choice, such as a compiler option or by defining the behavior of some
kinds of syntax not allowed by the C standard. That's just IMHO, of
course - in the absence of a explicit definition in the standard, it's
hard to be sure what the committee intended.

[toc] | [prev] | [next] | [standalone]


#380797

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-01-24 07:42 -0800
Message-ID<86il3ieo0t.fsf@linuxsc.com>
In reply to#380607
James Kuyper <jameskuyper@alumni.caltech.edu> writes:

> On 1/21/24 12:55, Kaz Kylheku wrote:
>
>> On 2024-01-21, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>>
>>> However, it seems more reasonable to me that whether or not
>>> something is an extension is not supposed to be up to the
>>> implementor to decide.  Instead, anything that is an extension
>>> must be listed.  This would be an easier interpretation to defend
>>> if there were any explicit definition of "extension" in the
>>> standard.
>>
>> The implication is that anything that works by accident must be
>> listed as an extension.  If function arguments happen to be
>> evaluated left to right, with all side effects complete between
>> them, this has to be listed as an extension.  Then in the future
>> when the vendor finds that inconvenient for further compiler work,
>> they have to take away the extension.
>
> No, that's unspecified behavior, if 4p9 were intended to be
> understood as mandating documentation of all unspecified behavior,
> it would make the category of implementation-defined behavior
> redundant.

Quite so.

> Since extensions are also explicitly prohibited from changing the
> behavior of strictly conforming code, I think that in order for
> something qualify as an extension, it has to define behavior that
> the standard leaves undefined.

The essential property of an extension is that it must specify a
language feature or library feature that is not specified in the C
standard.  Implementations are free to /define/ undefined behavior
any way they want, and doing so doesn't require an extension;  the
point of documenting an extension is to /specify what happens/ in
certain cases, which also means giving a guarantee that what is
documented is what will happen (with the understanding that the
guarantee is only that the implementation will make its best
efforts to do so, because some results are outside of an
implementation's ability to control).

(I note in passing that an odd consequence of how the C standard
uses certain terminology is that "defining" something doesn't stop
it from being "undefined".  The term "undefined behavior" is thus
something of a misnomer.  But I digress.)

Conversely, an extension can specify a feature that is not, or
might not be, undefined behavior, but still needs to be documented
as an extension.  For example

    #include <foo.h>

is not undefined behavior, but must be documented as an extension
if the header <foo.h> is part of the implementation, because what
is in the header <foo.h> is not specified in the C standard.
Similarly, a declaration like

    typedef __uint128_t U128;

is not necessarily undefined behavior, because implementations are
free to define reserved identifiers any way they wish.  But if it's
important that it work, then it must be documented as an extension,
as otherwise an implementation is free to reject it by virtue of
using a language feature not specified in the C standard (which
therefore means the program is not strictly conforming, and so can
be rejected).

> In a certain sense, every
> implementation implicitly defines that behavior - whatever it is
> that actually happens when the behavior is undefined is that
> definition.  However, I think an extension should have to be
> explicitly activated by some deliberate user choice, such as a
> compiler option or by defining the behavior of some kinds of
> syntax not allowed by the C standard.  That's just IMHO, of course
> - in the absence of a explicit definition in the standard, it's
> hard to be sure what the committee intended.

That's a QOI issue.  I'm not convinced that it's a good idea in
all cases.  For example, either of the two cases mentioned above:

    #include <foo.h>

    typedef __uint128_t U128;

do not IMO need an explicit user action to activate, because it's
obvious they are making use of extensions, and are pretty unlikely
to occur by accident.  I concede however that other people may
reasonably hold other views on that question.

[toc] | [prev] | [next] | [standalone]


#381406

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-01-31 12:43 -0800
Message-ID<86wmrp9qt8.fsf@linuxsc.com>
In reply to#380576
Kaz Kylheku <433-929-6894@kylheku.com> writes:

> On 2024-01-21, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>
>> However, it seems more reasonable to me that whether or not something is
>> an extension is not supposed to be up to the implementor to decide.
>> Instead, anything that is an extension must be listed.  This would be an
>> easier interpretation to defend if there were any explicit definition of
>> "extension" in the standard.
>
> The implication is that anything that works by accident must be
> listed as an extension.  If function arguments happen to be
> evaluated left to right, with all side effects complete between
> them, this has to be listed as an extension.  Then in the future
> when the vendor finds that inconvenient for further compiler work,
> they have to take away the extension.
>
> I don't see how it can not be the implementor's privilege to
> assert what is reliable for use and documented, versus what is
> not.

It's important to understand what constitutes an extension.  And
there are different kinds of extensions.

If an implementation chooses, say, to evaluate function arguments
always left-to-right, that is perfectly okay (and need not be an
extension).  But if an there is to be a /guarantee/ that function
arguments will always be evaluated left-to-right, that means
providing a guarantee that the C standard does not;  thus we have an
extension (to the requirements in the C standard), and the extension
must be documented.  This case is one kind of extension.

If an implementation chooses to alter the semantics of, for example,
an extern declaration inside a function body, so that the declared
identifier has file scope rather than block scope, that is a
different kind of extension.  At the point of the extern declaration
we can't actually detect any difference.  A subsequent use, however,
outside the function body, would normally be a constraint violation
and so require a diagnostic, but under the altered semantics the
identifier has already been declared and so no diagnostic is needed.
(Note that this behavior is one of the cases listed in Annex J.5,
"Common extensions".)  This example illustrates a second kind of
extension, and they always must be documented as such.

If an implementation chooses to define, for example, __uint128_t to
be the name of an integer type, that represents a third kind of
extension.  (Annex J.5 also mentions such definitions as an example
on its list of "Common extensions".)  Such cases must be documented
as extensions because, one, the expected default is that there be no
definition (which normally would cause a diagnostic because of some
constraint violation), and two, only the implementation is in a
position to know if the symbol in question was defined by the
implementation or by something else.  Clearly any definition the
implementation provides signals a change from the expected default,
which by any reasonable definition of the word constitutes an
extension, and hence must be documented.

[toc] | [prev] | [next] | [standalone]


#381412

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-01-31 13:41 -0800
Message-ID<87cythrxip.fsf@nosuchdomain.example.com>
In reply to#381406
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Kaz Kylheku <433-929-6894@kylheku.com> writes:
> It's important to understand what constitutes an extension.  And
> there are different kinds of extensions.
>
> If an implementation chooses, say, to evaluate function arguments
> always left-to-right, that is perfectly okay (and need not be an
> extension).  But if an there is to be a /guarantee/ that function
> arguments will always be evaluated left-to-right, that means
> providing a guarantee that the C standard does not;  thus we have an
> extension (to the requirements in the C standard), and the extension
> must be documented.  This case is one kind of extension.

If an implementation chooses to guarantee left-to-right evaluation, I
don't see anything in the standard that requires that guarantee to be
documented.  (Of course it can and should be.)

It's not entirely clear to me exactly what must or must not be
considered to be an "extension" as the C standard uses the term.  The
standard doesn't show the word "extension" in italics or provide a
definition in section 3.

Unless your point is that it's not a guarantee unless it's documented?
But I don't see that that documentation is required *by the standard*.

[...]

> If an implementation chooses to define, for example, __uint128_t to
> be the name of an integer type, that represents a third kind of
> extension.  (Annex J.5 also mentions such definitions as an example
> on its list of "Common extensions".)  Such cases must be documented
> as extensions because, one, the expected default is that there be no
> definition (which normally would cause a diagnostic because of some
> constraint violation), and two, only the implementation is in a
> position to know if the symbol in question was defined by the
> implementation or by something else.  Clearly any definition the
> implementation provides signals a change from the expected default,
> which by any reasonable definition of the word constitutes an
> extension, and hence must be documented.

Again, that can and should be documented, but since any use of the
identifer __uint128_t has undefined behavior, I don't see any
requirement in the standard that it must be documented.

(Aside: gcc has an extension adding __int128 as a keyword, supporting
types "__int128" and "unsigned __int128", but only on some target
systems.  These do not qualify as extended integer types.  I understand
that "__uint128_t" was a hypothetical example.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#381442

FromDavid Brown <david.brown@hesbynett.no>
Date2024-02-01 09:19 +0100
Message-ID<upfk6t$1vt73$1@dont-email.me>
In reply to#381412
On 31/01/2024 22:41, Keith Thompson wrote:
> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>> Kaz Kylheku <433-929-6894@kylheku.com> writes:
>> It's important to understand what constitutes an extension.  And
>> there are different kinds of extensions.
>>
>> If an implementation chooses, say, to evaluate function arguments
>> always left-to-right, that is perfectly okay (and need not be an
>> extension).  But if an there is to be a /guarantee/ that function
>> arguments will always be evaluated left-to-right, that means
>> providing a guarantee that the C standard does not;  thus we have an
>> extension (to the requirements in the C standard), and the extension
>> must be documented.  This case is one kind of extension.
> 
> If an implementation chooses to guarantee left-to-right evaluation, I
> don't see anything in the standard that requires that guarantee to be
> documented.  (Of course it can and should be.)
> 

I would say that a "guarantee" is a promise - in this case, from the 
compiler writers to compiler users.  It's not a guarantee if they don't 
tell anyone!  Then it's just an implementation detail.  But I don't see 
that it has to be documented in any particular way, or called an 
"extension".  IIRC MSVC's "guarantee" that it won't use type-based alias 
analysis for optimisation (and thus casting between pointer types will 
work as some people think they should work) is "documented" in a blog 
post by one of the compiler developers.

Of course it is up to the user to decide how much they trust the 
guaranteed additional behaviour.  A mailing list post with "We'll 
evaluate left to right, or your money back!" or a note in a blog page 
would probably not inspire as much confidence as clear information in 
the main reference documentation for a compiler.

[toc] | [prev] | [next] | [standalone]


#383629

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-03-14 23:11 -0700
Message-ID<867ci4owhc.fsf@linuxsc.com>
In reply to#381412
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Kaz Kylheku <433-929-6894@kylheku.com> writes:
>> It's important to understand what constitutes an extension.  And
>> there are different kinds of extensions.
>>
>> If an implementation chooses, say, to evaluate function arguments
>> always left-to-right, that is perfectly okay (and need not be an
>> extension).  But if an there is to be a /guarantee/ that function
>> arguments will always be evaluated left-to-right, that means
>> providing a guarantee that the C standard does not;  thus we have an
>> extension (to the requirements in the C standard), and the extension
>> must be documented.  This case is one kind of extension.
>
> If an implementation chooses to guarantee left-to-right evaluation, I
> don't see anything in the standard that requires that guarantee to be
> documented.  (Of course it can and should be.)
>
> It's not entirely clear to me exactly what must or must not be
> considered to be an "extension" as the C standard uses the term.  The
> standard doesn't show the word "extension" in italics or provide a
> definition in section 3.
>
> Unless your point is that it's not a guarantee unless it's documented?
> But I don't see that that documentation is required *by the standard*.

It seems likely that we have different notions of what "a guarantee"
is.  As I am using the term it does not mean a statement of what
does happen but a promise for what will happen.  Consulting some
online dictionaries, I find the following definitions (among others
that for the most part are not relevant).  Note that all of these
are for "guarantee" used as a noun (presented in the order of
shortest first):

    an assurance for the fulfillment of a condition

    Something that assures a particular outcome or condition.

    A pledge that something will be performed in a specified
    manner.

    an unconditional commitment that something will happen or
    that something is true

    a written assurance that some product or service will be
    provided or will meet certain specifications

    A promise or assurance, especially one given in writing, that
    attests to the quality or durability of a product or service.

    a promise or assurance, especially one in writing, that
    something is of specified quality, content, benefit, etc.,
    or that it will perform satisfactorily for a given length of
    time:  "a money-back guarantee".

In the context of a C implementation, for some condition to be a
guarantee I would say it must be written down (which is to say,
documented), as otherwise it doesn't qualify as a guarantee.  In
any case that is how I am using the term.

Incidentally, as best I can determine the C standard uses the
term "guarantee" as a noun in only one place in normative text
(6.5.2.3 p6) and in two places in informative text (5.1.2.4 p23
and a footnote to 7.22.2.1 p2).  Various forms of "guarantee"
used as a verb appear in the C standard in lots of places.  I am
specifically using the noun form in my comments here.

I think most people would agree that any documented guarantee of
behavior beyond what the C standard requires of all implementations
(and is not part of the documentation for implementation-defined
behaviors) qualifies as an extension to the C language, and thus
should be considered an extension as the ISO C standard uses the
term, given that the C standard itself does not define the term
but (one assumes) uses the word in its ordinary English sense.
   

> [...]
>
>> If an implementation chooses to define, for example, __uint128_t to
>> be the name of an integer type, that represents a third kind of
>> extension.  (Annex J.5 also mentions such definitions as an example
>> on its list of "Common extensions".)  Such cases must be documented
>> as extensions because, one, the expected default is that there be no
>> definition (which normally would cause a diagnostic because of some
>> constraint violation), and two, only the implementation is in a
>> position to know if the symbol in question was defined by the
>> implementation or by something else.  Clearly any definition the
>> implementation provides signals a change from the expected default,
>> which by any reasonable definition of the word constitutes an
>> extension, and hence must be documented.
>
> Again, that can and should be documented, but since any use of the
> identifer __uint128_t has undefined behavior,

That isn't right.  The C standard says that declaring or defining a
reserved identifier is undefined behavior.  The C standard does NOT
say that using a reserved identifier is undefined behavior.  If an
implementation does not define an identifier like __uint128_t, then
any use in ordinary code (that is, not part of a pre-processor
directive) should produce a diagnostic due to a syntax or constraint
violation.  If we don't get a diagnostic we know that the identifier
/must/ have been defined by the implementation, and because it is a
change in behavior over standard C it must be documented as an
extension.

(Note added during editing:  "any use in ordinary code" is meant in
the sense of "a use that is not a declaration or definition".)

> I don't see any
> requirement in the standard that it must be documented.

It must be documented because it represents a change in behavior
over what the C standard requires, and any such change constitutes
an extension to the language, and the C standard requires extensions
to be documented.

> (Aside: gcc has an extension adding __int128 as a keyword, supporting
> types "__int128" and "unsigned __int128", but only on some target
> systems.  These do not qualify as extended integer types.  I understand
> that "__uint128_t" was a hypothetical example.)

On the systems I use the identifiers __int128_t and __uint128_t are
both predefined type names (and not keywords), under both gcc and
clang.  I see some support for __int128 as a keyword, but the
predefined type names seem to be more reliable (at least in my
environments).

[toc] | [prev] | [next] | [standalone]


#383631

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-03-14 23:56 -0700
Message-ID<874jd83rw4.fsf@nosuchdomain.example.com>
In reply to#383629
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
>> (Aside: gcc has an extension adding __int128 as a keyword, supporting
>> types "__int128" and "unsigned __int128", but only on some target
>> systems.  These do not qualify as extended integer types.  I understand
>> that "__uint128_t" was a hypothetical example.)
>
> On the systems I use the identifiers __int128_t and __uint128_t are
> both predefined type names (and not keywords), under both gcc and
> clang.  I see some support for __int128 as a keyword, but the
> predefined type names seem to be more reliable (at least in my
> environments).

That's odd.  The gcc documentation describes __int128 as an extension:
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/_005f_005fint128.html

    As an extension the integer scalar type __int128 is supported for
    targets which have an integer mode wide enough to hold 128
    bits. Simply write __int128 for a signed 128-bit integer, or
    unsigned __int128 for an unsigned 128-bit integer. There is no
    support in GCC for expressing an integer constant of type __int128
    for targets with long long integer less than 128 bits wide.

It doesn't mention __int128_t or __uint128_t at all, though I see it
does recognize both, and as you say it doesn't treat them as keywords.
Likewise for clang, though I haven't checked the clang documentation.

(I might reply to other parts of your post later.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#383630

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-03-14 23:12 -0700
Message-ID<8634ssowfk.fsf@linuxsc.com>
In reply to#381412
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

[...]

P.S.  My apologies for not responding to your posting earlier.

[toc] | [prev] | [next] | [standalone]


#382356

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-02-11 17:38 -0800
Message-ID<86bk8m4g36.fsf@linuxsc.com>
In reply to#380557
Kaz Kylheku <433-929-6894@kylheku.com> writes:

> On 2024-01-20, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> [...]  Just including <unistd.h> has undefined behavior as far as
>>> ISO C is concerned, [...]
>>
>> Not true.  The behavior of #include <unistd.h> is defined in
>> section 6.10.2 p2.  One of two things is true:  either the header
>> named is part of the implementation, or it isn't.  If the named
>> header is part of the implementation, then it constitutes a
>> language extension, and so it must be documented (and defined).
>
> The problem with this reasoning is
>
> 1. Implementations in fact have internal headers that are not
> documented, and which are not supposed to be included directly.
> You will not get documentation for every single header that
> is accessible via #include, and it is not reasonable for ISO C to
> require it.  I don't see where it does.

First, James Kuyper already identified section 4 paragraph 9.

Second, implementations do have lots of internal headers that are
not meant to be included directly, but just because such headers
exist doesn't mean they can be #include'd.  Consider these lines
at the start of <bits/byteswap.h>

 #if !defined _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H
 # error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
 #endif

Clearly implementations can and do distinguish between headers
that are meant to be user #include-able and those that are not,
and take steps to protect the hidden ones.  It seems obvious
that implementations consider it reasonable to document headers
that are meant to be user #include-able, and to protect the
hidden headers so they can't be #included directly, because
that is what existing implementations do.

> 2. A documented extension continues to be undefined behavior.
> The behavior is "defined", but not "ISO C defined".  So even
> if all the implementation's internal headers were documented
> as extensions, their use would still be UB.
>
> Undefined behavior is for which "this document imposes not
> requirements", right?
>
> It is not behavior for which "this document, together with the
> ocumentation accompanying a given implementation, imposes
> no requirements".  Just "this document" (and no other).
>
> If "this document" imposes no requirements, it's "undefined
> behavior", no matter who or what imposes additional requirements!

Your logic here is all messed up.  The very first sentence uses
circular reasoning.  Next you ignore the point that the "define" in
section 4 paragraph 9 is a Standard-imposed requirement, and surely
the Standard means to require that implementations obey their own
definitions, because that's what "define" means.  The idea that
having to document extensions doesn't imply an ISO C requirement is
just being obtuse.

Perhaps a more fundamental flaw is you have the key implication
backwards.  IF using a particular program construct or data value
has been identified as undefined behavior, THEN the C standard
imposes no requirements on those uses.  The implication doesn't go
the other way.  For example, the C standard imposes no requirements
for what happens on Tuesdays.  That does not mean that compiling a
program on a Tuesday is undefined behavior.  The universe of
discourse is program constructs and data values ("values" here also
includes things such as trap representations).  Saying "an unknown
header is undefined behavior" is meaningless, because it's outside
the universe of discourse, just like Tuesdays are.  The C construct
in question is "#include <unistd.h>", and the C standard defines
behavior for that construct.

> Intuitively, a header which is part of an implementation can do
> anything.  For instance #include <pascal.h> can cause the rest of
> the translation unit to be analyzed as Pascal syntax, and not C.
>
> An implementation can provide a header <reboot.h>, including
> which causes a reboot at compile time, link time, or
> execution time.
>
> If such headers happen to exist, what in the standard is violated?

More bad logic.  Of course the contents of a header or #include'd
file can have, for example, syntax errors, that result in crossing
the line into undefined behavior.  The question is not whether an
unknown header /can/ cross the line into undefined behavior but
whether it /must/ cross that line.  Whether a #include of an unknown
header encounters undefined behavior depends on the contents of the
header, and nothing else.  A #include <unistd.h> MIGHT cross the
line into UB land, but there is nothing that says it MUST cross that
line.

Note by the way that exactly the same reasoning applies to an
unknown source file, such as #include "foo.h".  If we don't know
what's in foo.h (maybe it was left by a hacker in a little-used
byway of where the implementation looks for #include'd source
files), then undefined behavior is possible, but whether UB
actually happens depends only on the contents of the file, not on
whether we know what's in it.

> I used to experience a lot of push-back against the above views,
> but I'm seeing that people are coming around.

I expect that is simply a consequence of your dogged persistence
and the brighter people dropping out of the conversations.  It's
not whether some people start to be convinced, but rather which
people are convinced, and how firmly convinced, and why.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web