Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions