Repository of buggy compiler versions for C++11 support - c++

I have a C++ soft that gets compiled with different OSes, platforms & compilers. Now sometimes compiler have bugs e.g. for instance this one, which implies that gcc versions pre 4.6.4 and pre 4.7.3 are a no-go. Now i could include a unit test that showcases the bug (and perhaps this question will reveal that indeed that's what I should be doing) but this is a tedious task: compiler bugs are sometimes hard to repro and turning one into a unit test might not be easy either... and that's when you have the platform & compiler at hand.
What I'm looking for is a repository that tells me which versions of g++, clang++ and msvc++ suffers from fatal bugs for supporting C++11 (i'm not talking about missing features, when features are not there I work around them). I would then fatal crash when building with them in the build system. Nice feature is, I'm not even forced to hit a bug to ban a compiler (so I'm saving myself future trouble).
Does such a list exist?

This is probably not the answer you are looking for, but I believe the correct way to deal with this is to have a white-list, rather than a black-list. In other words, have a list of compilers that you know works, and if the customer tries to build using a different version than the ones you have tested with, you issue a warning message as part of the build script saying something like this:
This compiler is not supported, please see
http://www.example.com/list_of_supported_compilers.html for a list of
compilers we support. If you choose to continue using this compiler,
feel free to do so, but don't expect full support from our
tech-support, if you find a problem.
The reason I say this is that:
You will not be able to prove that EVERY version other than what is on your blacklist works correctly. You can, however, for whatever testcases you have, prove that compiler X version a.b.c-d works [this doesn't mean that this compiler is bug free - just that you haven't hit any of those bugs in your testing!]
Even if the compiler is "known good" (by whatever standard that is defined), your particular code may trigger bugs that affect your code.
Any sufficiently large software (or hardware) product will have bugs. You can only show that your software works by testing it. Relying on external "there is known bug in version such and such of compiler X" will not help you avoid bugs affecting your code. Having said that, most compilers are fairly well tested, so you (usually) need to do some fairly unusual/complicated things to make the compiler fail.

Investigate Boost.Config, in particular the header <boost/config.hpp>.
This includes a large group of macros for a wide variety of compilers (and different versions there of) which indicate which C++ features are enabled, broken etc. It also includes a comprehensive test suite which can be used to test any new compiler for missing features etc.

Related

Using different C++ standard for different parts of the same file

