Skip to content

CWG2823 [expr.unary.op] p1 should explicitly specify the behavior if the expression does not refer to the object or function #198

Closed
cplusplus/draft
#6684

Description

@xmh0511

Full name of submitter (unless configured in github; will be published with the issue): Jim X

Define the behavior as the manner as in [expr.add] p4

When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.

  • [...]
  • Otherwise, the behavior is undefined.

[expr.unary.op] p1 does not explicitly specify the behavior of the otherwise case.

result is an lvalue referring to the object or function to which the expression points.

So, what if the expression points to the other pointer values?

Suggested resolution

  • if the expression points to an object or function, the result is an lvalue referring to the object or function
  • Otherwise, the behavior is undefined.

Activity

  1. frederick-vs-ja commented on Dec 15, 2022

    @frederick-vs-ja

    I guess this is covered (perhaps non-normative?) "implicit undefined behavior" rule ([defns.undefined]/Note 1). So this case is undefined even though not explicitly stated. There's a similar normative rule in C.

    Such UB may be subject to change, see CWG232 and CWG315.

    Perhaps we need a paper to eliminate all implicit UB, because sometimes it's difficult to determine whether some given behavior is undefined or unspecified.

  2. languagelawyer commented on Dec 15, 2022

    @languagelawyer

    I guess this is covered (perhaps non-normative?) "implicit undefined behavior" rule

    The rule is normative: behavior for which this document imposes no requirements. No requirement == undefined behavior by definition.

  3. jensmaurer commented on Dec 15, 2022

    @jensmaurer
    Member

    In general, I think we want to be explicit about undefined behavior in C++.
    "Undefined behavior by omission" is frowned upon.

  4. villevoutilainen commented on Dec 15, 2022

    @villevoutilainen
    Member

    I would really welcome the suggested change here. This bit in the standard is a topic of recurring questions, and it always takes unfortunately long to explain that a null pointer does not point to an object, and hence dereferencing it is undefined behavior. We have a similar problem at [expr.ref]/6.2, where we say "the expression designates the corresponding member subobject of the object designated by the first expression". There we don't (bother) say(ing) that if no object is designated, we are in the land of UB. That tends to take even longer to explain than the unary operator*. Even if we end up making mere operator* of a null pointer well-defined (See https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232), in all likelihood we'll still (continue to) require that the LHS of an operator-> must be non-null, and questions about that will continue. Unless we just clarify it, along the lines of what's been suggested here.

  5. languagelawyer commented on Dec 15, 2022

    @languagelawyer

    @villevoutilainen thanks for reminding that this issue is just CWG232

  6. changed the title [-][expr.unary.op] p1 should explicitly specify the behavior if the expression does not refer to the object or function[/-] [+]CWG232 [expr.unary.op] p1 should explicitly specify the behavior if the expression does not refer to the object or function[/+] on Dec 15, 2022
  7. xmh0511 commented on Dec 16, 2022

    @xmh0511
    Author

    Perhaps we need a paper to eliminate all implicit UB, because sometimes it's difficult to determine whether some given behavior is undefined or unspecified.

    Yes, this is what I think about here. Read the rule with an implication meaning that would vary to different readers is frowned upon. Explicitly specify what the behavior should be is clear and unambiguous.

  8. xmh0511 commented on Dec 16, 2022

    @xmh0511
    Author

    No requirement == undefined behavior by definition.

    Before I posted this issue, I knew the rule may be interpreted by the implication meaning(i.e. if we didn't specify the behavior, the behavior can be subsumed to undefined behaviors, which is its literal meaning). However, assume [expr.unary.op] p1 falls into UB if the expression is a null pointer value, then how about [expr.typeid] p3

    If the glvalue is obtained by applying the unary * operator to a pointer and the pointer is a null pointer value ([basic.compound]), the typeid expression throws an exception ([except.throw]) of a type that would match a handler of type std​::​bad_­typeid exception ([bad.typeid]).

    Since *(NULL) has been assumed to be UB, why typeid(*(NULL)) instead has the defined behavior? This is contradictory here. So, explicitly defining what behavior should be is looked forward to, instead of by guess, I think.

  9. languagelawyer commented on Dec 16, 2022

    @languagelawyer

    This is contradictory here.

    If assuming the rule «Behavior of evaluating of an expression E does not depend on its context», then yes. But there is no such rule.

  10. FrankHB commented on Feb 10, 2023

    @FrankHB

    I guess this is covered (perhaps non-normative?) "implicit undefined behavior" rule

    The rule is normative: behavior for which this document imposes no requirements. No requirement == undefined behavior by definition.

    The normative wording is the definition, but not the rule of reasoning if the term is not existing in the use sites at the first place, i.e. you cannot get the logical consequeces in both direction randomly. Just like most formal languages (and programming languages), plain English is also not a system having such property in nature.

    If you want to make such a way of reasoning working, you must have some additional meta rules. Such rules can be added by ISO documents normatively, but I don't find such, and I think it is out of the scope of ISO C++. Further, allowing such meta rules potentionally makes the specification (or more seriously, all standards) suffer from higher risks of ambiguity globally, so I don't think it legitemate.

  11. FrankHB commented on Feb 10, 2023

    @FrankHB

    In general, I think we want to be explicit about undefined behavior in C++. "Undefined behavior by omission" is frowned upon.

    This is quite important. I guess this is also the reason that ISO C++ lacks the fallback normative rule equivalent to ISO C 4/2, delibrately. However, the current wording is not intuitive for readers to get the point. We should probably make the intent more normative.

  12. frederick-vs-ja commented on Apr 6, 2023

    @frederick-vs-ja

    I guess this is also the reason that ISO C++ lacks the fallback normative rule equivalent to ISO C 4/2, delibrately.

    I guess this is intended, but the motivation seems mysterious and not well recognized.

    N3090 [defns.undefined] used to say

    undefined behavior
    behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [ Note: [...] — end note ]

    And then the sentence "Undefined behavior may also be expected when [...]." was moved into the note in N3126, even without any editorial mark. The reason of this change wasn't found in the editor's report N3127.

  13. frederick-vs-ja commented on Nov 15, 2023

    @frederick-vs-ja

    This should have been superseded by CWG2823.

  14. changed the title [-]CWG232 [expr.unary.op] p1 should explicitly specify the behavior if the expression does not refer to the object or function[/-] [+]CWG2823 [expr.unary.op] p1 should explicitly specify the behavior if the expression does not refer to the object or function[/+] on Nov 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions