I'd like to make conditional use of newer C++ language features in OMR. The goal would be to allow newer features when available, while falling back gracefully to nonstandard compiler extensions, or empty symbols, when not available.
The goal wouldn't be to upgrade the minimum supported compiler versions, nor to use newer stdlib editions.
Some things I would like to support:
nullptrconstexprfinalnoexceptstatic_assertThe upside is, consumers who compile OMR with newer C++ editions would enjoy a better interface that can take advantage of these newer features. The downside is that this will introduces more variability to the codebase.
Looking at constexpr as an example, I want to define an OMR_CONSTEXPR symbol to constexpr when available, or empty if not. If constexpr is available, we'll also define the symbol OMR_HAVE_CONSTEXPR, which can be used for #ifdefing. Further, constexpr semantics change across C++ editions. We'd also provide a variant, OMR_CONSTEXPR14/ OMR_HAVE_CONSTEXPR14 for code that is only constexpr since C++14.
There are two possible ways to decide how and when to define these symbols:
omrcfg.h. Once determined, the features used by OMR will not change, the interface is "stuck".noexcept, but the consumer sees it declared with throw()? A linker error, or are we okay?An easy implementation would be to use the cmake module WriteCompilerDetectionHeader. here is an example of what the module outputs. This header uses strategy 2 when defining symbols. One problem here is, the header will name compiler feature macros with the prefix OMR_COMPILER_, which is already a prefix we reserve for the jit.
I'm leaning towards a hand-rolled header, using strategy 2, where the conditions are derived from cmake's implementation, but the symbol naming conventions are our own.
What would people like to see?
I'm mostly supportive of this effort. There are several places in the OMR compiler where these C++11 features would be very useful. In fact, there are a few components of the C++11 standard library that had to be reimplemented. Maybe these could be consolidated?
A couple of thoughts about supported features:
static_cast is one of the few features that should be available on all our supported compilers, as it's used in the OMR compiler source. Maybe we can skip creating a wrapper for it?override (to go with final).Regarding constexpr: While I believe it to be an extremely useful feature and would love to be able to use it, I am a little concerned about some of the complexity of having the fall-back code. There are some cases where there simply dropping the constexpr won't work, so it's use would have to limited to a subset of what constexpr can do.
I want this for static_assert in particular.
I also don't particularly care about the fallback - we have enough builds on real compilers that we'll get what we need from the assertions.
I'm also a +1 to the static_assert case and echo @Leonardo2718's comments about the fallback for constexpr.
My overall impression is that this is driven by the technology - here are tools let's apply them. Can you reformat this to be driven by the problems you're trying to solve?
What problems of OMR's does using these solve? How does each one improve the code base? Tackling them one a time in this manor would result in a much stronger proposal which would allow approving / rejecting on an individual feature basis
I'm not convinced we need fallbacks for a lot of these - do it if the compiler supports it, otherwise ignore. We have enough modern compilers that we should catch any errors.
W.r.t. static_assert we can just use the compiler supported construct. See eclipse/openj9#7685. I see @pshipton has already made the change for AIX. I think we're only missing z/OS then. I'll try to get this done in the next few days.
Most helpful comment
I want this for static_assert in particular.