Re: [PATCH 00/11] pragma once: treewide conversion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 3, 2021 at 11:46 AM Tom Tromey <tom@xxxxxxxxxx> wrote:
>
> It's also worth noting that in GCC it is slower than include guards.
> See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58770
>
> It's just a bug, probably easy to fix.  On the other hand, nobody has
> ever bothered to do so.

That bugzilla is actually worth reading, if only to explain how the
include guard is more robust technology compared to #pragma once.

The traditional include guarding with #ifndef/#define/#endif around
the contents has the advantage that a compiler _can_ generate the
obvious trivial optimizations of just memoizing that "oh, I've seen
this filename already, and it had that include guard pattern, so I
don't need to include it again".

But, I hear you say "that's exactly what '#pragma once' does too!".

No, it's not. There's actually two huge and very fundamental
differences between '#pragma once' and the traditional include guard
optimization:

 (a) the traditional include guard optimization HAS NO HIDDEN SEMANTIC
MEANING. It's a pure optimization that doesn't actually change
anything else. If you don't do the optimization, absolutely nothing
changes.

 (b) the traditional include guard model allows for overriding and is
simply more flexible

And the GCC bugzilla talks about some of the issues with (a), and I
already mentioned one similar issue with (a) wrt sparse: exactly what
is it that "#pragma once" really protects?

Is it the filename? Is it the _canonical_ filename? What about
symbolic links or hardlinks? Is it the inode number? What about
filesystems that don't really have those concepts?

The above questions aren't some made-up example. They are literally
FUNDAMENTAL DESIGN MISTAKES in "#pragma once".

In contrast, include guards just work. You give the guard an explicit
name, and that solves all the problems above, and allows for extra
flexibility (ie the (b) issue: you can override things and include
things twice if you know you're playing games, but you can also use
the guard name to see "have I already included this file" for when you
have possible nasty circular include file issues etc).

So the traditional include guard model is simply technically the superior model.

This is why I'm NAK'ing "#pragma once". It was never a good idea, and
the alleged advantage ("faster builds by avoiding double includes")
was always pure garbage because preprocessors could do the same
optimization using the traditional include guards. In fact, because
the traditional include guards have well-defined meaning and doesn't
have any of the questions about what makes a file unique, and a missed
optimization doesn't cause any semantic differences, a compiler has a
much _easier_ time with that optimization than with the ostensibly
simpler "#pragma once".

Most #pragma things are not wonderful. But '#pragma once' is actively bad.

             Linus



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux