[Clang 16] Notice of potentially breaking changes

The community is trying out a new way to alert interested parties about potentially disruptive changes in pre-release versions of our tools, and this post is the first such attempt at that. We expect to post these announcements to this channel and mark the posts with potentially-breaking so people can more easily be alerted without having to track development progress as closely. We’ve also added a potentially breaking changes section to our release notes to highlight concerns.

As this is the first such post, there are a few potentially breaking changes to Clang that are worth highlighting:

  • Clang will now correctly diagnose as ill-formed a constant expression where an enum without a fixed underlying type is set to a value outside the range of the enumeration’s values.
    enum E { Zero, One, Two, Three, Four };
    constexpr E Val1 = (E)3;  // Ok
    constexpr E Val2 = (E)7;  // Ok
    constexpr E Val3 = (E)8;  // Now diagnosed as out of the range [0, 7]
    constexpr E Val4 = (E)-1; // Now diagnosed as out of the range [0, 7]

Due to the extended period of time this bug was present in major C++ implementations (including Clang), this error has the ability to be downgraded into a warning (via: -Wno-error=enum-constexpr-conversion) to provide a transition period for users. This diagnostic is expected to turn into an error-only diagnostic in the next Clang release.

  • -Wincompatible-function-pointer-types now defaults to an error in all C language modes. It may be downgraded to a warning with -Wno-error=incompatible-function-pointer-types or disabled entirely with -Wno-implicit-function-pointer-types.
    void func(const int *i);
    void other(void) {
      void (*fp)(int *) = func; // Previously a warning, now a downgradable error.
    }

NOTE: We recommend that projects using configure scripts verify that the results do not change before/after setting -Werror=incompatible-function-pointer-types to avoid incompatibility with Clang 16.

  • Clang now disallows types whose sizes aren’t a multiple of their alignments to
    be used as the element type of arrays.
  typedef char int8_a16 __attribute__((aligned(16)));
  int8_a16 array[4]; // Now diagnosed as the element size not being a multiple of the array alignment.
2 Likes

7 is “outside the range of the enumeration’s values” (which would be 0…4), although it would be within the range of the minimum bitwidth required to represent all the enumeration’s values.

2 Likes

Can all the issues be reproduced with Clang 15 and -Werror=enum-constexpr-conversion -Werror=incompatible-function-pointer-types, or can you think of any case when this wouldn’t catch the same issues?

Yes to the -Wincompatible-function-pointer-types diagnostic, but no to the -Wenum-constexpr-conversion diagnostic. The former is catching the same set of issues it was previously catching in Clang 15, just with a different default status. The latter is a fixed bug where we silently accepted invalid code; -Wenum-constexpr-conversion doesn’t exist in Clang 15.

My complaint about enum-constexpr-conversion is that the description does not correctly say what is allowed and what isn’t. It’s not the range of values, it’s the bitsize needed to represent the range, that appears to be the controlling factor.
If you want enum-constexpr-conversion to genuinely complain about the actual range, then it has a bug.

I think we should move the detailed discussion part to another topic outside of the “announcement” category, this category is intended to broadcast to a large number of people. (Alternatively I can move the entire thread back to clang)

1 Like