Just this week I reported a compiler bug to clang saying it accepts the c11 keyword _thread_local in c99 mode, and there seems no set of options which will even make it warn me I'm using c11 constructs. It was closed "wontfix".
Here's the reason for anyone wondering:
_Thread_local is reserved in C99, so we don't need a -pedantic warning.
(Quoting the standard: "All identifiers that begin with an underscore and
either an uppercase letter or another underscore are always reserved for any
use.")
Which I don't really understand.. I mean, you don't need to warn about anything, that's what "warning" means, and having no way of warning that I'm using things from C11 seems weird to me, given how many other warnings exist.
That is not true. When GCC is used to compile a C++11 project with the --std=c++03 or --std=c++98 flags, it parses the whole source tree but throws errors whenever it catches C++11 features.
For example, this is the error message GCC returns when it catches an "override" keyword when compiling with --std=c++03 flags:
> controls (override/final) only available with -std=c++11 or -std=gnu++11
Maybe now you can argue it won't happen in practice, and my intuition is you'd still be wrong for large projects, but I don't have the time to try to come with a more realistic example. Hopefully this is enough to get the point across though. The syntax has changed, and the compiler can be only so smart trying to decipher it efficiently.
I wouldn't blame the compiler for missing make_unique in that scenario. Rather it would be nice if compilers warned that u8"foo" is a C++11 construct and any errors following could be due to it not existing in C++03. It never gets to the make_unique because there's another error before it. In C++11 mode, both g++ and clang++ (I tested 6 and 3.8, respectively) complain about make_unique not being a member of std, as expected.
> It never gets to the make_unique because there's another error before it.
Yes, that was literally the entire point of this example, because the prior commenter had said that GCC doesn't stumble on parsing errors and keeps going anyway.
Ah, right, I might have misunderstood you there. This is a bit of a special case though, as the preprocessor for C++03 messes up the code so badly that a later parser trips, and it never even gets to the pass that resolves identifiers because a critical error is raised before. Maybe then the preprocessor could emit warnings when replacing tokens it knows to be keywords in later standard versions. It likely isn't that easy, though, as emitting helpful warnings would probably require parsing some of the surrounding code, which hasn't happened yet, so the potential for false positives is large.
Sigh, I knew someone was going to just complain that this is using the preprocessor and I'd have to waste more time on this...
(a) It's a fundamental (but common) mistake to view processing as a logically "separate" stage from compiling C++ code. The two are semantically intertwined for all intents and purposes. Trivial example: the value of std::numeric_limits<int>::max() MUST match that of INT_MAX. Another trivial example: #pragmas (like omp parallel or vectorize) are "preprocessor" directives that can't really be "preprocessed"; they're often tightly coupled to the actual code. You cannot preprocess a program with a compiler that differs in any semantically visivle way from the actual compiler and expect the program to behave as the C++ standard specifies. The correct way to see a preprocessed file is as a convenient text-format snapshot/dump of the compiler's memory in the overall compilation process, nothing more.
(b) I don't want to spend more time on this but I'm pretty sure you could find a counterexample that doesn't depend on the preprocessor if you try hard enough. Just pretend I'm claiming the opposite and you're arguing with me about that, trying to prove me wrong. I'm sure you'll find a counterexample. Look at >> vs. > > and the like if you have no idea where to start.
I don't think we're disagreeing. All I meant was that if a critical error arises at a certain stage of compilation, errors that would only be detectable in a subsequent stage won't be emitted. This is in no way limited to this particular use case. Expecting it to continue isn't very realistic.
Doesn't sound like it to me... I don't consider it a bug. I don't think it's even solvable in general. In fact I think GCC is being quite generous in going out of its way to report things so nicely already.