Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Easy way to detect where the C++11/C++14 features are used in a C++ project (cppdepend.com)
48 points by virtualcpp on June 25, 2017 | hide | past | favorite | 23 comments


Disable C++11/14 with a compiler flag (or use an old compiler version) and try to build the project :-P


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.")

http://lists.llvm.org/pipermail/llvm-bugs/2017-June/056419.h...


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.


The problem is the compiler can't necessarily even parse the file with an older version of the language.


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


Nah, it's true. Here's dumb example, where the compiler errors totally miss make_unique:

  #include <memory>
  #define u8 }{
  struct Foo {
  	char const *foo() {
  		char const *r = u8"foo";
  		std::make_unique<int>(1);
  		return r;
  	}
  };
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.


Here's another example:

Test code:

#include <memory>

int main()

{

        std::unique_ptr<int> pPointer = std::make_unique<int>();
        return 0;
}

Here's the GCC output (v4.9.2) with C++14:

geezerjay@debian:tmp$ g++ --std=c++14 main.c++

geezerjay@debian:tmp$

And now the GCC output with C++11:

geezerjay@debian:tmp$ g++ --std=c++14 main.c++

main.c++: In function ‘int main()’:

main.c++:5:34: error: ‘make_unique’ is not a member of ‘std’ std::unique_ptr<int> pPointer = std::make_unique<int>();

                                  ^
main.c++:5:51: error: expected primary-expression before ‘int’

  std::unique_ptr<int> pPointer = std::make_unique<int>();
geezerjay@debian:tmp$

Perhaps recent GCC versions catch this issue, but errors are indeed thrown if make_unique, a C++14 feature, is present while compiling C++11 code.


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.


> I wouldn't blame the compiler

I'm not blaming anybody/anything though

> 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.


> Here's dumb example, where the compiler errors totally miss make_unique:

Sounds like you've found a bug in GCC. Why not report it?


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.


Oops. What a mess of features.


Then I suppose you have your answer.


Answer to what?


Most compilers stop after encountering a certain number of errors, like 20.


IIRC you can increase the displayed error count.


If I try to compile a project to use and it has over 20 errors, I'm probably not going to be sticking around to use it


An easier way would be when you change -std=c++1y to -std=c++03 it won't compile.


thanks for the ad




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: