Using [[deprecated]] attribute when warnings are errors (-Werror) - c++

I'm migrating to C++14 and keen to adopt its [[deprecated]] functionality, e.g.
#include <string>
#include <iostream>
[[deprecated]]
int f() { return 42; }
int main()
{
std::cout << f() << std::endl;
}
compiled with
g++ example.cpp -std=c++14 -Werror
and the problem is the deprecated warning is promoted (demoted?) to an error and the build fails.
Obviously using a #pragma to silence the warning completely defeats the point. Is there any way to tell g++ to emit warnings yet exclude specific ones from being treated as errors?

You need to add
-Wno-error=deprecated-declarations
to tell gcc to keep deprecated-declarations as a warning instead of making it an error.
You can add additional
-Wno-error=name_of_warning
if you have additional warnings that you would like to not be treated as errors as well.

With GCC (And also Clang) you can disable errors for specific warnings.
Using -Wno-error= followed by the name of the warning (displayed together with the warning or error) will disable the error for that specific item.
For your case with [[deprecated]], use the option -Wno-error=deprecated-declaration, and those will become warnings again instead of errors.

Related

Is there a way to tell Visual Studio to treat a warning as a warning, not an error?

In Visual Studio, warning C4996 (using a deprecated function) is treated as an error, and code that uses deprecated functions doesn't compile at all.
There are various ways to disable C4996 entirely, either suppressing it for a single line, for a translation unit, or for an entire project. But what if I want it to still raise a warning, but allow compilation while not treating it as an error?
#include <iostream>
[[deprecated]]
void deprecated_function()
{
std::cout << "I function, but have been deprecated.\n";
}
int main() {
deprecated_function();
}
This doesn't compile at all.
#include <iostream>
[[deprecated]]
void deprecated_function()
{
std::cout << "I function, but have been deprecated.\n";
}
int main() {
#pragma warning(suppress: 4996)
deprecated_function();
}
This compiles, but doesn't issue a warning at all.
Is it possible to tell Visual Studio to emit a warning, but still allow compilation, for a deprecated function? I'm thinking of refactoring purposes, where I'd like to mark a function as deprecated, identify all the places it's used, but the code still compiles at each intermediate stage where some but not all uses of the deprecated function have been replaced.
I'm compiling using Visual Studio 2019 Community 16.8.4, warning level set to /W3, "Treat Warnings as Errors" set to "No". This particular warning seems to be treated as an error if it gets emitted at all.
Found a working solution. It turns out the relevant flag is actually "SDL checks", not "Treat Warnings as Errors". Flipping it from /sdl to /sdl- causes compilation to emit a warning while still compiling.
EDIT: If I want to keep all the SDL checks on except treating Warning C4996 as an error, I can use the flag /sdl in combination with the flag /w34996, which specifies that 4996 is treated as a level 3 warning instead of an error.

How to enable -fpermissive for a section of code

I have a C single-header library that I would like to use in my C++ project. Normally, I would just include the file and that would be fine because C++ is almost a superset of C. However, this library has a goto that jumps over an initialization, violating the C++ standard.
I can get around this be enabling the -fpermissive compiler flag on GCC, but I want the errors to trigger properly for the rest of my code.
Is there a way I can enable it just for this one header file (perhaps similar to #pragma GCC diagnostic XXX).
There's #pragma GCC optimize "blah" or the function attribute __attribute__((optimize("blah"))) that act like the argument -fblah was given for the rest of that file/that specific function, but it doesn't seem to work with -fpermissive:
$ cat foo.cpp
#pragma GCC optimize "permissive"
void foo(int x) {
}
$ g++-8 -c -Wall -Wextra foo.cpp
foo.cpp:1:22: warning: bad option ‘-fpermissive’ to pragma ‘optimize’ [-Wpragmas]
#pragma GCC optimize "permissive"
^~~~~~~~~~~~
foo.cpp:3:16: warning: bad option ‘-fpermissive’ to attribute ‘optimize’ [-Wattributes]
void foo(int x) {
One option would be to put the function that needs this in a file by itself, and configure your build system to compile just that file with -fpermissive, though that breaks the header-only model. Or fix the code so it doesn't need that option at all.
Per gcc man page:
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive allows some nonconforming code to compile.
So in theory, one can allow a section to compile as permissive using a sequence of gcc warning pragmas:
// Start permissive code
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wuninitialized"
// .. Other #pragmas
// Permissive Code here.
// Restore normal processing.
#pragma GCC diagnostic pop
One challenge is that there is no published list of errors that will be ignored with -fpermissive (At least I could not find it). One possible approach will be to compile the code, and enter the '#pragma's one at at a time, until the code compiles cleanly.
If one can identify all (or most) of the rules, possible to put them into #include file.
#pragma GCC diagostic push
#include "permissive.h"
// Permissive Code here
#pragma GCC diagostic pop

C++11 exit() and abs() without including <cstdlib>?

Please tell me why this code is compiled with C++11 standard:
#include <iostream>
using namespace std;
int main()
{
abs(-12);
exit(1);
return 0;
}
it is without error g++ -std=++11 main.cpp
this error g++ main.cpp
if you remove #include <iostream> then get the error on exit() and abs() when the program is compiled.
Tell me why this happens, if I don't include <cstdlib>? And how to do that would compile with -std=c++11 was a warning or error?
The answer is really simple: the code compiles because under C++11 your iostream lib includes other libraries that have exit() and abs() defined. You won't get a warning or error for that. Why would you? After all cascade includes are supported.
However you should not depend on that since that's not a part of the standard and may break under different compiler. But I guess that as long as you stick to one compiler and one -std flag you're fine. Also fixing this by adding some includes should not be a big deal as well.

clang produces warning regarding c++11 despite update

updated clang recently (as well as xcode and developer tools) and ran a simple program to see if it was supporting c++11. Look like this:
#include <iostream>
using namespace std;
int main()
{
string my_array[5] = {"one", "two", "three"};
for (string &x : my_array)
cout << x << endl;
}
compile in terminal like this:
clang++ -std=c++11 -stdlib=libc++ -Weverything main.cpp
and get this warning:
main.cpp:17:20: warning: range-based for loop is incompatible with C++98
[-Wc++98-compat]
for (string &x : my_array)
but it still produces an executable and runs as expected. Why is this error being produced?
This is a warning rather than an error. The warning message also indicates the warning flag that enables it: -Wc++98-compat. This flag is enabled because you've enabled -Weverything (a good idea, IMO). To disable a specific warning you pass a warning flag with 'no-' prefixed to the warning name you want to disable:
-Wno-c++98-compat
The purpose of this warning is to allow building code as C++11 and to gain some C++11 benefits, such as performance improvements from move semantics, while still producing code compatible with older compilers. That is, this warning doesn't indicate any kind of problem with the program and the program will work just as the C++11 spec indicates (other than clang bugs, of course), but the warning is to inform you that if you were to compile as C++98 then it would not work.
If you don't plan to build the code as C++98 then this warning doesn't have any value to you and you should simply disable it.
I believe there's also a -Wc++11-compat flag in the latest versions now that clang supports (what will probably be called) C++14.

(Di|Tri)graphs in C++11

After reading up on digraphs and trigraphs I went on and tested a simple program:
#include <stdio.h>
int main()
{
int a = 0;
//??/
++a;
printf("%d",a);
return 0;
}
and by reflex I did
g++ -std=c++11 test.c
and to my surprise no warnings were emitted and 0 was printed so I went on and tried compiling with the C compiler and it did emit a warning due to the trigraph.
My question is why does -std=c++11 automatically pull in -trigraphs and emit no warning by default ? (without using -Wall) Do implementations of certain C++11 features require them? (highly doubt it but worth asking)
Passing -std=c99 has the same effect of enabling the trigraph and disabling the warning.
It must enable the trigraph to be strictly standard-compliant. Disabling the warning is surprising, but note that the warning is about a trigraph being ignored. The warning probably goes away because -std failed to activate separate warnings (-Wtrigraphs) about a trigraph being used.
And that should probably be considered a bug.