• Re: Difference between undefined behavior and "program is ill-formed"?

    From Juha Nieminen@21:1/5 to Alf P. Steinbach on Fri Nov 12 14:10:51 2021
    Alf P. Steinbach <alf.p.steinbach@gmail.com> wrote:
    On 12 Nov 2021 14:54, Juha Nieminen wrote:
    With std::vector<T, Allocator>, if Allocator::value_type is not the same
    as T, the behavior is undefined until C++20. Since C++20 the "program is
    ill-formed".

    What is the difference?

    The in-practice:

    UB can compile, with or without a diagnostic. Some/most kinds of UB are dynamic events during program execution, such as integer division by 0, dereferencing a nullpointer outside a `typeid` expressions, etc. It
    would be impossible for a compiler to diagnose them all.

    Ill formed program doesn't compile, and always causes a diagnostic.

    The formal:

    "Undefined Behavior" is (C++17 3.27) "behavior for which this
    International Standard imposes no requirements".

    "Ill formed" is just "not well formed", where "well formed" is just a
    (C++17 3.29) "program constructed according to the syntax rules,
    diagnosable semantic rules, and the one-definition rule".

    So that means that starting from C++20 we are guaranteed to get a
    compiler error if Allocator::value_type is not the same as T?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alf P. Steinbach@21:1/5 to Juha Nieminen on Fri Nov 12 15:06:19 2021
    On 12 Nov 2021 14:54, Juha Nieminen wrote:
    With std::vector<T, Allocator>, if Allocator::value_type is not the same
    as T, the behavior is undefined until C++20. Since C++20 the "program is ill-formed".

    What is the difference?

    The in-practice:

    UB can compile, with or without a diagnostic. Some/most kinds of UB are
    dynamic events during program execution, such as integer division by 0, dereferencing a nullpointer outside a `typeid` expressions, etc. It
    would be impossible for a compiler to diagnose them all.

    Ill formed program doesn't compile, and always causes a diagnostic.

    The formal:

    "Undefined Behavior" is (C++17 3.27) "behavior for which this
    International Standard imposes no requirements".

    "Ill formed" is just "not well formed", where "well formed" is just a
    (C++17 §3.29) "program constructed according to the syntax rules,
    diagnosable semantic rules, and the one-definition rule".

    - Alf

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Juha Nieminen@21:1/5 to All on Fri Nov 12 13:54:13 2021
    With std::vector<T, Allocator>, if Allocator::value_type is not the same
    as T, the behavior is undefined until C++20. Since C++20 the "program is ill-formed".

    What is the difference?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bo Persson@21:1/5 to Juha Nieminen on Fri Nov 12 16:35:26 2021
    On 2021-11-12 at 15:10, Juha Nieminen wrote:
    Alf P. Steinbach <alf.p.steinbach@gmail.com> wrote:
    On 12 Nov 2021 14:54, Juha Nieminen wrote:
    With std::vector<T, Allocator>, if Allocator::value_type is not the same >>> as T, the behavior is undefined until C++20. Since C++20 the "program is >>> ill-formed".

    What is the difference?

    The in-practice:

    UB can compile, with or without a diagnostic. Some/most kinds of UB are
    dynamic events during program execution, such as integer division by 0,
    dereferencing a nullpointer outside a `typeid` expressions, etc. It
    would be impossible for a compiler to diagnose them all.

    Ill formed program doesn't compile, and always causes a diagnostic.

    The formal:

    "Undefined Behavior" is (C++17 3.27) "behavior for which this
    International Standard imposes no requirements".

    "Ill formed" is just "not well formed", where "well formed" is just a
    (C++17 §3.29) "program constructed according to the syntax rules,
    diagnosable semantic rules, and the one-definition rule".

    So that means that starting from C++20 we are guaranteed to get a
    compiler error if Allocator::value_type is not the same as T?


    Yes. Easily implemented with a static_assert, which wasn't available
    when vector was born, but is now.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Juha Nieminen on Fri Nov 12 11:35:13 2021
    On 11/12/21 8:54 AM, Juha Nieminen wrote:
    With std::vector<T, Allocator>, if Allocator::value_type is not the same
    as T, the behavior is undefined until C++20. Since C++20 the "program is ill-formed".

    What is the difference?

    When the behavior is undefined, the standard imposes no requirements
    (3.30). Code which has undefined behavior is not considered to have
    violated a diagnosable rule (4.1p1).
    When a program is ill-formed, that qualifies as a violation of a
    diagnosable rule, and as such, the standard imposes one requirement:
    that at least one diagnostic message be generated.(4.1p2).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to James Kuyper on Sat Nov 13 10:27:57 2021
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    On 11/12/21 8:54 AM, Juha Nieminen wrote:

    With std::vector<T, Allocator>, if Allocator::value_type is not the same
    as T, the behavior is undefined until C++20. Since C++20 the "program is
    ill-formed".

    What is the difference?

    When the behavior is undefined, the standard imposes no requirements
    (3.30). Code which has undefined behavior is not considered to have
    violated a diagnosable rule (4.1p1).
    When a program is ill-formed, that qualifies as a violation of a
    diagnosable rule, and as such, the standard imposes one requirement:
    that at least one diagnostic message be generated.(4.1p2).

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Alf P. Steinbach on Sat Nov 13 10:26:57 2021
    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Tim Rentsch on Sat Nov 13 21:36:22 2021
    On 13/11/2021 19:26, Tim Rentsch wrote:
    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.


    I think that breaking the "One definition rule" would count here. Are
    there any others that you are thinking about?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alf P. Steinbach@21:1/5 to Tim Rentsch on Sun Nov 14 15:43:01 2021
    On 13 Nov 2021 19:26, Tim Rentsch wrote:
    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.


    Oh you're right, thanks. Sorry.

    I was talking about the in-practice but clearly some ill formed programs
    can't even practically be diagnosed as such.

    The difference between UB and ill-formed gets less clear then, but
    mainly that UB is well formed code that isn't constrained to any
    behavior, while ill formed code -- is code that isn't well formed and
    that isn't constrained to any behavior. A bit too circular for me. But I
    guess syntactically invalid code must be ill-formed and cannot have UB.

    - Alf

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to All on Mon Nov 15 14:15:49 2021
    14.11.2021 16:43 Alf P. Steinbach kirjutas:
    On 13 Nov 2021 19:26, Tim Rentsch wrote:
    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.


    Oh you're right, thanks. Sorry.

    I was talking about the in-practice but clearly some ill formed programs can't even practically be diagnosed as such.

    The difference between UB and ill-formed gets less clear then, but
    mainly that UB is well formed code that isn't constrained to any
    behavior, while ill formed code -- is code that isn't well formed and
    that isn't constrained to any behavior. A bit too circular for me. But I guess syntactically invalid code must be ill-formed and cannot have UB.

    "UB" is behavior which is undefined by the C++ standard. Another
    standard or the implementation can define the behavior, making the
    program valid.

    I suspect "ill-formed" is meant for programs which cannot or should not
    be made valid by another standard or implementation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Paavo Helde on Mon Nov 15 08:55:53 2021
    Paavo Helde <myfirstname@osa.pri.ee> writes:

    14.11.2021 16:43 Alf P. Steinbach kirjutas:

    On 13 Nov 2021 19:26, Tim Rentsch wrote:

    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.

    Oh you're right, thanks. Sorry.

    I was talking about the in-practice but clearly some ill formed
    programs can't even practically be diagnosed as such.

    The difference between UB and ill-formed gets less clear then, but
    mainly that UB is well formed code that isn't constrained to any
    behavior, while ill formed code -- is code that isn't well formed
    and that isn't constrained to any behavior. A bit too circular for
    me. But I guess syntactically invalid code must be ill-formed and
    cannot have UB.

    "UB" is behavior which is undefined by the C++ standard. Another
    standard or the implementation can define the behavior, making the
    program valid.

    I suspect "ill-formed" is meant for programs which cannot or should
    not be made valid by another standard or implementation.

    AFAICT any program construction that makes a program ill-formed
    is the same as undefined behavior, except that the ill-formed
    cases require a diagnostic (unless the C++ standard explicitly
    says otherwise for the specific case in question).

    Consider for example paragraph 8 in section 4.1:

    A conforming implementation may have extensions (including
    additional library functions), provided they do not alter the
    behavior of any well-formed program. Implementations are
    required to diagnose programs that use such extensions that
    are ill-formed according to this document. Having done so,
    however, they can compile and execute such programs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Alf P. Steinbach on Mon Nov 15 08:46:01 2021
    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    On 13 Nov 2021 19:26, Tim Rentsch wrote:

    "Alf P. Steinbach" <alf.p.steinbach@gmail.com> writes:

    [...]

    Ill formed program doesn't compile, and always causes a diagnostic.

    The C++ standard identifies several sets of circumstances that
    cause a program to be ill formed, but explicitly and specifically
    do not require a diagnostic.

    Oh you're right, thanks. Sorry.

    No worries. Your description is mostly right, and in fact I
    think it should _always_ be right. That there are exceptions
    is IMO a flaw in how the C++ standard is written.

    I was talking about the in-practice but clearly some ill formed
    programs can't even practically be diagnosed as such.

    The difference between UB and ill-formed gets less clear then, but
    mainly that UB is well formed code that isn't constrained to any
    behavior, while ill formed code -- is code that isn't well formed
    and that isn't constrained to any behavior. A bit too circular
    for me. But I guess syntactically invalid code must be ill-formed
    and cannot have UB.

    To be fair, any C++ construction that is ill-formed does require
    a diagnostic, unless there is a specific statement that no
    diagnostic is required. (Disclaimer: I am not 100% sure that
    the previous sentence holds true in the case of violations of
    the One Definition Rule.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)