-
Notifications
You must be signed in to change notification settings - Fork 8
Description
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
constT 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 ora 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, andis a bit-field if and only if X is a bit-field, and- has the type
constT 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.