Skip to content

CWG3158 [expr.prim.id.qual] Constification fails to apply to splice-expressions #844

@katzdm

Description

@katzdm

Full name of submitter: Dan Katz

Reference (section label): [expr.prim.id.qual]/4.2

Issue description:
The P2900 "constification" mechanism specifically applies to unqualified-ids. The mechanism can therefore be bypassed by instead referring to the same entity by way of a splice-expression, even though that "bypass" can be trivially detected during translation. It seems clear that the same constification-transform should apply to any such splice-expression referring to any such "non-local" variable or object within a contract assertion.

void f(int p)
  pre([&] { ++p; return true; }())  // error: unqualified-id 'p' has const type
  pre([&] { ++[:^^p:]; return true; }())  // lol sounds great
{
}

Suggested resolution:
Break [expr.prim.splice]/2.3 into two paragraphs and modify as follows:

  • Otherwise, if S is an object of type T, the expression

    • is an lvalue designating S,
    • is a bit-field if and only if S is a bit-field, and
    • has the type const T if the expression appears in a contract assertion C such that S is introduced by a variable declared outside of C or otherwise T.
  • Otherwise, if S is an object or a non-static data member, the expression is an lvalue designating S. The expression has the same type as that of S, and is a bit-field if and only if S is a bit-field.

Modify [expr.prim.splice]/2.5 as follows:

  • Otherwise, if S is a variable or a structured binding, where T is the type of S, S shall either have static or thread storage duration or shall inhabit a scope enclosing the expression. The expression:
    • is an lvalue referring to the object or function X associated with or referenced by S,
    • has the same type as that of S, and is a bit-field if and only if X is a bit-field, and
    • has the type const T if the expression appears in a contract assertion C such that S is declared outside of C or otherwise T.

A few other wording approaches might be worth considering:

  • We could define the "constification" transform in a more reusable way in e.g., [basic.contract] (e.g., as a mapping from a (designating-expression, entity)-pair to a constified type), then use that definition in both [expr.prim.id.unqual] and [expr.prim.splice].
  • We could try to perform the adjustment holistically in [expr.type] for all glvalues whose result is an entity declared outside of a contract assertion.

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