Ok, I know this sounds like a broken question, but let me explain before the downvotes start: we are using C++11 as a baseline for our development (targeting several platforms). Recently a few changes needed to be done in our codebase and suddenly the need for some C++17 features crawled in.
All is fine till now, on our developer platform all compiles nicely, but on one of the continuous integration platforms (Ubuntu 18.04) we have got some errors, like:
/usr/include/ev++.h:355:46: error: ISO C++1z does not allow dynamic exception specifications dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)
(c++1z dynamic exception specification error gives a good explanation why this happens and also offers some hacks on how to make it disappear)
But I started thinking (theoretically only, of course) that would it be possible that we specify some portions of a source file to be compiled with code conforming to C++11 and other parts with code conforming to C++17?
(And just to clarify: No, we don't want to upgrade, and yes, we have solved the problem, again, I am just interested in a theoretical approach)
In theory-theory it would be possible. Compiling different parts of file with different standards is effectivelly splitting the file and using different backend for every of these parts. It should not be that hard. But there is one big caveat - ABI compatibility. When you realize that linking object files compiled with different standards is often not possible, you see this whole idea is a landmine. The compiler would have to either keep the ABI stable (which would be nice but with the amount of changes made with every standard, keeping the ABI compatible between them would be a nightmare) or somehow translate the ABIs of different standards (this would also be nightmarish I suppose). Even now the most popular way to keep the ABI problems 'in check' is using extern "C" to avoid all fuss.
So the answer is - it would be possible in theory but the practical implications of such choice would be so dramatic that it is not worth it.

Tool for verifying effect of Visual Studio conformance switches on generated code

A recent minor release version of Visual Studio (15.7) implements the compiler switch /permissive-, which among other effects, enables two-phase name lookup for templates (https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance). I'd like to enable this switch on our codebase of about 4M lines of code. The problem is, the instantiated templates might change if this switch is enabled (see the first example at https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-phase-name-lookup-support-comes-to-msvc/), which lead to silent changes in the run-time behavior.
Is there a way to check whether the code generated with this conformance switch enabled is identical to the old code?
I'm aware that the correct answer is "you run your unit tests, duh!". Sadly with the amount of legacy code lying around, this is out of reach for the next couple of years, so I'm looking for an alternative.
Doing a compare on the binaries does not help, since there are differences present due to metadata changes.
New compilation errors aren't really of any help either: they only expose non-conforming syntax; changes in generated code can still be hidden.
Actually seeing the generated code is not important. A tool showing "this line will compile differently" would be sufficient. Or something similar to what "Preprocess to a File" does for the preprocessor.
The best I can think of is checking generated symbols via the dumpbin tool on every .obj file to see whether the same ones are being generated. This can expose only a subset of issues: the set of template instances in a file might be identical, but their locations in the code might be change.
You may analyze the compiler output (at assembly level) to check for differences generated with the 2 compiler settings you mentioned.
Please look at this related SO question about Visual C++ compilers.
Also, better suited for relatively small portions of code,
you may want to use the marvelous GodBolt's Compiler Explorer,
that does the same task but with an handy web interface and extended to various compilers (not only Microsoft Visual C++).
I'm sure it will become one of the most valuable tools in your developer's toolset.

C++11 equivalent to std::quoted introduced in C++14

As used in this answer, I'm looking for a C++11 compatible code for the same but the usage of std::quoted prevents me from achieving that. Can anyone suggest an alternative solution?
I give my answer assuming that you expect to find a generic approach to handle such situations. The main question that defines the guideline for me is:
"How long am I supposed to maintain this code for an older compiler version?"
If I'm certain that it will be migrated to the newer toolset along with the rest of the code base (even though in a few years time, but it will inevitably happen), then I just copy-paste implementation from the standard headers of the next target version of my compiler and put it into namespace std in a separate header within my code base. Even though it's a very rude hack, it ensures that I have exactly the same code version as the one I'll get after migration. As I start using newer (in this case C++14-compatible) compiler, I will just remove my own "quoted.h", and that's it.
Important Caveat: Barry suggested to copy-paste gcc's implementation, and I agree as long as the gcc is your main target compiler. If that's not the case, then I'd take the one from your compiler. I'm making this statement explicitly because I had troubles when I tried to copy gcc's std::nested_exception into my code base and, having switched from Visual Studio 2013 to 2017, noticed several differences. Also, in the case of gcc, pay attention to its license.
If I'm in a situation where I'll have to maintain compatibility with this older compiler for quite a while (for instance, if my product targets multiple compiler version), then it's more preferable first of all to look if there's a similar functionality available in Boost. And there is, in most cases. So check out at Boost website. Even though it states
"Quoted" I/O Manipulators for Strings are not yet accepted into Boost
as public components. Thus the header file is currently located in
you are able to use it from "boost/detail". And, I strongly believe that it's still better than writing your own version (despite the advice from Synxis), even though the latter can be quite simple.
If you're obliged to maintain the old toolset and you cannot use Boost, well...then it's maybe indeed worth thinking of putting your own implementation in.

Deal with project which may contain undefined behaviour

I would like advice how to proceed in such situation.
Imagine I have large C++ project which works well.
I have suspicion there might be some UB in this code (because in different project written by same author I found UB).
Now, say I need to add new features to this project.
I am afraid because:
if I recompile with new compiler this can increase risk of UB happening if in the code is UB already. (e.g. new compiler might not be OK with UB which the old compiler was fine with).
Is it realistic to eliminate all UB in this large project by eye inspection (before I move to adding new feature)??
If not, then I should at least compile with same version of compiler right? (to decrease chance of problems if there is UB).
Project is done in Visual Studio so I don't know if there are object files, in which case, I could leave object files same and only modify parts in files where I need to add something - thus again minimizing risk of UB.
What is the course of action in such situation? I think this could be pretty common scenario.
I like suggestion that I test the project using new compiler before adding new code, but even then - we know testing might not reveal UB, isn't it?
In order, I would:
Compile with -Wall (/W4 for you Windows folk) and fix errors.
Write tests if there aren't any already.
Use tools like valgrind to detect issues and fix them.
Study synchronization primitives if in use, and use modern paradigms where possible.
Document the code and adhere to a style guide.
I would not attempt to avoid problems by keeping object files around. That's a nightmarish maintenance problem.
Undefined Behavior = Bugs
It's impossible to prove that a project is bug-free. Even the best programmers do create bugs. Even the best code-review cannot eliminate all bugs in a project. No, it's not realistic to eliminate all UB in a project of some size by code inspection or by any other means. Your best option is to review the code and eliminate as many as possible.
Change your perception of UB (bugs): If you encounter a bug during your re-engineering efforts, it's a good thing! You are in the best position to remove one UB.
Don't keep the old compiler just because you are afraid of UB. Recompile the project with the latest and best compiler available. Compilers can also have bugs. Newer compilers will produce better, more robust code. Newer compilers will produce better warnings. Use all warnings possible -Wall.
Eliminate all the warnings that the compiler produces. Every single warning is there for a reason, it highlights a problem. The likelihood of a "false positive" is quite dim nowadays. This is even true for MSVC (I'm not talking about real old compilers like before VC 2005)
Use a static code checker (Cppcheck). It can point you to common problems with the code.
Use a custom rule set for your code checker. It will help you to get the code up to some standard.
If possible, compile the project with another compiler (GCC, Clang) just for the sake of getting the warnings of these compilers.
Don't link against old object files. This will create more problems than what you think it avoids
As others said: First and foremost, try to find the errors, not hide them.
The first and simplest measure is to set the warning level to /W4 (you can try Wall, but due to the large amount of noise this will produce (e.g. from standard headerfiles), it is usually only of help if you know you have an error in a certain part of your code)
Use static analyzers - you can start with the builtin Code Analysis tool and then go for external tools (which are usually much more difficult to set up correctly for a non-trivial project).
Write lots of tests and make sure, you are exercising edge cases - thats where UB usually lurks.
If possible, try to compile the project (or parts of it) under clang and activate the different sanitizers (in particular there is UndefinedBehaviorSanitizer) which will further instrument your code to check for UB (only helpfull if you have tests to exercise that UB though)
Test your code at different optimization levels and combination of flags (in VS, especially _ITERATOR_DEBUG_LEVEL can be helpfull to find out-of-bounds errors)
I'd say any non-trivial code base potentially contains undefined behavior. What is special about that particular Programmer? If he/she is prone to a special kind of UB, then you can focus your efforts on this.

Why is clang not used more? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I've done a fair amount of programming in C/C++ before, but nowadays it only accounts for a small percentage of the programming I do (scripting languages are much better suited for a lot of the work I do). I worked on some C programming projects the last few days and was surprised how many little syntactical details I kept forgetting. What's worse is that cc/gcc typically had cryptic or non-informative error messages about these issues (sorry I can't remember any specific examples).
I learned about the clang compiler not too long ago and decided to try that. The error messages were much clearer and helped me identify and fix the problems in my syntax. My question is why this tool is not used/mentioned more than it is? Is it that it is so new compared to the usual suspects (cc/gcc), or is it that it doesn't support features that they support, or is it just harder to obtain? I have a hard time believing that last one, since it was installed with the dev tools on my iMac and required a single command (sudo apt-get install clang) to install on my Ubuntu box.
My question is why this tool is not used/mentioned more than it is?
It's probably because of history, and because how we humans generally behave.
Traditionally gcc has been the only real (free) compiler that can be practically used to compile C programs on atleast all the free *nix clones out there. It's what virtually all the base system and kernel of linux, *BSD, now probably OSX, and others are compiled with.
While flaws are here and there, basically this means: gcc works. And if it isn't broken, don't fix it. Out of this, you now have a huge user base, it's easy to get help with gcc, there's a lot of people that have used gcc, that are working on gcc itself etc.
Generally, if you want to switch a huge community from something they're used to, to something else, that "something else" have to be *significantly" better. Just "better" is often not reason enough. I think you can find examples of this in many areas of society.
clang is newer, some people will just be suspicious if it's up to the task, if it has bugs, if it produces slower code etc. - it seems to be in the human nature to be suspicious - new things are scary. Many don't even know about clang, many don't care because they're happy with gcc.
Though, if you rather want to use clang, go for it - error messages are indeed "better" and easier to understand vs gcc.
The clang front end is relatively new. For example, the 2.8 release in October 2010 marks the completion of the C++ 98/03 support.
It seems likely that with increasing maturity, there will be an increasing adoption. For example, there is ongoing work on making the FreeBSD OS (and other BSD OS's) build with clang, eliminating a dependence on GCC/G++.
Apple are pushing the LLVM/clang combination. It seems likely that they will cease to support their old GCC toolchain branch (based on 4.2) and come to depend solely on clang tools for OSX/iOS development.
Clang is also seeing increasing adoption in custom compilers for C-like languages (e.g. shader language compilers for OpenCL)
LLVM has been around for a while, but — at least in my neck of the woods — it has only risen to prominence very recently, possibly due to the fact that Apple has been pushing heavily of late to replace gcc with Clang in their own tool-chain.
Also, I believe it's C++ support has only recently become production-grade. EDIT: It appears that it isn't even that yet. (See comments below.)
Another factor might be that LLVM is largely backed by a single vendor, towards which non-Apple developers have an innate mistrust.
My question is why this tool is not used/mentioned more than it is? Is it that it is so new compared to the usual suspects…
This is exactly the reason. It is still new and core functionality is still being actively developed. Remember that existing projects may be making use of compiler-specific features – or using libraries which do – and developers are, in any case, loath to change working tools for experimental ones that may have unexpected bugs or unknown performance/size/etc. tradeoffs, even when the new tools are increasingly getting better every day.
As a student programmer I find it a total godsend mainly due to it's helpful and understandable error messages. I use it mainly for programming in C, though I am beginning to branch out into C++ also using Clang.
As to why is it not mentioned more, I suspect it is since GCC has been established for so long, for most users it is THE compiler. GCC for me works fine except for it's extremely cryptic error messages which as a student does throw me off quite a bit.
Overall I do highly recommend Clang for use by both students and developers. Since it is now the official compiler for Apple and Xcode, I suspect it's use and name recognition will quickly pickup. FreeBSD seems to have also adopted it as their main compiler though I suspect that will have less impact on it's popularity than it's adoption by Apple.
Addendum: Due to the competition from Clang, the clarity of the error messages in GCC 4.8 and 4.9 has shown a significant improvement; though I still find Clang a little more lucid, the gap however has narrowed significantly.
Today, clang is replacing gcc in most places. i.e., most *NIX-like operating system and Linux distributions. Some examples oare FreeBSD,Minix and mac(a bit obvious) clang that switched clang as default compiler. Some of my friends too,when I showed them.
This IMHO, looks like some peoples had problems with it,probably in older versions. But with clang version 3.0, I don't have any of this problems. As I metioned before, I'm using it really in all my new projects. Almost my default compiler, sometimes I do make C=gcc just to seen how difference to clang error/warning. And clang win ever. With better explanations and make a great effort to optimization. It include suggestions for use extensions(some are gcc inerhid) of the compiler to a best perfomance in the code generation.
I had written a trivial function that print an error message. But I would to exit from program after printed the error message on standard output. So,I make a simple modification,put an exit(1) as last statement in the function. As the following:
void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "error: ");
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
And so the clang show
warning: function 'error' could be declared with attribute 'noreturn'
[-Wmissing-noreturn]`
(gcc doesn't produce it even not with -Wall -Wextra -Wunreachable-code -O3 flags)
I say "that seems like nice. But what is 'nonreturn' attribute? I'd never listen or read about this. I jump to google and search for clang could be declared with attribute 'noreturn' (oh,yeah,I could just written clang nonreturn attribute,but forget it) and I found this link with a good explanation of what it this attribute and the possible gain of perfomance that I could get.
So I run to add this attribute to my function prototype(of course,if it is the gcc or clang compiler; macros will do the trick-detection). Oh yeah,to me,any small gain of perfomance(of course,without making the code unreadable) it a win.
And don't ends here,some year ago,I make return in a function where the proviously is a switch as default handling defined(as in the error() function here). But even so, gcc clains about function without return-value(I'm sorry,I don't recall to exactly error/warning message) how it possible? there is no more statements after switch,if no case match,default value is executed and don't really matter the below statements,if any. But clang think different,like me,and give a warning about this declaration,helping me make better code.
And for this kind of very small thing, I'm loving the clang.
(Note: I'm sorry for my bad english. English isn't my native language speaker, but despite it I'm trying express me here)