Skip to content

CWG2849 [class.temporary] "temporary object other than a function parameter object" wording is wrong #490

Description

@t3nsor

Full name of submitter: Brian Bi

Reference (section label): [class.temporary]

Issue description: From Stack Overflow.

The wording "temporary object other than a function parameter object" does not make sense since a function parameter object is never a temporary object ([class.temporary]/1). In the example that was added during CWG deliberation in Kona (2022) to illustrate this exception, the parameter of f2 is not a temporary in the first place, so there is no exception. Note that in the special case where the implementation creates an extra temporary under [class.temporary]/3, that temporary is not the same as the function parameter object, and its lifetime is unobservable.

Suggested resolution:

Strike "other than a function parameter object" from [class.temporary]/7.

Insert a new note before Example 2 in [stmt.ranged]:

[ Note: A function parameter object is not a temporary object ([class.temporary]), even if its lifetime ends at the end of the full-expression containing the call ([expr.call]). — end note ]

Activity

  1. frederick-vs-ja commented on Jan 22, 2024

    @frederick-vs-ja

    There also seems something wrong in [class.temporary] p3.

    The current wording says:

    [...] implementations are permitted to create a temporary object to hold the function parameter or result object. [...]

    which is inconsistent with the next sentence:

    [...] The temporary object is constructed from the function argument or return value, respectively, [...]

    It seems to me that the part "to hold the function parameter or result object" is redundant and defective, perhaps we should strike it.

  2. t3nsor commented on Jan 22, 2024

    @t3nsor
    Author

    There also seems something wrong in [class.temporary] p3.

    The current wording says:

    [...] implementations are permitted to create a temporary object to hold the function parameter or result object. [...]

    which is inconsistent with the next sentence:

    [...] The temporary object is constructed from the function argument or return value, respectively, [...]

    It seems to me that the part "to hold the function parameter or result object" is redundant and defective, perhaps we should strike it.

    I think that could be fixed as part of CWG2434 (which probably needs a volunteer for drafting)

  3. jensmaurer commented on Jan 22, 2024

    @jensmaurer
    Member

    One says "function parameter or result object", the other "function argument or return value". Note parameter vs. argument.

  4. jensmaurer commented on Jan 22, 2024

    @jensmaurer
    Member

    If a parameter object is not a temporary object, what is the storage duration related to a function parameter object? (Function parameter objects may be destroyed when the function returns, or at the end of the full-expression. Does the storage outlive the point of destruction, at least in the former case?)

  5. t3nsor commented on Jan 23, 2024

    @t3nsor
    Author

    If a parameter object is not a temporary object, what is the storage duration related to a function parameter object? (Function parameter objects may be destroyed when the function returns, or at the end of the full-expression. Does the storage outlive the point of destruction, at least in the former case?)

    In current wording, parameter objects unambiguously have automatic storage duration under [basic.stc.auto]/1 notwithstanding the special rules in [expr.call]/6 about when they're destroyed.

    I don't think we ever explicitly say when storage lifetime ends, except in the case of dynamic storage duration, but that's a different issue.

  6. jensmaurer commented on Jan 23, 2024

    @jensmaurer
    Member

    I don't think we ever explicitly say when storage lifetime ends,

    We do:

    [basic.stc.auto] p1 says:

    The storage for these entities lasts until the block in which they are created exits.

    Since parameter objects are created in the caller, that means their storage stays around until the end of the block (and can't be reused by the compiler unless proven otherwise).

  7. t3nsor commented on Jan 23, 2024

    @t3nsor
    Author

    [basic.stc.auto] p1 says:

    The storage for these entities lasts until the block in which they are created exits.

    Since parameter objects are created in the caller, that means their storage stays around until the end of the block (and can't be reused by the compiler unless proven otherwise).

    That seems unlikely to be what we actually want, right? If a block contains two separate statements that each contain a function call, it seems obvious that the second function call can reuse the space in which the first function call allocated parameter objects.

    I think what we want is for the storage lifetime for parameter objects to parallel the (implementation-defined choice of) lifetime, and [stmt.dcl] probably needs to be amended too.

  8. jensmaurer commented on Jan 24, 2024

    @jensmaurer
    Member

    That seems unlikely to be what we actually want, right?

    Right. That means we have three issue with "storage duration", at least in the sense of "how long does the storage exist":

    • storage duration for temporaries
    • storage duration for parameter objects
    • storage duration for exception objects
  9. jensmaurer commented on Jan 30, 2024

    @jensmaurer
    Member

    CWG2849 for the original issue.

  10. changed the title [-][class.temporary] "temporary object other than a function parameter object" wording is wrong[/-] [+]CWG2849 [class.temporary] "temporary object other than a function parameter object" wording is wrong[/+] on Jan 30, 2024
  11. t3nsor commented on Jan 30, 2024

    @t3nsor
    Author

    If we decide we also want to tackle the wider "storage duration of function parameters" issue then here's a first attempt at some drafting.

    Edit [basic.stc.auto]/1, combining it with the note in paragraph 2. (The "end of duration of storage" wording is borrowed from [basic.stc.general].)

    Variables that belong to a block or parameter scope and are not explicitly declared static, thread_local, or extern have automatic storage duration. The storage for these entities such block variables lasts until the block in which they are created exits.
    [ Note 1: These block variables are initialized and destroyed as described in [stmt.dcl]. —end note ]
    It is implementation-defined whether the duration of storage for a parameter ends when the function in which it is defined returns or at the end of the full-expression containing the call.
    [ Note 2: Parameters are initialized and destroyed as described in [expr.call]. — end note ]

    Edit [class.temporary]/8:

    The destruction of a temporary whose lifetime is not extended beyond the full-expression in which it was created is sequenced before the destruction of every temporary which is constructed earlier in the same full-expression. Let x and y each be either a temporary object whose lifetime is not extended, or a function parameter. If the lifetimes of x and y end at the end of the same full-expression, and the initialization of x is sequenced before that of y, then the destruction of y is sequenced before that of x. If the lifetime of two or more temporaries with lifetimes extending beyond the full-expressions in which they were created ends at the same point, these temporaries are destroyed at that point in the reverse order of the completion of their construction. [...]

    Edit [expr.call]/6:

    [...] It is implementation-defined whether the lifetime of a parameter ends when the function in which it is defined returns or at the end of the enclosing full-expression. When the duration of storage for one or more parameters ends ([basic.stc.auto]), all such parameters are destroyed in the reverse order of their construction. The initialization and destruction of each parameter occurs within the context of the full-expression ([intro.execution]) where the function call appears.

    Edit [stmt.dcl]/2 to clarify that it applies only to block variables, since that seems to be the original intent anyway (e.g., we don't guarantee that function parameters are initialized in declaration order). Since function parameters don't have a declaration-statement, it would make more sense to describe them elsewhere.

    A block variable with automatic storage duration ([basic.stc.auto]) is active everywhere in the scope to which it belongs after its init-declarator. Upon each transfer of control (including sequential execution of statements) within a function from point P to point Q, all block variables with automatic storage duration that are active at P and not at Q are destroyed in the reverse order of their construction. Then, all block variables with automatic storage duration that are active at Q but not at P are initialized in declaration order; unless all such variables have vacuous initialization ([basic.life]), the transfer of control shall not be a jump. When a declaration-statement is executed, P and Q are the points immediately before and after it; when a function returns, Q is after its body.

  12. t3nsor commented on Feb 2, 2024

    @t3nsor
    Author

    I updated the drafting above based on feedback from today's telecon.

  13. jensmaurer commented on Feb 3, 2024

    @jensmaurer
    Member

    CWG2850 for the storage duration of function parameter objects

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