public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception.
@ 2024-03-28 22:00 kkylheku at gmail dot com
  2024-03-28 22:03 ` [Bug c/114526] " pinskia at gcc dot gnu.org
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-03-28 22:00 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

            Bug ID: 114526
           Summary: ISO C does not prohibit extensions: fix misconception.
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kkylheku at gmail dot com
  Target Milestone: ---

There seems to be a historic misconception in the development of GCC that the C
standard prohibits extensions. The -Wpedantic/-pedantic options are
unfortunately organized around this false idea.

Firstly, for a bit of background, in the GNU Coding Standards document we have
this:

> But we do not follow either of these specifications rigidly,
> and there are specific points on which we decided not to
> follow them, so as to make the GNU system better for users.
>
> For instance, Standard C says that nearly all extensions to C
> are prohibited. How silly! GCC implements many extensions,
> some of which were later adopted as part of the standard.
> If you want these constructs to give an error message as
> “required” by the standard, you must specify ‘--pedantic’,
> which was implemented only so that we can say “GCC is a 100%
> implementation of the standard”, not because there is any
> reason to actually use it. 

[https://www.gnu.org/prep/standards/standards.html]

I suspect this might have been written, at some point, by someone actually
working on the design of GCC. Or at least believing the GCC documentation.

The GCC man page contains text which propagates the same falsehood, claiming
that the -Wpedantic/-pedantic options "[i]ssue all the warnings demanded by
strict ISO C and ISO C++; reject all programs that use forbidden extensions,
and some other programs that do not follow ISO C and ISO C++." The same text
appears in the main documentation.

This is false; there are no forbidden extensions. There are conforming
extensions and nonconforming extensions. Nonconforming extensions are those
that require a diagnostic if interpreted as ISO C, due to using new syntax or
anything else diagnosable.

Probably, -pedantic mode should only stick to emitting required diagnostics.
For instance if program uses a nonconforming extension then -pedantic should
cause that to be diagnosed (while continuing to accept the GNU extension, if
it's just a warning).

The following diagnostics have a wording which perpetrates the falsehood that
extensions are forbidden:

> warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
> warning: ISO C forbids conversion of object pointer to function pointer type [-Wpedantic]

ISO C forbids no not such thing, and requires no diagnostic. 

It is a conforming extension in GCC, allowed by the standard, and even required
by POSIX (so that the result of dlsym can be usefully converted to a function
pointer).

Diagnostics which warn about conforming extensions (and reject programs when
warnings are treated as errors) arguably have no place in -pedantic mode. (They
can stand on their own, or be put into some other special category.)

The incorrect claims in the documentation should be removed, and pedantic
mode's focus should be diagnosing situations where ISO C requires a diagnostic
but GCC doesn't emit one by default.

Wording in diagnostics which claims that ISO C forbids something should
likewise be revised; people read these statements and take them to be true!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
@ 2024-03-28 22:03 ` pinskia at gcc dot gnu.org
  2024-03-28 22:06 ` pinskia at gcc dot gnu.org
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-03-28 22:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
https://gcc.gnu.org/legacy-ml/gcc-patches/2004-01/msg00599.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
  2024-03-28 22:03 ` [Bug c/114526] " pinskia at gcc dot gnu.org
@ 2024-03-28 22:06 ` pinskia at gcc dot gnu.org
  2024-03-28 22:33 ` kkylheku at gmail dot com
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-03-28 22:06 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |DUPLICATE

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Actually it is a required diagnostic. See PR 11234 for explanation on how. This
was changed a little over 20 years ago explictly to reject this because it is
invalid C.

*** This bug has been marked as a duplicate of bug 11234 ***

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
  2024-03-28 22:03 ` [Bug c/114526] " pinskia at gcc dot gnu.org
  2024-03-28 22:06 ` pinskia at gcc dot gnu.org
@ 2024-03-28 22:33 ` kkylheku at gmail dot com
  2024-03-29  0:27 ` harald at gigawatt dot nl
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-03-28 22:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #3 from Kaz Kylheku <kkylheku at gmail dot com> ---
(In reply to Andrew Pinski from comment #2)
> Actually it is a required diagnostic. See PR 11234 for explanation on how.
> This was changed a little over 20 years ago explictly to reject this because
> it is invalid C.
> 
> *** This bug has been marked as a duplicate of bug 11234 ***

This bug report is more than about the specific warning about conversion of
function and object pointers.

It's about all/any options that don't belong in -pedantic; and about false
sentences in diagnostics and documentation.

Now, a conversion between a function and object pointer requires no diagnostic
if the required cast is present. Either way, it is undefined behavior.

I'm referencing the N3220 draft.

The 6.3 Conversions sections lists, in 6.3.2.3 Pointers, various possible
conversions among pointers. Conversions between pointers to object types and to
function types are not mentioned.

It has always been like that going back to ISO C 90 and ANSI C.

As an extension, not only is it not forbidden, but it is listed in an Appendix
as a common extension. In the N3220 draft we have:

  J.5.8 Function pointer casts

  A pointer to an object or to void may be cast to a pointer to a function,
  allowing data to be invoked as a function (6.5.5).

A diagnostic is required if a pointer to function is converted to an object
pointer, without a cast.

  6.5.5 Cast Operators

  Constraints

  ...

  Conversions that involve pointers, other than where permitted by the
  constraints of 6.5.17.2, shall be specified by means of an explicit cast.  

If a cast is present, the constraint is satisfied; the conversion is no longer
implicit but explicit. No other constraints apply to the conversion. In fact no
other requirements at all, since it is not defined.

GCC provides the common extension described in J.5.8. It is conforming; nothing
needs to be diagnosed about a program which uses it. It, and other extensions,
must not be called "forbidden".

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (2 preceding siblings ...)
  2024-03-28 22:33 ` kkylheku at gmail dot com
@ 2024-03-29  0:27 ` harald at gigawatt dot nl
  2024-03-29  1:20 ` jsm28 at gcc dot gnu.org
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-03-29  0:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

Harald van Dijk <harald at gigawatt dot nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |harald at gigawatt dot nl

--- Comment #4 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Andrew Pinski from comment #2)
> Actually it is a required diagnostic.

It is not.

> See PR 11234 for explanation on how.

As acknowledged by PR 11234's reporter in his comment #10 there, the
description of the bug explains why such code is undefined, but not why it
violates any syntax rule or constraint. Indeed, it violates no syntax rule or
constraint and accordingly no diagnostic is required, the reporter has since
agreed.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (3 preceding siblings ...)
  2024-03-29  0:27 ` harald at gigawatt dot nl
@ 2024-03-29  1:20 ` jsm28 at gcc dot gnu.org
  2024-03-29  1:23 ` harald at gigawatt dot nl
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: jsm28 at gcc dot gnu.org @ 2024-03-29  1:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #5 from Joseph S. Myers <jsm28 at gcc dot gnu.org> ---
The -pedantic documentation was updated to reflect reality - that the option is
about more than just when diagnostics are required by ISO C ("forbidden
extensions" can be taken, in the C case, as meaning those that involve
constraint violations or are outside the standard C syntax) but covers some
other programs doing things not defined in ISO C as well - in commit
074e95e34275d72664f997ed949d9c91e37cd6ee (July 2000). I don't think any
possible narrower intent there may have been long before then is particularly
relevant now.

It may well be the case that for certain diagnostics for things that do not
violate constraints or syntax rules, "ISO C does not define" or "is a GNU
extension" or similar would be better wording.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (4 preceding siblings ...)
  2024-03-29  1:20 ` jsm28 at gcc dot gnu.org
@ 2024-03-29  1:23 ` harald at gigawatt dot nl
  2024-03-29  3:07 ` kkylheku at gmail dot com
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-03-29  1:23 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #6 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Joseph S. Myers from comment #5)
> The -pedantic documentation was updated to reflect reality - that the option
> is about more than just when diagnostics are required by ISO C ("forbidden
> extensions" can be taken, in the C case, as meaning those that involve
> constraint violations or are outside the standard C syntax) but covers some
> other programs doing things not defined in ISO C as well - in commit
> 074e95e34275d72664f997ed949d9c91e37cd6ee (July 2000). I don't think any
> possible narrower intent there may have been long before then is
> particularly relevant now.

Actually, the narrower intent is still documented at
<https://gcc.gnu.org/onlinedocs/gcc/Warnings-and-Errors.html>. Arguably, this
behaviour makes -ansi -pedantic-errors a non-conforming implementation because
it rejects code that is only undefined at runtime, which ISO C requires
implementations to accept unless the implementation can prove the code is
reached.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (5 preceding siblings ...)
  2024-03-29  1:23 ` harald at gigawatt dot nl
@ 2024-03-29  3:07 ` kkylheku at gmail dot com
  2024-04-02 16:04 ` jsm28 at gcc dot gnu.org
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-03-29  3:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #7 from Kaz Kylheku <kkylheku at gmail dot com> ---
Also, it would be useful for the documentation to list all the -W-* options
that are implied by -Wpedantic.

The function/object pointer conversion diagnostics, unfortunately, are tied to
-Wpedantic itself, which is unhelpful.

-Wpedantic serves both as a diagnostic option, and a container for diagnostic
options. E.g if you don't want the extension of void * pointer arithmetic, you
can use -Wpointer-arith to diagnose it; that is turned on by -Wpedantic.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (6 preceding siblings ...)
  2024-03-29  3:07 ` kkylheku at gmail dot com
@ 2024-04-02 16:04 ` jsm28 at gcc dot gnu.org
  2024-04-02 16:16 ` harald at gigawatt dot nl
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: jsm28 at gcc dot gnu.org @ 2024-04-02 16:04 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #8 from Joseph S. Myers <jsm28 at gcc dot gnu.org> ---
"rejects", in the ISO C sense, only applies to errors and pedwarns in GCC; not
to warnings conditional on -pedantic (of which there are also some, but which
don't turn into errors with -pedantic).

If you have cases where something that is only *undefined as a property of a
particular execution of the program* (as opposed to undefined as a property of
a translation unit or of the collection of translation units making up a
program, or violating a Constraint or syntax rule) but that are errors or
pedwarns, those should be reported as separate bugs. There are various cases
where we make sure to only warn at compilation time and generate code that
aborts at precisely the point in execution where undefined behavior would
occur, precisely because the undefined behavior in those cases is a property of
a program execution.

I believe conversions between function and object pointers are undefined as a
property of the translation unit - not of a particular execution. Whereas e.g.
calling a function pointer converted to an incompatible type is undefined as a
property of a particular execution (the undefinedness only occurring when the
call itself is executed, after all side effects from the function designator
and arguments have taken place).

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (7 preceding siblings ...)
  2024-04-02 16:04 ` jsm28 at gcc dot gnu.org
@ 2024-04-02 16:16 ` harald at gigawatt dot nl
  2024-04-02 16:20 ` harald at gigawatt dot nl
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-02 16:16 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #9 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Joseph S. Myers from comment #8)
> "rejects", in the ISO C sense, only applies to errors and pedwarns in GCC;
> not to warnings conditional on -pedantic (of which there are also some, but
> which don't turn into errors with -pedantic).
> 
> If you have cases where something that is only *undefined as a property of a
> particular execution of the program* (as opposed to undefined as a property
> of a translation unit or of the collection of translation units making up a
> program, or violating a Constraint or syntax rule) but that are errors or
> pedwarns, those should be reported as separate bugs.

Bug 83584, which like this one is closed as a duplicate of 11234, is about
exactly that.

  void *f(void) { return (void *)f; }
  int main(void) { return 0; }

This is a strictly conforming program. It violates no syntax rule or
constraint, and exhibits no translation-time undefined behaviour, yet it
triggers a pedwarn, turning into an error with -pedantic-errors. It would have
undefined behaviour i f f were ever called, but it is not called.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (8 preceding siblings ...)
  2024-04-02 16:16 ` harald at gigawatt dot nl
@ 2024-04-02 16:20 ` harald at gigawatt dot nl
  2024-04-02 17:21 ` jsm28 at gcc dot gnu.org
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-02 16:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #10 from Harald van Dijk <harald at gigawatt dot nl> ---
Sorry, sent my earlier comment too soon.

(In reply to Joseph S. Myers from comment #8)
> I believe conversions between function and object pointers are undefined as
> a property of the translation unit - not of a particular execution.

But there is nothing in the standard to support this. The standard fully
defines the behaviour of the program I posted, which is just to return 0.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (9 preceding siblings ...)
  2024-04-02 16:20 ` harald at gigawatt dot nl
@ 2024-04-02 17:21 ` jsm28 at gcc dot gnu.org
  2024-04-02 17:29 ` kkylheku at gmail dot com
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: jsm28 at gcc dot gnu.org @ 2024-04-02 17:21 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #11 from Joseph S. Myers <jsm28 at gcc dot gnu.org> ---
I think that simply failing to say whether a value of type X may be converted
to type Y is clearly enough for it at least to be unspecified whether or when
such conversions are possible in a cast at all (which is enough for rejecting
the translation unit). And since no requirements are imposed relating to such
conversions at either translation time or runtime, the definition of undefined
behavior is met.

If you try to cast from a struct to a union (for example), you violate a
constraint. If you try to do a conversion between a pointer and another scalar
type that's not one of the "may be converted" cases listed as allowing such a
conversion, you have undefined behavior through the lack of definition (if it's
an implicit conversion rather than a cast, doing it as an implicit conversion
violates a constraint unless it follows the requirements for assignment
expressions.)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (10 preceding siblings ...)
  2024-04-02 17:21 ` jsm28 at gcc dot gnu.org
@ 2024-04-02 17:29 ` kkylheku at gmail dot com
  2024-04-02 17:35 ` kkylheku at gmail dot com
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-04-02 17:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #12 from Kaz Kylheku <kkylheku at gmail dot com> ---
(In reply to Harald van Dijk from comment #10)
> Sorry, sent my earlier comment too soon.
> 
> (In reply to Joseph S. Myers from comment #8)
> > I believe conversions between function and object pointers are undefined as
> > a property of the translation unit - not of a particular execution.
> 
> But there is nothing in the standard to support this. The standard fully
> defines the behaviour of the program I posted, which is just to return 0.

It does not. You're relying on the implementation (1) glossing over the
undefined conversion at translation time (or supporting it as an extension) and
then (2) optimization removing whatever code was generated for it since the
value is unused.

The standard does not define the conversion, by omission of defined behavior.

Moreover, the omission isn't absolute. There is a non-normative mention of this
conversion in an informative Annex which acknowledges the conversion as a
common extension. That tells us that the omission of a definition of behavior
from the normative text is known, and deliberate.

Undefined behavior means that the implementation is permitted to stop, at
translation or execution time, with or without the issuance of a diagnostic
message.

Moreover, implementations are not required to optimize. If the abstract
semantics of your program is executed literally, then there will be an
undefined conversion performed, whose value is then discarded in the
expression-statement.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (11 preceding siblings ...)
  2024-04-02 17:29 ` kkylheku at gmail dot com
@ 2024-04-02 17:35 ` kkylheku at gmail dot com
  2024-04-02 17:57 ` harald at gigawatt dot nl
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-04-02 17:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #13 from Kaz Kylheku <kkylheku at gmail dot com> ---
(In reply to Joseph S. Myers from comment #11)
> I think that simply failing to say whether a value of type X may be
> converted to type Y is clearly enough for it at least to be unspecified
> whether or when such conversions are possible in a cast at all (which is
> enough for rejecting the translation unit).

"Unspecified (Behavior)" is a normative term though. Unspecified situations
occur when the standard gives the implementation a choice from among a finite
number of behaviors (none of those being anything like "stop the program", or
"behave unpredictably"), but the implementation is not required to document
which behavior is selected.

The difference between "unspecified" and "implementation-defined" is that under
the latter, the choice must be documented.

E.g. order of evaluation of function argument expressions is unspecified,
therefore we don't know whether G or H is called first in F(G(), H()), and the
implementation doesn't have to provide any documented requirements about it.

When the standard doesn't define a behavior, not mentioning any possible
choices or anything of the sort, it is undefined. "behave unpredictably" or
"stop the program" are possible behaviors then.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (12 preceding siblings ...)
  2024-04-02 17:35 ` kkylheku at gmail dot com
@ 2024-04-02 17:57 ` harald at gigawatt dot nl
  2024-04-02 18:18 ` jsm28 at gcc dot gnu.org
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-02 17:57 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #14 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Joseph S. Myers from comment #11)
> I think that simply failing to say whether a value of type X may be
> converted to type Y is clearly enough for it at least to be unspecified
> whether or when such conversions are possible in a cast at all (which is
> enough for rejecting the translation unit).

I disagree. You're reading something into the standard that it does not say
anywhere. It would make sense if it did say that, but it doesn't.

> And since no requirements are
> imposed relating to such conversions at either translation time or runtime,
> the definition of undefined behavior is met.

The behaviour at runtime is implicitly unspecified. The behaviour at
translation time is not, as my program does not attempt to convert between any
function and object pointer. Performing that conversion is undefined by
omission. Writing code that *would* perform that conversion, if executed, is
not undefined, because the standard defines the behaviour of code that is not
executed: it does nothing.

I am assuming, at least, that there is no dispute that

  #include <stdio.h>
  int main(void) {
    if (0) puts("Hello, world!");
    return 0;
  }

has never been permitted to print "Hello, world!".

(In reply to Kaz Kylheku from comment #12)
> It does not. You're relying on the implementation (1) glossing over the
> undefined conversion at translation time (or supporting it as an extension)

I'm not.

> Undefined behavior means that the implementation is permitted to stop, at
> translation or execution time, with or without the issuance of a diagnostic
> message.

My program has no undefined behaviour. It is in the same category as

  void f(void) { 1/0; }
  int main(void) { return 0; }

which is strictly confirming despite the division by zero in an uncalled
function, despite division taking constant operands. The implementation is not
at liberty to treat this as translation-time undefined behaviour, because the
program does not divide by zero. Even though constant expressions could
otherwise be optimised. And GCC rightly accepts this with -pedantic-errors.

It is in the same category as

  void f(x) void *x; { f(f); }
  int main(void) { return 0; }

which is strictly conforming despite the unevaluated function call to an
unprototyped function with a wrong argument type where the compiler knows the
type of the parameter. And GCC rightly accepts this too with -pedantic-errors.
It does not even warn by default.

There have been DRs that explicitly address this for various forms of undefined
behaviour (#109, #132, #317). Is it really necessary for WG14 to receive a
separate DR for every category of undefined behaviour to clarify that the same
rules for undefined behaviour apply everywhere?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (13 preceding siblings ...)
  2024-04-02 17:57 ` harald at gigawatt dot nl
@ 2024-04-02 18:18 ` jsm28 at gcc dot gnu.org
  2024-04-02 19:06 ` harald at gigawatt dot nl
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: jsm28 at gcc dot gnu.org @ 2024-04-02 18:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #15 from Joseph S. Myers <jsm28 at gcc dot gnu.org> ---
There are several statements such as "Any pointer type may be converted to an
integer type." and "A pointer to an object type may be converted to a pointer
to a different object type.", that allow certain conversions to occur in a
translation unit and are associated with some properties of those conversions
if they are executed. There are also statements disallowing certain conversions
from occurring in a translation unit (for example, conversions between pointer
and floating types are constraint violations). In the cases where there is no
statement either way, the behavior is undefined as a property of the
translation unit (not just of the execution): it is not defined whether such a
conversion may occur in a translation unit, and not defined what the semantics
would be on execution if an implementation permits the translation of such a
conversion. Being undefined through omission of definition has, as per clause
4, not difference in meaning or emphasis from being explicitly undefined.

I'd suggest working with the Undefined Behavior Study Group on making it more
explicit for each instance of undefined behavior whether it is a property of
the program or of an execution thereof, but if any case seems particularly
unclear, filing an issue once the new C standard issue tracker is up and
running would probably be reasonable (but it seems likely that such issues
would be referred to the UB study group to recommend a resolution just as
floating-point issues would likely be referred to the CFP group).

It's *not* the case that the same rules apply everywhere, because there are two
different kinds of UB depending on whether what's undefined is a property of
the program or an execution thereof. Division by zero is obviously UB as a
property of an execution, because whether a value is zero is a property of the
execution. Different types for the same identifier with external linkage in
different translation units is obviously UB as a property of the program (and
not widely diagnosed without LTO), as the whole concept of an identifier
corresponding to an object with a particular value depends on a globally
consistent notion of its type and the UB is about presence of declarations
rather than a particular path of execution. In some cases, as here, it may be
less obvious how to read the wording as referring to properties of an execution
or of a program.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (14 preceding siblings ...)
  2024-04-02 18:18 ` jsm28 at gcc dot gnu.org
@ 2024-04-02 19:06 ` harald at gigawatt dot nl
  2024-04-02 19:41 ` kkylheku at gmail dot com
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-02 19:06 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #16 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Joseph S. Myers from comment #15)
> In the cases where there is no statement either way, the behavior is
> undefined as a property of the translation unit (not just of the execution):
> it is not defined whether such a conversion may occur in a translation unit,

This is still not stated anywhere in the standard though.

> Being undefined
> through omission of definition has, as per clause 4, not difference in
> meaning or emphasis from being explicitly undefined.

Of course, but if the standard had explicitly stated that conversion between
function pointers and object pointers was undefined, it might be phrased in a
way that applies even to dead code. If you are relying on being undefined by
omission, you have to be really sure the behaviour is not defined *anywhere*,
including by general rules about dead code.

I will grant that the standard never explicitly says dead code is not executed
and has no effect, but if this is in dispute, we have a bigger problem.

> I'd suggest working with the Undefined Behavior Study Group on making it
> more explicit for each instance of undefined behavior whether it is a
> property of the program or of an execution thereof, but if any case seems
> particularly unclear, filing an issue once the new C standard issue tracker
> is up and running would probably be reasonable (but it seems likely that
> such issues would be referred to the UB study group to recommend a
> resolution just as floating-point issues would likely be referred to the CFP
> group).

Considering my stance is that WG14 have repeatedly and consistently stated what
the rules are, I see this as a waste of their time.

> It's *not* the case that the same rules apply everywhere, because there are
> two different kinds of UB depending on whether what's undefined is a
> property of the program or an execution thereof. Division by zero is
> obviously UB as a property of an execution, because whether a value is zero
> is a property of the execution.

Considering this example of 1/0 has been the subject of two separate DRs that I
referenced, I have to say it is not obvious from the standard itself. Keeping
in mind that the operands are constants and implementations are required to be
capable of constant expression evaluation in some contexts, a hypothetical
standard that permitted, or even required, this to be evaluated at translation
time (with undefined behaviour) even in otherwise dead code would make perfect
sense. But that is not the C standard we have, at least not the official
interpretation of it.

> Different types for the same identifier with
> external linkage in different translation units is obviously UB as a
> property of the program (and not widely diagnosed without LTO), as the whole
> concept of an identifier corresponding to an object with a particular value
> depends on a globally consistent notion of its type and the UB is about
> presence of declarations rather than a particular path of execution.

Yes, because a program that does not reference these identifiers still violates
the rule that specifies they must have compatible type. This means that there
is no execution of the program that avoids UB.

But in my program, there is no rule that is violated. Perhaps the rule that you
describe in your comment, that no program may contain any unsupported
conversion anywhere, regardless of whether the conversion is ever performed,
should exist, but it is simply not the case that there is such a rule to be
found anywhere in the standard.

One additional comment, though:

The fact that conversions between function pointers and object pointers are
rejected under -pedantic-errors mean that 'gcc -std=c99 -pedantic-errors'
cannot  be used as the implementation for POSIX's c99 utility, as POSIX's c99
utility is required to conform to the C99 standard, and simultaneously, permit
conversions between function pointers and object pointers (at least in some
cases). (Adjust for later versions as needed.) This is unfortunate, and
regardless of whether the C standard allows such programs to be rejected, can
we agree that the C standard also allows them to be accepted, and POSIX
requires them to be accepted? Is that not already sufficient reason to
reconsider?

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (15 preceding siblings ...)
  2024-04-02 19:06 ` harald at gigawatt dot nl
@ 2024-04-02 19:41 ` kkylheku at gmail dot com
  2024-04-02 21:37 ` harald at gigawatt dot nl
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-04-02 19:41 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #17 from Kaz Kylheku <kkylheku at gmail dot com> ---
(In reply to Harald van Dijk from comment #14)
> (In reply to Joseph S. Myers from comment #11)
> > I think that simply failing to say whether a value of type X may be
> > converted to type Y is clearly enough for it at least to be unspecified
> > whether or when such conversions are possible in a cast at all (which is
> > enough for rejecting the translation unit).
> 
> I disagree. You're reading something into the standard that it does not say
> anywhere. It would make sense if it did say that, but it doesn't.

The standrad does not define the conversion at the *type* level.

> 
> > And since no requirements are
> > imposed relating to such conversions at either translation time or runtime,
> > the definition of undefined behavior is met.
> 
> The behaviour at runtime is implicitly unspecified. The behaviour at
> translation time is not, as my program does not attempt to convert between
> any function and object pointer. Performing that conversion is undefined by
> omission. Writing code that *would* perform that conversion, if executed, is
> not undefined, because the standard defines the behaviour of code that is
> not executed: it does nothing.
> 
> I am assuming, at least, that there is no dispute that
> 
>   #include <stdio.h>
>   int main(void) {
>     if (0) puts("Hello, world!");
>     return 0;
>   }
> 
> has never been permitted to print "Hello, world!".
> 
> (In reply to Kaz Kylheku from comment #12)
> > It does not. You're relying on the implementation (1) glossing over the
> > undefined conversion at translation time (or supporting it as an extension)
> 
> I'm not.
> 
> > Undefined behavior means that the implementation is permitted to stop, at
> > translation or execution time, with or without the issuance of a diagnostic
> > message.
> 
> My program has no undefined behaviour. It is in the same category as
> 
>   void f(void) { 1/0; }
>   int main(void) { return 0; }
> 
> which is strictly confirming despite the division by zero in an uncalled
> function, despite division taking constant operands.

The program is strictly conforming because it has no problem with type. The
language defines a division operator for the types int x int -> int. There can
be divisions written x / y where we don't know that y is zero until a run-time
input is supplied.

The expression 1/0 has a meaning and is translatable; just the operand values
are bad.

Compilers have to be careful when doing constant folding not to blow up on bad
expressions that are not actually called.
Something like this could occur:

   switch (sizeof (T)) {
   case 4:
      ...  1 / (8 - sizeof (T));
   case 8
      ...  1 / (16 - sizeof (T));

   }

where if the size is 8, then case 4: never taken in that case, has a constant
division by zero.  Evaluation of constants is required for dead-code
elimination, so dead code elimination cannot be counted on to remove bad
expressions.

But:

  (void *) &function

has no meaning at all due to a type problem. Because it's a type problem, it is
a static problem which speaks to the ability to translate the expression. That
ability is not required.

The standard is mum about converting a function pointer type to void * type,
regardless of the specific run-time values involved.

We wouldn't say that

  void f(void) { "abc" / "def"; }

is strictly conforming because f is not called in the program. There is a type
problem. Now in this case there is a constraint violation: it requires a
diagnostic.

(void *) &function has a problem in the same category: operator not defined for
the given types. The only difference is that there is no requirement for a
diagnostic.

The implementation is justified in aborting the translation. Possibly with a
diagnostic (which could say "conversion of function pointers to data pointers
is not supported, goodbye!").

In summary,   (void *) &function  is a type mismatch error, which is not caught
by the C type system due to there being no constraint violation. It's a hole in
the type system.

When an implementation hits a situation that triggers a hole in the type
system, it is allowed to diagnose it and reject the program.

Anyway, this is all moot because this bugzilla is about GNU C, which has the
extension. The behavior is locally defined.

We would like NOT to have a diagnostic under -Wpedantic, so we are on the same
page.

Whether your program is strictly conforming or not, we would like not to have
it diagnosed under the -Wpedantic umbrella, and even if it is changed to a
program which calls f.

There is nothing wrong with the diagnostic, but it should be uncoupled from
-Wpedantic and available under its own option.   Possibly, an umbrella option
could exist for this kind of "super pedantic" errors, like
-Wconforming-extensions (warn about the use of GNU extensions that are
conforming, and thus require no diagnostic by ISO C).

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (16 preceding siblings ...)
  2024-04-02 19:41 ` kkylheku at gmail dot com
@ 2024-04-02 21:37 ` harald at gigawatt dot nl
  2024-04-03  5:48 ` kkylheku at gmail dot com
  2024-04-03  8:07 ` harald at gigawatt dot nl
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-02 21:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #18 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Kaz Kylheku from comment #17)
> The standrad does not define the conversion at the *type* level.
> ...
> The program is strictly conforming because it has no problem with type.

The DRs I referenced include ones where type errors have explicitly been stated
not to render behaviour undefined.

DR 132 (C90):

  /* No headers included */
  int checkup()
  {
  /* Case 1 */
  if (0)
  printf("Printing.\n");
  /* Case 2 */
  return 2 || 1 / 0;
  } 

  Response: "The Response to Defect Report #109 addresses this issue. The
translation unit must be successfully translated."

This, despite the fact that it implicitly declares as int(*)(), which is
incompatible with the type it is meant to be declared as.

The distinction you see between type errors and non-type errors is not one that
I believe is supported by previous DR responses.

> We wouldn't say that
> 
>   void f(void) { "abc" / "def"; }
> 
> is strictly conforming because f is not called in the program. There is a
> type problem. Now in this case there is a constraint violation: it requires
> a diagnostic.

My position is that it is *only* because this violates a constraint that this
cannot be part of a strictly conforming program, even if never called, as far
as standard C is concerned. That is why implementations are allowed to reject
it without program flow analysis.

> Anyway, this is all moot because this bugzilla is about GNU C, which has the
> extension. The behavior is locally defined.

Sure, I'm happy to put that aside if it becomes irrelevant to the bug.

> We would like NOT to have a diagnostic under -Wpedantic, so we are on the
> same page.
> 
> Whether your program is strictly conforming or not, we would like not to
> have it diagnosed under the -Wpedantic umbrella, and even if it is changed
> to a program which calls f.
> 
> There is nothing wrong with the diagnostic, but it should be uncoupled from
> -Wpedantic and available under its own option.   Possibly, an umbrella
> option could exist for this kind of "super pedantic" errors, like
> -Wconforming-extensions (warn about the use of GNU extensions that are
> conforming, and thus require no diagnostic by ISO C).

Agreed that having the warning is useful. If 'gcc -std=c99 -pedantic-errors'
emits a warning for this, regardless of whether it is enabled by default, that
is fine, and that does not prevent it from being a valid implementation of the
'c99' utility.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (17 preceding siblings ...)
  2024-04-02 21:37 ` harald at gigawatt dot nl
@ 2024-04-03  5:48 ` kkylheku at gmail dot com
  2024-04-03  8:07 ` harald at gigawatt dot nl
  19 siblings, 0 replies; 21+ messages in thread
From: kkylheku at gmail dot com @ 2024-04-03  5:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #19 from Kaz Kylheku <kkylheku at gmail dot com> ---
(In reply to Harald van Dijk from comment #18)
> (In reply to Kaz Kylheku from comment #17)
> > The standrad does not define the conversion at the *type* level.
> > ...
> > The program is strictly conforming because it has no problem with type.
> 
> The DRs I referenced include ones where type errors have explicitly been
> stated not to render behaviour undefined.
> 
> DR 132 (C90):
> 
>   /* No headers included */
>   int checkup()
>   {
>   /* Case 1 */
>   if (0)
>   printf("Printing.\n");
>   /* Case 2 */
>   return 2 || 1 / 0;
>   } 
> 
>   Response: "The Response to Defect Report #109 addresses this issue. The
> translation unit must be successfully translated."

Note that this report response does not say that the translation
unit must also be successfully linked, in a hosted implementation, to
produce a program.

> This, despite the fact that it implicitly declares as int(*)(), which is
> incompatible with the type it is meant to be declared as.

A mismatch, in linkage, can only occur when a reference is of a
different type from the definition.

In this translation unit alone, there is no type mismatch, because
the unit contains only a reference to printf, and no definition.

The translation unit can be part of a program where it makes sense.
E.g. in a freestanding implementation, where there isn't a library
with a printf, another translation unit can supply a compatible
definition of printf. Then, if (0) can be flipped to if (1) and
checkup() can be called, even.

There is no type problem here whatsoever that is comparable to
an operator being given operands whose type combination is not
defined for the operator. That's a problem entirely confined in
translation phase 7; it cannot be rescued by adding a suitable
secondary translation unit.

A call to an implicitly declared printf is translatable. There are
requirements about every aspect of it. There are no requiremnts
about how to translate (void *) &fn.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Bug c/114526] ISO C does not prohibit extensions: fix misconception.
  2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
                   ` (18 preceding siblings ...)
  2024-04-03  5:48 ` kkylheku at gmail dot com
@ 2024-04-03  8:07 ` harald at gigawatt dot nl
  19 siblings, 0 replies; 21+ messages in thread
From: harald at gigawatt dot nl @ 2024-04-03  8:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114526

--- Comment #20 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Kaz Kylheku from comment #19)

Needless to say I still disagree, but I interpreted your comment #17 as
suggesting this aspect of the discussion is neither necessary nor useful for
this bug, and agreed with that in comment #18. So let's actually stop this
aspect of the discussion.

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2024-04-03  8:07 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-28 22:00 [Bug c/114526] New: ISO C does not prohibit extensions: fix misconception kkylheku at gmail dot com
2024-03-28 22:03 ` [Bug c/114526] " pinskia at gcc dot gnu.org
2024-03-28 22:06 ` pinskia at gcc dot gnu.org
2024-03-28 22:33 ` kkylheku at gmail dot com
2024-03-29  0:27 ` harald at gigawatt dot nl
2024-03-29  1:20 ` jsm28 at gcc dot gnu.org
2024-03-29  1:23 ` harald at gigawatt dot nl
2024-03-29  3:07 ` kkylheku at gmail dot com
2024-04-02 16:04 ` jsm28 at gcc dot gnu.org
2024-04-02 16:16 ` harald at gigawatt dot nl
2024-04-02 16:20 ` harald at gigawatt dot nl
2024-04-02 17:21 ` jsm28 at gcc dot gnu.org
2024-04-02 17:29 ` kkylheku at gmail dot com
2024-04-02 17:35 ` kkylheku at gmail dot com
2024-04-02 17:57 ` harald at gigawatt dot nl
2024-04-02 18:18 ` jsm28 at gcc dot gnu.org
2024-04-02 19:06 ` harald at gigawatt dot nl
2024-04-02 19:41 ` kkylheku at gmail dot com
2024-04-02 21:37 ` harald at gigawatt dot nl
2024-04-03  5:48 ` kkylheku at gmail dot com
2024-04-03  8:07 ` harald at gigawatt dot nl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).