Overeager -Wswitch

Hi all,

We have a codebase using the Poco library and libstdc++. We'd like to
use -Wswitch for our own code, but as soon as we include one of Poco's
headers we get a -Wswitch warning:

In file included from .../Poco/BinaryReader.h:25:
.../Poco/MemoryStream.h:87:12: warning: enumeration value
'_S_ios_seekdir_end' not handled in switch [-Wswitch]
                        switch (way)
                                ^
(source: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/MemoryStream.h#L87)

This turns out not to be a problem in Poco, but a quirk in libstdc++;
they define a last-enumerator, _S_ios_seekdir_end, see here:

This construct looks a little unconventional, but I don't know enough
about the library spec to say whether it's conforming.

So Poco has a fully covered switch per the abstract standard, but on
top of libstdc++ Clang rightfully discovers it doesn't. And because of
Poco's inline impl, we're stuck in the middle...

Is there a way to trim -Wswitch to discover this scenario? I could
work on a patch if it seems doable, but I'm not sure how to address it
without short-circuiting -Wswitch for all system headers, for example.

Alternatively, if we could get a patch into Poco, is there something
like MSVC's #pragma(warning:disable) for Clang, so they could
selectively silence the warning around this function?

Thanks for any ideas,
- Kim

add GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch"
... your function here...
#pragma GCC diagnostic pop

I think it also works with clang as pragma group.

Joerg

Hi Joerg,

Alternatively, if we could get a patch into Poco, is there something
like MSVC's #pragma(warning:disable) for Clang, so they could
selectively silence the warning around this function?

add GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch"
... your function here...
#pragma GCC diagnostic pop

I think it also works with clang as pragma group.

Thanks, that's what I was looking for in the way of disabling. To
confirm, #pragma clang diagnostic also works.

I think we've agreed to rewrite the function in Poco using if/else
instead of switch, because it was hard to find a switch phrasing that
worked with all -W combinations (-Weverything overrode the #pragma
diagnostic and threw diagnostics for code that worked with -Wall).

That said, it might be worth trying to make Clang aware of libstdc++'s
enum convention, but I haven't thought of a way to do so yet.

- Kim

I don't think there is anything Clang can or should do here, but please
fill an upstream report against GCC if they still do it in the most
recent version.

Joerg

Using the last enum value (often suffixed with "_end" or "_last") to track total number of values is a common coding practice so I'm not sure they are going to fix this.

-Y

If it was actually the last value, that wouldn’t be an issue. But it’s actually set to 1L << 16 which is not any of the real values. I expect they’re using this as a trick to force the type of the enum to be a 32-bit int, since before C++11, there was no way to specify the type of the enum directly.

If that’s so, they could switch to using “enum _Ios_Fmtflags : uint32_t” now.

Thanks, that sounds like a plausible explanation.

FWIW, I've filed a bug on libstdc++:
67996 – std::ios_base::seekdir raises -Wswitch with Clang.

And had a pull request accepted to work around this in Poco using an
if/else chain instead of a switch:
https://github.com/pocoproject/poco/commit/883cdb7b14f6738e9b89578bc24806e1b905426b

I suspect libstdc++ won't change, but at least I've worked around my
immediate problem.

Thanks!

- Kim