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


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

Re: Call to a function

Started byTim Rentsch <tr.17687@z991.linuxsc.com>
First post2023-10-29 05:47 -0700
Last post2024-01-23 14:19 -0500
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: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-10-29 05:47 -0700
    Re: Call to a function Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-10-29 14:40 -0700
      Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-11-10 06:33 -0800
      Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-11-17 21:16 -0800
      Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-11-19 00:09 -0800
        Re: Call to a function Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-11-19 13:20 -0800
          Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-19 12:49 -0800
            Re: Call to a function Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-01-22 03:27 +0000
              Re: Call to a function Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-01-21 20:14 -0800
              Re: Call to a function scott@slp53.sl.home (Scott Lurndal) - 2024-01-22 16:36 +0000
                Re: Call to a function Lawrence D'Oliveiro <ldo@nz.invalid> - 2024-01-22 22:05 +0000
      Re: Call to a function James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-11-19 18:50 -0500
        Re: Call to a function Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-01-22 18:11 -0800
        Re: Call to a function James Kuyper <jameskuyper@alumni.caltech.edu> - 2024-01-23 14:19 -0500

#379356 — Re: Call to a function

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-10-29 05:47 -0700
SubjectRe: Call to a function
Message-ID<86msw11tpp.fsf@linuxsc.com>
James Kuyper <jameskuyper@alumni.caltech.edu> writes:

> On 10/24/23 8:54 PM, Tim Rentsch wrote:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>> [...]
>>>
>>>> The point isn't quite the same.  The C standard explicitly says
>>>> integers may be converted to any pointer type.  The C standard
>>>> does not say that a pointer to an object type may be converted
>>>> to a pointer to function type.  Every implementation is within
>>>> its rights to reject any program whose static text includes[*] a
>>>> cast from a pointer to an object type to a pointer to function
>>>> type, regardless of whether the cast has any chance of being
>>>> executed.
>>>>
>>>> [*] meaning, still present as source of any preprocessor
>>>> conditionals have been processed, etc.
>>>
>>> I disagree.  (I think we've discussed this before.)
>>>
>>> Concretely, I believe that this program violates no syntax error
>>> or constraint.  It includes code whose behavior would be undefined
>>> if it were executed, but the `if (0)` prevents that.
>>>
>>> On what basis do you think a conforming implementation may reject
>>> it?
>>
>> First let me ask a question.  Does the C standard allow an
>> implementation to reject any program that is not strictly
>> conforming?
>
> [...]
>
> The standard never talks about rejection.  It requires that "A
> conforming hosted implementation shall accept any strictly
> conforming program.".  No such requirement applies to any program
> which is not strictly conforming.  (4p6)

Perhaps I shouldn't have used the word "reject".  If the question
were phrased "Does the C standard allow an implementation not to
accept any program that is not strictly conforming?", does your
comment above mean you would say Yes to that question?

[toc] | [next] | [standalone]


#379399

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-10-29 14:40 -0700
Message-ID<87leblhzud.fsf@nosuchdomain.example.com>
In reply to#379356
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>> On 10/24/23 8:54 PM, Tim Rentsch wrote:
>>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>> [...]
>>>>> The point isn't quite the same.  The C standard explicitly says
>>>>> integers may be converted to any pointer type.  The C standard
>>>>> does not say that a pointer to an object type may be converted
>>>>> to a pointer to function type.  Every implementation is within
>>>>> its rights to reject any program whose static text includes[*] a
>>>>> cast from a pointer to an object type to a pointer to function
>>>>> type, regardless of whether the cast has any chance of being
>>>>> executed.
>>>>>
>>>>> [*] meaning, still present as source of any preprocessor
>>>>> conditionals have been processed, etc.
>>>>
>>>> I disagree.  (I think we've discussed this before.)
>>>>
>>>> Concretely, I believe that this program violates no syntax error
>>>> or constraint.  It includes code whose behavior would be undefined
>>>> if it were executed, but the `if (0)` prevents that.
>>>>
>>>> On what basis do you think a conforming implementation may reject
>>>> it?
>>>
>>> First let me ask a question.  Does the C standard allow an
>>> implementation to reject any program that is not strictly
>>> conforming?
>>
>> [...]
>>
>> The standard never talks about rejection.  It requires that "A
>> conforming hosted implementation shall accept any strictly
>> conforming program.".  No such requirement applies to any program
>> which is not strictly conforming.  (4p6)
>
> Perhaps I shouldn't have used the word "reject".  If the question
> were phrased "Does the C standard allow an implementation not to
> accept any program that is not strictly conforming?", does your
> comment above mean you would say Yes to that question?

I've decided not to answer any more of your questions until you
answer mine.

The code we're discussing was snipped at some point, so here it
is again:

int main(void) {
    int obj = 42;
    typedef void func(void);
    if (0) {
        func *fptr = (func*)&obj;
        fptr();
    }
}

It illustrates the issue that the standard does not define the behavior
of a conversion from an object pointer type to a function pointer type
(other than the special case of a null pointer constant), but does not
make such conversion, expressed as a cast, a constraint violation.

I asked: "On what basis do you think a conforming implementation may
reject it?  Do you see a syntax rule or constraint that it violates?  Do
you see some other basis for rejecting it?"

To be clear, I'm asking about whether an implementation may reject it
specifically because of the pointer conversion, not about reasons for
rejecting it that would apply equally to a "hello, world" program.

Feel free to disregard the following paragraphs.

The impression I get (very likely a wrong one) is that you are
trying to use a Socratic method, asking me questions that you
think will steer me to the correct conclusion -- a conclusion that
you have not shared.  I am not speculating about your motivations
(which you hide very well); rather, I am letting you know about the
impression that I get from what you write.  I'm interested in what
you think about relevant technical issues, but I'm not interested
in playing the role of your student.

(We have two similar discussions happening in parallel in different
threads.  The other one involved a non-void function falling off
the end, with the caller attempting to use the result.  I won't get
into that code in this thread, other than to say that I'm awaiting
your answer there as well.  In both threads, it's becoming difficult
to remember what was being discussed in the first place.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

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


#379497

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-11-10 06:33 -0800
Message-ID<86edgxznhy.fsf@linuxsc.com>
In reply to#379399
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>>
>>> On 10/24/23 8:54 PM, Tim Rentsch wrote:
>>>
>>>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>>>
>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>> [...]
>>>>>
>>>>>> The point isn't quite the same.  The C standard explicitly says
>>>>>> integers may be converted to any pointer type.  The C standard
>>>>>> does not say that a pointer to an object type may be converted
>>>>>> to a pointer to function type.  Every implementation is within
>>>>>> its rights to reject any program whose static text includes[*] a
>>>>>> cast from a pointer to an object type to a pointer to function
>>>>>> type, regardless of whether the cast has any chance of being
>>>>>> executed.
>>>>>>
>>>>>> [*] meaning, still present as source of any preprocessor
>>>>>> conditionals have been processed, etc.
>>>>>
>>>>> I disagree.  (I think we've discussed this before.)
>>>>>
>>>>> Concretely, I believe that this program violates no syntax
>>>>> error or constraint.  It includes code whose behavior would be
>>>>> undefined if it were executed, but the `if (0)` prevents that.
>>>>>
>>>>> On what basis do you think a conforming implementation may
>>>>> reject it?
>>>>
>>>> First let me ask a question.  Does the C standard allow an
>>>> implementation to reject any program that is not strictly
>>>> conforming?
>>>
>>> [...]

Let me respond now to the paragraph below, and get back to your
other comments in a later posting.

> The impression I get (very likely a wrong one) is that you are
> trying to use a Socratic method, asking me questions that you
> think will steer me to the correct conclusion -- a conclusion that
> you have not shared.  I am not speculating about your motivations
> (which you hide very well); rather, I am letting you know about the
> impression that I get from what you write.  I'm interested in what
> you think about relevant technical issues, but I'm not interested
> in playing the role of your student.

To be clear, my question above is meant to elicit your views on
what I asked about.  My question was not meant to educate you, to
be a Socratic question, or to steer you in any particular
direction.  I was only looking for an answer, nothing more.

I ask the question because it is a threshold question for your
earlier question upthread.  My answer to your prior question
depends on this premise for its conclusion.  I asked my question
separately because I want to clarify the discussion.  As things
stand, my question has gotten a yes answer from James Kuyper and
Kaz, and a no answer from Richard Damon and yourself.  I
responded to Richard's posting sometime last week but have not
seen any followup from him on that.  I responded to several of
your postings just in the last day, so I'm not sure if you have
had a chance yet to read those.  If after reading my comments you
agree that the C standard allows implementations not to accept
any program that is not strictly conforming then I can go ahead
and answer your question.  If after reading my comments you still
do not agree to that premise then there really isn't anything
more for me to say other than I believe your understanding of the
C standard is not consistent with what its authors intend.  I can
agree to accept (no pun intended) either view as your final
opinion on the matter.

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


#379513

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-11-17 21:16 -0800
Message-ID<86h6ljy71z.fsf@linuxsc.com>
In reply to#379399
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

[...]

> (We have two similar discussions happening in parallel in different
> threads.  The other one involved a non-void function falling off
> the end, with the caller attempting to use the result.  I won't get
> into that code in this thread, other than to say that I'm awaiting
> your answer there as well.  [...])

I don't remember any outstanding question from the discussion of
falling off the end of a non-void function.  Looking back over
postings from you responding to a posting of mine I don't see
any either.  I guess it's possible there was a question but I
didn't see it.  In any case I have no idea what question in that
thread you want answered, so if you still want an answer please
ask the question again.

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


#379517

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-11-19 00:09 -0800
Message-ID<865y1yxiyw.fsf@linuxsc.com>
In reply to#379399
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> The code we're discussing was snipped at some point, so here it
> is again:
>
> int main(void) {
>     int obj = 42;
>     typedef void func(void);
>     if (0) {
>         func *fptr = (func*)&obj;
>         fptr();
>     }
> }
>
> It illustrates the issue that the standard does not define the behavior
> of a conversion from an object pointer type to a function pointer type
> (other than the special case of a null pointer constant), but does not
> make such conversion, expressed as a cast, a constraint violation.
>
> I asked:  "On what basis do you think a conforming implementation may
> reject it?

The code is not strictly conforming.

> Do you see a syntax rule or constraint that it violates?

No.

> Do you see some other basis for rejecting it?"

Yes.  The conversion expression can be untranslatable on some
platforms.  That means any such expression cannot be part of
a strictly conforming program.

> To be clear, I'm asking about whether an implementation may reject it
> specifically because of the pointer conversion, not about reasons for
> rejecting it that would apply equally to a "hello, world" program.

It is the pointer conversion expression that makes the program be
not strictly conforming.

> Feel free to disregard the following paragraphs.
>
> The impression I get (very likely a wrong one) is that you are
> trying to use a Socratic method,

I'm not.

> asking me questions that you
> think will steer me to the correct conclusion -- a conclusion that
> you have not shared.  I am not speculating about your motivations
> (which you hide very well); rather, I am letting you know about the
> impression that I get from what you write.  I'm interested in what
> you think about relevant technical issues, but I'm not interested
> in playing the role of your student.

I have no interest in treating you as a student.  I'd be much
happier if you would do more thinking for yourself.

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


#379525

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-11-19 13:20 -0800
Message-ID<87fs11e8yz.fsf@nosuchdomain.example.com>
In reply to#379517
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> The code we're discussing was snipped at some point, so here it
>> is again:
>>
>> int main(void) {
>>     int obj = 42;
>>     typedef void func(void);
>>     if (0) {
>>         func *fptr = (func*)&obj;
>>         fptr();
>>     }
>> }
>>
>> It illustrates the issue that the standard does not define the behavior
>> of a conversion from an object pointer type to a function pointer type
>> (other than the special case of a null pointer constant), but does not
>> make such conversion, expressed as a cast, a constraint violation.
>>
>> I asked:  "On what basis do you think a conforming implementation may
>> reject it?
>
> The code is not strictly conforming.
>
>> Do you see a syntax rule or constraint that it violates?
>
> No.
>
>> Do you see some other basis for rejecting it?"
>
> Yes.  The conversion expression can be untranslatable on some
> platforms.  That means any such expression cannot be part of
> a strictly conforming program.

I disagree.  A conforming implementation could implement a conversion of
an object pointer to a function pointer that always yields a null
pointer, or that yields a pointer whose representation is derived from
the representation of the operand.  The latter is typically done for
pointer-to-integer or integer-to-pointer conversions with mismatched
sizes (6.3.2.3 explicitly says that integers may be converted to
pointers and vice versa).

If, hypothetically, the standard said that an otherwise valid program
containing a conversion of an object pointer to a function pointer type
must be successfully translated, then compiler implementers could easily
find a way to implement such conversions, even if the result is not
useful.  It is incorrect to claim that such a conversion expression may
be "untranslatable".

[...]

> I have no interest in treating you as a student.  I'd be much
> happier if you would do more thinking for yourself.

I would be happier if you would not assume that I'm not already
doing that.  Be less arrogant.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

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


#380515

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-01-19 12:49 -0800
Message-ID<86bk9hjbey.fsf@linuxsc.com>
In reply to#379525
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> The code we're discussing was snipped at some point, so here it
>>> is again:
>>>
>>> int main(void) {
>>>     int obj = 42;
>>>     typedef void func(void);
>>>     if (0) {
>>>         func *fptr = (func*)&obj;
>>>         fptr();
>>>     }
>>> }
>>>
>>> It illustrates the issue that the standard does not define the behavior
>>> of a conversion from an object pointer type to a function pointer type
>>> (other than the special case of a null pointer constant), but does not
>>> make such conversion, expressed as a cast, a constraint violation.
>>>
>>> I asked:  "On what basis do you think a conforming implementation may
>>> reject it?
>>
>> The code is not strictly conforming.
>>
>>> Do you see a syntax rule or constraint that it violates?
>>
>> No.
>>
>>> Do you see some other basis for rejecting it?"
>>
>> Yes.  The conversion expression can be untranslatable on some
>> platforms.  That means any such expression cannot be part of
>> a strictly conforming program.
>
> I disagree.  A conforming implementation could implement a
> conversion of an object pointer to a function pointer that always
> yields a null pointer, or that yields a pointer whose representation
> is derived from the representation of the operand.  The latter is
> typically done for pointer-to-integer or integer-to-pointer
> conversions with mismatched sizes (6.3.2.3 explicitly says that
> integers may be converted to pointers and vice versa).
>
> If, hypothetically, the standard said that an otherwise valid
> program containing a conversion of an object pointer to a function
> pointer type must be successfully translated, then compiler
> implementers could easily find a way to implement such conversions,
> even if the result is not useful.  It is incorrect to claim that
> such a conversion expression may be "untranslatable".

What you mean by translatable is different from what I mean.  Of
course it is possible to produce a sequence of bits that conforms
to the bit-level representation of a function pointer.  The
problem is that it might not be possible to do that in a way that
is sensible, meaningful, or useful.

The contrast with converting between pointers and integers is
helpful here.  Converting a pointer to an integer, even if the
integer type isn't as big as the pointer type, is always
potentially useful, because for example the integer could be used
as a hash function.  Integers also have the nice property that
they are dense (not counting padding bits), so producing any old
integer value will never be problematic.  (Yes I know about the
rule that if the value cannot be represented the behavior is
undefined, but I'm not talking about that.)  Going the other
direction, an integer type whose size is large enough (and almost
always there are such types) can guarantee that converting a
pointer to an integer is invertible.  There is a deeper principle
here:  the addressing structures used in actual hardware use
integers as the basis for addresses.  Converting between integers
and pointers always makes sense at some low level.  An exception
to that rule is elaborate function pointers, which can use very
large structured values to represent a pointer to function.  This
exception is the primary motivation for the C standard saying
that "The result [of converting a pointer to an integer] need not
be in the range of values of any integer type";  in such cases
the behavior is undefined but it is still always allowed to write
an expression asking for such conversions - it is only trying to
execute these expressions that causes a problem.

Note that the C standard reflects the distinction I'm making
here.  The standard specifically specifies that integers may
be converted to pointers, and vice versa.  The standard also
specifically specifies that object pointers may be converted to
other object pointers, and that function pointers may be
converted to other function pointers.  The standard does NOT
specify that function pointers may be converted to object
pointers, or that object pointers may be converted to function
pointers.  This difference corresponds exactly to what I mean
by translatable and untranslatable.  This distinction is not
incidental, accidental, or meaningless.  On the contrary, it is
certainly deliberate, and goes to the heart of the question here.

>> I have no interest in treating you as a student.  I'd be much
>> happier if you would do more thinking for yourself.
>
> I would be happier if you would not assume that I'm not already
> doing that.

It's not assumption but observation.  To give an example, not too
long ago you asked a question in comp.std.c asking about undefined
behavior and indeterminate answers.  I wrote a long posting in
response, basically going through a thorough and systematic review
of the history in different versions of the C standard.  I'm sure
you could have done that yourself if you had tried to do so.

Please note that I'm not saying that you *should* have done that,
only that you *could* have done that.

> Be less arrogant.

I don't think it's arrogant to think or to say that you are
more capable than your comments would otherwise indicate.  If
anything it seems just the opposite, that I have a higher
impression of your abilities than might seem to be the case
to a casual reader.

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


#380608

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2024-01-22 03:27 +0000
Message-ID<uoknaf$j1rr$2@dont-email.me>
In reply to#380515
On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote:

> An exception to that rule is elaborate
> function pointers, which can use very large structured values to
> represent a pointer to function.

Real-world example: PowerPC/POWER, where a function reference is two 
addresses, one for the code and the other for, I think it’s called the GOT 
(“Global Object Table”). Every piece of code assumes its GOT register has 
been set up with the right value.

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


#380609

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2024-01-21 20:14 -0800
Message-ID<877ck2atsn.fsf@nosuchdomain.example.com>
In reply to#380608
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
> On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote:
>> An exception to that rule is elaborate
>> function pointers, which can use very large structured values to
>> represent a pointer to function.
>
> Real-world example: PowerPC/POWER, where a function reference is two 
> addresses, one for the code and the other for, I think it’s called the GOT 
> (“Global Object Table”). Every piece of code assumes its GOT register has 
> been set up with the right value.

According to <https://devblogs.microsoft.com/oldnewthing/20180816-00/?p=99505>:

    Since each function requires its table of contents to be set
    properly, a function pointer on PowerPC is not a pointer to the
    first instruction. Instead, it’s a pointer to a structure
    consisting of two pointers: The first pointer points to the
    first instruction of the function, and the second pointer is
    the table of contents for the function.

A quick experiment with a gcc powerpc cross-compiler
(powerpc-linux-gnu-gcc (Ubuntu 13.2.0-4ubuntu3) 13.2.0) indicates that
void* and function pointers are the same size, 4 bytes.

I suppose compilers *could* have used that two-pointer structure as the
representation of a function pointer.  Possibly that would have broken
code that makes invalid assumptions about function pointer sizes.

-- 
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]


#380629

Fromscott@slp53.sl.home (Scott Lurndal)
Date2024-01-22 16:36 +0000
Message-ID<yQwrN.323726$p%Mb.65389@fx15.iad>
In reply to#380608
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>On Fri, 19 Jan 2024 12:49:57 -0800, Tim Rentsch wrote:
>
>> An exception to that rule is elaborate
>> function pointers, which can use very large structured values to
>> represent a pointer to function.
>
>Real-world example: PowerPC/POWER, where a function reference is two 
>addresses, one for the code and the other for, I think it’s called the GOT 
>(“Global Object Table”). Every piece of code assumes its GOT register has 
>been set up with the right value.

That's called dynamic linking and is only used for inter-library function
calls.   Intralibrary and intraapplication function calls don't need the
GOT (Global Offset Table), which is used by all modern Unix and Linux
distributions to support dynamic linking.

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


#380642

FromLawrence D'Oliveiro <ldo@nz.invalid>
Date2024-01-22 22:05 +0000
Message-ID<uomori$tokp$1@dont-email.me>
In reply to#380629
On Mon, 22 Jan 2024 16:36:46 GMT, Scott Lurndal wrote:

> .. GOT (Global Offset Table) ...

There had to be actual addresses in there somewhere though, did there not? 
Otherwise you would have to ask “offsets to what?”.

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


#379528

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2023-11-19 18:50 -0500
Message-ID<uje6vv$gei$1@dont-email.me>
In reply to#379399
> Keith Thompson <Keith.S.T...@gmail.com> writes:
> 
>> The code we're discussing was snipped at some point, so here it
>> is again:
>>
>> int main(void) {
>> int obj = 42;
>> typedef void func(void);
>> if (0) {
>> func *fptr = (func*)&obj;
>> fptr();
>> }
>> }
>>
>> It illustrates the issue that the standard does not define the behavior
>> of a conversion from an object pointer type to a function pointer type
>> (other than the special case of a null pointer constant), but does not
>> make such conversion, expressed as a cast, a constraint violation.
>>
>> I asked: "On what basis do you think a conforming implementation may
>> reject it?
> 
> The code is not strictly conforming.
> 
>> Do you see a syntax rule or constraint that it violates?
> 
> No.
> 
>> Do you see some other basis for rejecting it?"
> 
> Yes. The conversion expression can be untranslatable on some
> platforms. That means any such expression cannot be part of
> a strictly conforming program.

The committee has officially ruled in DR 109 that code with undefined
behavior renders the program not strictly conforming, only if execution
of that code is an inevitable consequence of running the program. Not
only is execution of this code not inevitable, it is in fact impossible
for it to be executed.

I'm curious - on what platform is it impossible, or at least difficult,
to translate an if(0) block as a no-op? I'd think that simply failing to
generate any corresponding machine code would be sufficient on most, if
not all, platforms.

The code that appeared in DR 109 was not a no-op, but the behavior of
any program that called the function would be undefined, which means
that the standard imposes no requirements on its behavior. On what
platform is it difficult to generate code that has no requirements on
how it behaves? I'd think it would be trivial translate it as, for
instance, the equivalent of

fprintf(stderr, "ISO C does not define the behavior of converting \n"
    "a pointer to an object into a pointer to a function.\n");
exit(EXIT_FAILURE);

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


#380665

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2024-01-22 18:11 -0800
Message-ID<86y1cgg5nb.fsf@linuxsc.com>
In reply to#379528
I am responding here to two different messages from James Kuyper,
combined for convenience in a single posting.  Each segment
starts with an attribution line naming James and giving his email
address, as would appear in a normal followup, and then gives
a Message-ID for that posting.

Incidentally, both of these message seems to be a response to a
posting (or postings) of mine, but they seem not to be linked
in the usual way that newgroup postings.  I'm not sure how or
why that happened, but I thought I should mention it.

[..first message..]

James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[Message-ID: <uje6vv$gei$1@dont-email.me>]

[This message is missing an attribution line that might have
 been something like the following line]

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.T...@gmail.com> writes:
>>
>>> The code we're discussing was snipped at some point, so here it
>>> is again:
>>>
>>> int main(void) {
>>> int obj = 42;
>>> typedef void func(void);
>>> if (0) {
>>> func *fptr = (func*)&obj;
>>> fptr();
>>> }
>>> }
>>>
>>> It illustrates the issue that the standard does not define the
>>> behavior of a conversion from an object pointer type to a function
>>> pointer type (other than the special case of a null pointer
>>> constant), but does not make such conversion, expressed as a cast,
>>> a constraint violation.
>>>
>>> I asked:  "On what basis do you think a conforming implementation
>>> may reject it?
>>
>> The code is not strictly conforming.
>>
>>> Do you see a syntax rule or constraint that it violates?
>>
>> No.
>>
>>> Do you see some other basis for rejecting it?"
>>
>> Yes.  The conversion expression can be untranslatable on some
>> platforms.  That means any such expression cannot be part of
>> a strictly conforming program.
>
> The committee has officially ruled in DR 109 that code with undefined
> behavior renders the program not strictly conforming, only if execution
> of that code is an inevitable consequence of running the program.  Not
> only is execution of this code not inevitable, it is in fact impossible
> for it to be executed.

The remarks in DR 109 are irrelevant to what I'm saying.  The
program given above fails to be strictly conforming for reasons
that have nothing to do with undefined behavior.

> I'm curious - on what platform is it impossible, or at least
> difficult, to translate an if(0) block as a no-op?  I'd think that
> simply failing to generate any corresponding machine code would be
> sufficient on most, if not all, platforms.

I hope you realize that this question is quite irrelevant to the
matter being addressed here.

> The code that appeared in DR 109 was not a no-op, but the behavior
> of any program that called the function would be undefined, which
> means that the standard imposes no requirements on its behavior.
> On what platform is it difficult to generate code that has no
> requirements on how it behaves?  I'd think it would be trivial
> translate it as, for instance, the equivalent of
>
> fprintf(stderr, "ISO C does not define the behavior of converting \n"
>     "a pointer to an object into a pointer to a function.\n");
> exit(EXIT_FAILURE);

You seem to think that the problem has to do with how to compile
program text that has undefined behavior.  It doesn't.  Please
see also my response to Keith Thompson's message regarding what
I mean by "translatable".


[..second message..]

James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[in a posting with Message-ID: <ujdgc9$3t0ni$1@dont-email.me>]

> On 2023-11-19 at 02:28 EST, Tim Rentsch wrote:
>
>> James Kuyper <james...@alumni.caltech.edu> writes:
>>
>>> Most fundamentally, what I an hoping to accomplish is to convince
>>> you to answer Keith's question.
>>
>> Consider a C compiler for a machine where function pointers are
>> much bigger than any object pointer type.  Functions might even
>> live in a completely different address space than data (a
>> so-called Harvard architecture).  On such a machine there is no
>> sensible way to change an object pointer into a function pointer,
>> or vice versa.  Naturally the compiler would prefer to choose not
>> to translate any source file that contains such a conversion.
>
> But the standard does not allow such behavior - 

Yes, it does.  There's a flaw in your logic in trying to decide
whether the program is strictly conforming.

> if they wish to
> claim conformance to the C standard, they'll have to do something
> other than what they'd prefer.  Since the code with undefined
> behavior is protected by an if(0), an implementation is not
> required to generate the impossible conversion code, and is
> required to accept the program.

Let me say again that the question of undefined behavior is
not relevant here.  The given program fails to be strictly
conforming for reasons that have nothing to do with undefined
behavior.

>> The C standard doesn't say function pointers may be converted to
>> object pointers, or the other way around.  The obvious thing to
>> do is simply give an error message and forego the translation
>> effort.  It doesn't make sense that the standard would insist
>> that an implementation translate a construct that is nonsensical,
>> not just in a particular case but in every possible case.
>
> I appreciate that you feel that way - but the committee resolved
> DR 109 in conflict with your feeling.

That is your misunderstanding.  The remarks in DR 109 have no
bearing on my conclusions.

> The code referred to by DR
> 109 divided an integer by an integer constant of 0, which wasn't
> even protected by an if(0).  It was the only line in the only
> function defined in that translation unit, which was absolutely
> guaranteed, if function were called, to execute that line.  The
> only reason the committee gave for it being strictly conforming
> was that there was no guarantee that the rest of the program ever
> actually called the function.  But the committee decided that that
> fact was sufficient to make the code, in itself, strictly
> conforming, and the implementation was therefore required to
> accept it.  If the program as a whole did call that function, that
> fact would be sufficient to justify rejecting the whole program,
> but it was not sufficient to justify rejecting that particular
> translation unit.

Your phrasing here is slightly off.  What was actually said is
that

    A conforming implementation must not fail to translate
    a strictly conforming program simply because some
    possible execution of that program would result in
    undefined behavior.

The undefined behavior not being evaluated doesn't guarantee the
program is strictly conforming.  If a program /is/ otherwise
strictly conforming then undefined behavior that is potentially
unevaluated doesn't interfere with that.  Do you see the
difference?  The problem here is that the code in Keith's program
is not strictly conforming, regardless of whether there is
evaluated undefined behavior.

> Basically, code with undefined behavior prevents a program from
> being strictly conforming only if execution of such code is an
> inevitable consequence of starting the program.  If executing that
> code can be avoided, then only a failure to avoid it renders the
> the behavior undefined.  If that failure is not realized at
> compile time, then the implementation must still accept it.

If undefined behavior is unavoidable, then the program is not
strictly conforming, and it need not be accepted.

However, if all undefined behavior is potentially not evalauted,
that does not by itself guarantee that the program is strictly
conforming.  Furthermore you yourself quoted, in another posting,
the relevant sentence from the C standard that bears on the
question of strict conformance.

> If the committee ruled that way on that code, how could you
> possibly expect it to support rejection of this code?

You think the only things that matter in the two programs are
analogous.  They aren't.

>> Converting between function pointers and object pointers isn't
>> like dividing by zero.
>
> True - there's implementations which can meaningfully do such a
> conversion - there's no meaningful way to divide an integer by 0
> (a floating point calculation could reasonably produce infinity,
> if infinity can be represented on that hardware).  Which makes the
> committee's decision on DR 109 even stronger.

Again you miss the point.  The question of undefined behavior
has no bearing on the conclusion.

>> [.. some remarks unrelated to the primary topic ..]
>
> [...]
> However, if you're unable to provide a convincing argument that
> your point of view is correct, then it's a point of view that is,
> quite frankly, of no interest.

I have very little interest in trying to offer an argument
that convinces you.  My conclusions are correct, whether
my comments convince you or not.

[... incidental commentary left out ...]

>> Try compiling Keith's program with gcc -pedantic-errors.  I expect
>> you will find, as I did, that gcc flags the conversion with an
>> error and doesn't produce an output file.  The C standard allows
>> such behavior only if the source file being compiled is not
>> strictly conforming.  I have more confidence in gcc's understanding
>> of the C standard than I do in yours.
>
> I have considerable trust in gcc, but more trust in the actual
> words of the standard.  Where there's a disagreement, I favor the
> actual words of the standard.

The problem is not the words of the C standard but what you think
they mean.

> And, having seen how you interpret the standard, I certainly
> trust my interpretation more than yours.

Of course.  You're living in your own language bubble.  Unlike you,
I calibrate my understanding of what text in the C standard means
by comparing it with other sources, including especially remarks
written or spoken by C standard committee members in other contexts.

>>> Yes, it does.  And I frequently despair of ever figuring out a way
>>> to say what I mean that will be understood as intended by you.
>>> [...]
>>
>> The problem is not me understanding you, but you not understanding
>> me.  Your mental model for how to use and understand natural
>> language is peculiar.  Also rigid and inflexible.  Probably the
>> most troublesome property is that you are focused on argument more
>> than on understanding.  You read the words but don't understand the
>> meaning.  Instead you insist on playing idiosyncratic word games,
>> apparently believing that how you interpret the words is universal
>> and absolute.  It isn't.  Assigning meaning to natural language is
>> inherently a subjective process, not an objective one.  You're a
>> lot better at arguing than you are at listening.  You might want to
>> think about that.
>
> Subjectivity is fine for poetry - but we're talking about a
> standard.  To the extent that the meaning of words is subjective,
> they are unsuitable for use in a standard.  The whole point of the
> standard is to standardize the requirements - that is, to make
> them exactly the same for everyone.  If you have to use subjective
> interpretations to determine what the requirements are, the
> standard has failed the purpose for which it was intended.  An
> implementor could use it's subjective opinion to justify
> implementing C in a way that would be inconsistent with the
> subjective opinion of a user.

I'm sorry you missed the point of what I was saying.

Just one more item.  Here is a quote from the C Rationale document:

  Consequences of the treatment of pointer types in the
  Standard include:

    * [...]

    * Even with an explicit cast, it is invalid to convert
      a function pointer to an object pointer or a pointer
      to void, or vice versa.

Note in particular the word /invalid/.  Not undefined, but
invalid.  What do you suppose is the basis for that statement?
What bearing does it have on the question being discussed?
What do you think the implications are for the various assertions
made during the discussion?

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


#380689

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2024-01-23 14:19 -0500
Message-ID<uop3fd$1d8ao$1@dont-email.me>
In reply to#379528
On 2024-01-22 00:08, Tim Rentsch wrote:
...
> Incidentally, both of these message seems to be a response to a
> posting (or postings) of mine, but they seem not to be linked
> in the usual way that newgroup postings. I'm not sure how or
> why that happened, but I thought I should mention it.

I currently have Thunderbird configured to delete any usenet messages
from you. This is not intended to punish you, nor does it incur any
obligation on my part to ignore your questions. It's intended solely to
reduce the amount of aggravation I feel as a result of reading your
messages. As a result, if I end up learning about one of your messages
by other means, and decide that I do want to respond, it's inconvenient
to do so. This is both an advantage and a disadvantage - it discourages
me from responding unless strongly motivated, but it also makes it
inconvenient to respond if I am sufficiently motivated.
I've been using Google Groups to post such messages, but when they cut
that off, I've been forced to switched to a couple of other
work-arounds. I'm not sure which one I used in that message, and the
details aren't important, but I'm not surprised if either method messed
up the message links.

> [..first message..]
> 
> James Kuyper <james...@alumni.caltech.edu> writes:
> [Message-ID: <uje6vv$gei$1...@dont-email.me>]
> 
> [This message is missing an attribution line that might have
> been something like the following line]
> The remarks in DR 109 are irrelevant to what I'm saying. The
> program given above fails to be strictly conforming for reasons
> that have nothing to do with undefined behavior.

And once again, typical Tim Rentsch behavior. This would have been a
perfectly obvious and natural opportunity to insert a statement of what
you think the actual reason is, but you refuse to do so.

>> I'm curious - on what platform is it impossible, or at least
>> difficult, to translate an if(0) block as a no-op? I'd think that
>> simply failing to generate any corresponding machine code would be
>> sufficient on most, if not all, platforms.
> 
> I hope you realize that this question is quite irrelevant to the
> matter being addressed here.

You said that implementing such a conversion would be difficult. I don't
see what's difficult about a conversion that does not in fact need to be
implemented.

>> The code that appeared in DR 109 was not a no-op, but the behavior
>> of any program that called the function would be undefined, which
>> means that the standard imposes no requirements on its behavior.
>> On what platform is it difficult to generate code that has no
>> requirements on how it behaves? I'd think it would be trivial
>> translate it as, for instance, the equivalent of
>>
>> fprintf(stderr, "ISO C does not define the behavior of converting \n"
>> "a pointer to an object into a pointer to a function.\n");
>> exit(EXIT_FAILURE);
> 
> You seem to think that the problem has to do with how to compile
> program text that has undefined behavior. It doesn't. Please
> see also my response to Keith Thompson's message regarding what
> I mean by "translatable".

The relevant code does not need to be translated, and therefore does not
need to be translatable, since it is literally impossible for it to be
executed.

...
> Yes, it does. There's a flaw in your logic in trying to decide
> whether the program is strictly conforming.

Once again, you passed upon on a perfectly obvious and natural
opportunity to insert a statement explaining what actually renders the
program not strictly conforming.

You could have easily, at any time, short-circuited months of circuitous
arguing by identifying the feature of the program that renders it not
strictly conforming. The only suspect I can find for such a feature is
the fact that the code which never gets executed would have undefined
behavior if it were executed. Since you say that's not the problem, I
have no idea what you think the problem actually is.

...
> Let me say again that the question of undefined behavior is
> not relevant here. The given program fails to be strictly
> conforming for reasons that have nothing to do with undefined
> behavior.

Again, you passed up on a perfectly obvious and natural opportunity to
insert a statement identifying what you think the reason actually is.

...
> The undefined behavior not being evaluated doesn't guarantee the
> program is strictly conforming. If a program /is/ otherwise
> strictly conforming then undefined behavior that is potentially
> unevaluated doesn't interfere with that. Do you see the
> difference?

Not in any way that is applicable. I see no other way in which it fails
to be strictly conforming. I may have missed something, and you might
have noticed it, which is why we've repeatedly asked you to identify it,
but you have repeatedly and steadfastly refused to explain what that
other way is.
Again, you missed a perfectly obvious and natural opportunity to insert
a statement identifying what it is that you think makes the program not
strictly conforming.

...
>> If the committee ruled that way on that code, how could you
>> possibly expect it to support rejection of this code?
> 
> You think the only things that matter in the two programs are
> analogous. They aren't.

Because you refuse to identify what thing it is you think matters.
Once again, you missed a perfectly obvious and natural opportunity to
insert a statement identifying what it is that you think matters.

...
> Again you miss the point. The question of undefined behavior
> has no bearing on the conclusion.

Again, you missed a perfectly natural and obvious opportunity to
identify what it is that you think does have a bearing on the conclusion.

...> I have very little interest in trying to offer an argument
> that convinces you. My conclusions are correct, whether
> my comments convince you or not.

Yes, I've noticed your lack of interest in convince me. But do you have
any idea how frustrating it is to shadow box with someone who refuses to
put his arguments out there so we can decide whether or not they make
any sense. There's a perfectly natural conclusion that can be reached
when someone behaves that way, and that is they are afraid to explain
their arguments, because they know that those arguments are not good
enough to survive public exposure. That might not be your actual reason,
but your behavior entitles us to assume that it is - not because that
would be the most reasonable guess, but as a built-in punishment for
your refusal to communicate.

...
> The problem is not the words of the C standard but what you think
> they mean.

And, again, you missed a perfectly obvious and natural opportunity to
explain what it is you think they actually mean.

...
> I calibrate my understanding of what text in the C standard means
> by comparing it with other sources, including especially remarks
> written or spoken by C standard committee members in other contexts.

And again, you missed a perfectly obvious and natural opportunity to
insert a citation of the relevant remarks that informed you interpretation.

...
> I'm sorry you missed the point of what I was saying.

That's because you refuse to explain it. You just criticize what I say
without bothering to explain your criticism. How could I possibly have
any idea what your point is when you won't explain it?
Again, you missed a perfectly obvious and natural opportunity to insert
an explanation of what your point is.

> Just one more item. Here is a quote from the C Rationale document:
> 
> Consequences of the treatment of pointer types in the
> Standard include:
> 
> * [...]
> 
> * Even with an explicit cast, it is invalid to convert
> a function pointer to an object pointer or a pointer
> to void, or vice versa.
> 
> Note in particular the word /invalid/. Not undefined, but
> invalid. What do you suppose is the basis for that statement?

Since the standard doesn't use the term "invalid" in any applicable text
that I could find, I would assume that the basis for this statement is
the fact that the behavior of such a conversion is undefined. The terms
"syntax error", "constraint violation", "unspecified behavior",
"implementation-defined behavior", "undefined behavior", and
"locale-specific", among others, all have requirements (or the lack
thereof) attached to them by the C standard. "invalid" does not. The
behavior of such a conversion is undefined "by omission of any explicit
definition of the behavior", and as far as I know that is the only
relevant problem with it. It doesn't violate any applicable syntax rule
or constraint that I'm aware of. And you've repeatedly refused to
identify one.

> What bearing does it have on the question being discussed?
> What do you think the implications are for the various assertions
> made during the discussion?

I don't think it has a bearing, because I think it is using "invalid" as
an informal reference to the fact that the behavior is undefined. We
appear to both be in agreement that the undefined behavior of that
statement, if it were executed, is irrelevant to the strict conformance
of this code, since it cannot be executed, so I would expect that to
have no implications for the various assertions.

Again, you passed  upon on a perfectly obvious and natural opportunity
for inserting statements explaining what bearing you think it has on the
discussion and what the implications are for the various statements made
during the discussion.

If you've not willing to explain, why do you even bother posting a
message? A message that merely asserts that there is a problem, while
failing to identify it, does nothing except raise the suspicion that you
don't actually have a valid reason for thinking that there's a problem.

[toc] | [prev] | [standalone]


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


csiph-web