Skip to content

[basic.type.qualifier] *const object* definition does not include objects nested within const objects by byte arrays that provide storage #793

@MitalAshok

Description

@MitalAshok

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

Reference (section label): [basic.type.qualifier]

Link to reflector thread (if any):

Issue description:

const object is used to define what objects are UB to modify ([dcl.type.cv]p4). The current definition only mentions subobjects of another const object, but when a byte array provides storage ([intro.object]p3) for another object, it is not a subobject. However, it should still be UB to modify.

For example, this program appears to be well defined:

struct X {
    X() {
        p = new (storage) int(7);
    }
    alignas(int) std::byte storage[sizeof(int)];
    int* p;
};

int main() {
    const X x;
    *x.p = 0;
    return *x.p;
}

Since the int object created by the new-expression is of type int and is not a subobject ([intro.object]p3 explicitly says it's a complete object), it is not a const object, so [dcl.type.cv]p4 does not make this modification undefined behaviour.

Also consider const arrays providing storage for objects with mutable subobjects:

struct A {
    mutable int i;
};

struct X {
    X() {
        new (storage) A{ 7 };
    }
    alignas(A) std::byte storage[sizeof(A)];
};

int main() {
    const X x;
    const A* p = std::launder(reinterpret_cast<const A*>(x.storage));
    p->i = 0;
    return p->i;
}

Suggested resolution:

Modify [basic.type.qualifier]p(1.1) as follows:

A const object is an object of type const T or a non-mutable subobject of a const object or a non-mutable subobject of a const object or an object where there exists a const object that provides storage for the complete object ([intro.object]p5) of that object.

Similarly modify [basic.type.qualifiers]p(1.2) as follows:

A volatile object is an object of type volatile T or a subobject of a volatile object or an object where there exists a volatile object that provides storage for the complete object of that object.

And similarly modify [basic.type.qualifier]p(1.3) as follows:

A const volatile object is

  • an object of type const volatile T,
  • a non-mutable subobject of a const volatile object,
  • a const subobject of a volatile object, or
  • a non-mutable volatile subobject of a const object,
  • an object where there exists a const volatile object that provides storage for the complete object of that object,
  • a const object where there exists a volatile object that provides storage for the complete object of that object, or
  • a volatile object where there exists a const object that provides storage for the complete object of that object.

It also might be possible to write it as:

A const volatile object is an object that is both a const object and a volatile objectof type const volatile T, a non-mutable subobject of a const volatile object, a const subobject of a volatile object, or a non-mutable volatile subobject of a const object.


Related discussion: LWG3870, CWG2514

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