OR in version conditional compilation

jxel jxel at gmall.com
Sat Mar 21 01:21:20 UTC 2020

On Saturday, 21 March 2020 at 00:12:20 UTC, Jonathan M Davis 
> On Friday, March 20, 2020 4:33:58 PM MDT jxel via 
> Digitalmars-d-learn wrote:
>> On Friday, 20 March 2020 at 21:03:55 UTC, Jonathan M Davis 
>> wrote:
>> > On Wednesday, March 18, 2020 10:23:26 AM MDT IGotD- via
>> >
>> > Digitalmars-d-learn wrote:
>> >> I have not seen any example where version has several OR 
>> >> matches.
>> >>
>> >> Example idiom:
>> >>
>> >> version(X86_64 || X86)
>> >> {
>> >>
>> >> }
>> >> else version(ARM || Thumb)
>> >> {
>> >>
>> >> }...
>> >>
>> >> you get the idea. So is this possible at all or do you have 
>> >> to duplicate the code for each version identifier despite 
>> >> they are equal for many version identifiers?
>> >
>> > To add to what the others have said, the reasons that Walter 
>> > is against having boolean conditions in version statements 
>> > have to do with how using boolean conditions in #ifdefs in 
>> > C/C++ has historically been a big source of bugs. So, 
>> > disallowing it helps prevent certain classes of bugs. It's 
>> > why druntime duplicates most C declarations across platforms.
>> What kind of bugs are those?
> There are a variety of issues that come from it, and it's been 
> discussed at length in past threads (and much better than I'll 
> explain here, I'm sure), but the main issues stem from the fact 
> that when you're writing code that is platform-dependent but 
> using it on multiple platforms, it can become really easy to 
> break stuff as the code is altered over time. e.g. you can make 
> a change that works perfectly fine on the platform that you're 
> developing on without realizing that it won't work on the other 
> platforms sharing the same #ifdef block, and while you should 
> be testing such code on all supported platforms, it often 
> doesn't happen, and even when it does happen, it's usually much 
> further down the line after many more changes have been made. 
> It would be highly abnormal for someone to test what they're 
> working on on all of the relevant platforms as they're working 
> on it.

None of that is limited specifically to ifdefs. If you modify 
code not in an ifdef you can still cause bugs that only 
materialize on specific platforms. This is the nature of building 
for multiple platforms at the low level, hell you'll still have 
problems even in Java.

The D test suite doesn't run unit tests for every platform for 
all libraries. There's also debug assert statements that fail, 
and at least last I checked for some platforms didn't run debug 
builds, so the tests don't catch this. And not everyone develops 
for those platforms so I guess no one does a debug build on their 
systems either.

> It also can get really tricky to avoid subtle bugs once you 
> start having more complex boolean expressions and/or have 
> nested #ifdefs. That's where things tend to get _really_ bad. 
> Another big problem comes in when you just assume that the code 
> from one platform will work with another and alter existing 
> #ifdefs to be used on the new platform. Suddenly code that was 
> only supposed to be used on one platform is being used on 
> multiple, and it can cause big problems depending on what that 
> code actualy does and what assumptions were made when writing 
> it. By simply following the basic idiom of
> version(A)
> {
> }
> else version(B)
> {
> }
> else
>     static assert(false, "Platform not supported");
> you avoid problems that stem from code being used an a platform 
> that it's not intended for, and you get compilation errors if 
> you try to use code on a platform that it wasn't made to work 
> on yet. It can result in more code duplication than many people 
> like, but it's ultimately less error-prone. Either way, in 
> general, it's far better to design your code such that as 
> little of it as possible is platform-dependent and that those 
> parts that are are well-encapsulated.
> - Jonathan M Davis

Like I said in my other comment. This only works if you can 
assert out of it, and in C and C++ it is the same.

There's a bigger problem that still isnt solved, if you need one 
version statement that doesn't assert to failure. Since a typo 
will just evaluate to false, the version statement may never be 
active under any circumstance and it would be difficult to fins 
such a bug. For example for conguration options, there's no other 
versions you would put in else versions, and it isnt intended to 
fail if that configuration version isnt there. The version 
feature inherited one of C's worst characteristics of the 
preprocessor for ifdef.

More information about the Digitalmars-d-learn mailing list