Skip to content

[expr.const.cast] Changing qualifiers with pointers to arrays when casting away constness is forbidden #989

Description

@Halalaluyafail3

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

Reference (section label): [expr.const.cast]/6

Issue description:

Consider whether or not reinterpret_cast<const int**>((const int(*)[])0) is valid, which requires that the type const int(*)[] does not cast away constness in a conversion to the type const int** due to [expr.reinterpret.cast]/2. This has three possible values of n for different-qualification decompositions to consider with T1 being const int(*)[] and T2 being const int**:

  • n=0, cv01 and cv02 are both empty, U1 is the type const int(*)[], and U2 is the type const int**. Changing each cvi1 to cvi2 has no effect here, so a qualification conversion is valid.
  • n=1, cv01 and cv02 are both empty, P01 and P02 are both "pointer to", cv11 is either const or empty, cv12 is empty, U1 is either the type int[] or the type const int[], and U2 is the type const int*. If [conv.qual] Adding const with pointers to arrays in the qualification-combined type #987 is resolved as not allowing U1 to be the type const int[] then U1 is definitely the type int[] and cv11 is definitely const. Otherwise, if U1 is the type int[] then cv11 must be const. If U1 is the type int[] then changing cv11 to cv12 does have an effect here and causes the qualification conversion to be invalid. If U1 is the type const int[] and cv11 is empty then changing each cvi1 to cvi2 has no effect here, so a qualification conversion is valid. If U1 is the type const int[] and cv11 is const then changing cv11 to cv12 removes the const but it is unclear whether or not the const is actually removed from the resulting type because U1 is still const, so it is unclear whether or not the qualification conversion is valid.
  • n=2, cv01 and cv02 are both empty, P01 and P02 are both "pointer to", P11 is "array of unknown bound of", P12 is "pointer to", cv11 and cv21 are either both empty or both const, cv12 is empty, cv22 is either const or empty, U1 is either the type int or const int, and U2 is either the type int or const int. If [conv.qual] Adding const with pointers to arrays in the qualification-combined type #987 is resolved as not allowing either U1 or U2 to be the type const int, then U1 and U2 are definitely both the type int. Otherwise, if U1 is the type int then cv11 and cv21 must both be const, and if U2 is the type int then cv22 must be const (this second if is not intended to be dependent upon the first if). If U1 is the type int and cv22 is const then changing cv11 to cv12 removes the const but it is unclear whether or not the const is actually removed from the resulting type because cv21 is still const, so it is unclear whether or not the qualification conversion is valid. If U1 is the type int and cv22 is empty then changing cv11 and cv21 to cv12 and cv22 respectively does have an effect here and causes the qualification conversion to be invalid. If U1 is the type const int and cv11 and cv21 are both empty then changing each cvi1 to cvi2 has either no effect or redundantly adds const, so a qualification conversion is valid. If U1 is the type const int and cv11 and cv21 are both const then changing cv11 to cv12 removes the const and changing cv21 to cv22 removes a second const if cv22 is empty but it is unclear whether or not the const is actually removed from the resulting type because U1 is still const and if cv22 is const then the const of cv12 will remain, so it is unclear whether or not the qualification conversion is valid.

Second, consider the whether or not the reverse reinterpret_cast<const int(*)[]>((const int**)0) is valid. This has three possible values of n for different qualification-decompositions to consider with T1 being const int** and T2 being const int(*)[]:

  • n=0, cv01 and cv02 are both empty, U1 is the type const int**, and U2 is the type const int(*)[]. Changing each cvi1 to cvi2 has no effect here, so a qualification conversion is valid.
  • n=1, cv01 and cv02 are both empty, P01 and P02 are both "pointer to", cv11 is empty, cv12 is either const or empty, U1 is the type const int*, and U2 is either the type int[] or the type const int[]. If [conv.qual] Adding const with pointers to arrays in the qualification-combined type #987 is resolved as not allowing U2 to be the type const int[] then U2 is definitely the type int[] and cv12 is definitely const. Otherwise, if U2 is the type int[] then cv12 must be const. In any scenario changing each cvi1 to cvi2 has no effect here or adds const, so a qualification conversion is valid.
  • n=2, cv01 and cv02 are both empty, P01 and P02 are both "pointer to", P11 is "pointer to", P12 is "array of unknown bound of", cv11 is empty, cv21 is either const or empty, cv12 and cv22 are either both empty or both const, U1 is either the type int or const int, and U2 is either the type int or const int. If [conv.qual] Adding const with pointers to arrays in the qualification-combined type #987 is resolved as not allowing either U1 or U2 to be the type const int, then U1 and U2 are definitely both the type int. Otherwise, if U1 is the type int then cv21 must be const, and if U2 is the type int then cv12 and cv22 must both be const (this second if is not intended to be dependent upon the first if). If cv12 and cv22 are both const then changing each cvi1 to cvi2 does have an effect here and causes the qualification conversion to be valid. If U1 is the type int and cv12 and cv22 are both empty then changing cv21 to cv22 does have an effect here and causes the qualification conversion to be invalid. If U1 is the type const int, cv21 is empty, and cv12 and cv22 are both empty then changing each cvi1 to cvi2 has no effect here, so a qualification conversion is valid. If U1 is the type const int, cv21 is const, and cv12 and cv22 are both empty then changing cv21 to cv22 removes the const but it is unclear whether or not the const is actually removed from the resulting type because U1 is still const, so it is unclear whether or not the qualification conversion is valid.

There is disagreement among implementations as to whether or not these casts are valid. What was the intent for these two cases? Specifically, if one const is removed from an array type in a qualification-decomposition of it where const is specified multiple times does that actually remove the const or does it need to be removed from all levels for the const to actually be removed?

Activity

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