Turn warnings into error only within supplied diff - c++

At a company I used to work at, the build system was set up to turn warnings into errors only within changed code. It worked by supplying generating a diff (typically between the branch you were trying to merge and master and then supplying that diff to some compilation tool, and the tool would produce warnings only within the supplied diff.
This was great as it allowed you to e.g. deprecate some function, and have the build system prevent people from introducing new uses of that function, and then remove old usages of that function later.
Unfortunately, I didn't look at the setup closely enough before I left the company, and don't know how to replicate it. My question: How can I replicate this setup?
Question is tagged Clang but I would also be interested in answers that use tooling from other compilers.

If I had to implement that, my first idea would be:
Get merged file.
Analyze diff to figure out which regions were changed.
Generate a new file and inject #pragma directives1 that locally enable/disable warnings around the changed regions.
Also inject #line directives to make it look like warnings/errors are coming from the original file.
Compile modified file and save compiler warnings/errors.
Delete modified file.
Present compiler diagnostics to the user.
1 E.g. https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas for GCC.

Clang supports GCC's #pragma diagnostic.
For example:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
// ... changed code here ...
#pragma GCC diagnostic pop
MSVC also has something similar:
#pragma warning(push, 3)
// ... changed code here ...
#pragma warning(pop)

Related

Why some top level competitive programmers use #pragma?

why they use this before#include<bits/stdc++.h>
mainly I've been using #include ...
Now I'm seeing these lines on a cpp program so I became curious.
#pragma optimization_level 3
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize("Ofast")//Comment optimisations for interactive problems (use endl)
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
These are indications to the compiler to change its behaviour as if you had passed the equivalent command line flags. For programming competitions, you often submit source code rather than a binary - it's then built and tested using a system you don't control (and can't set the command line on). Putting these settings in as #pragma lines lets you control settings you might not otherwise be able to do in the competition environment.

#pragma once position: before or after #include's

In existing code I saw #pragma once be used after header #includes
//Some_Header.h
#include "header1.h"
#include "header2.h"
#pragma once
//implementations
Instead of
//Some_Header.h
#pragma once
#include "header1.h"
#include "header2.h"
//implementations
I thought it always needed to be like the second example, does it matter where your #pragma once is defined or does the preprocessor pick it up anywhere in your file?
Edit
I know #pragma once is not part of the standard and include guards are but that is not my question.
#pragma once should be placed before any headers are included. Argument of #pragma directive is a subject to macro expansion. So content of included headers can alter the pragma behavior:
// whatever.hpp
...
#define once lol_no
// your_header.hpp
#include "whatever.hpp"
#pragma once // warning C4068: unknown pragma
#pragma once relates only to a file where it is placed. It matters to the compiler whether the file contains this pragma or not, and the position of it is unimportant. Therefore, the line with #pragma once can be placed anywhere in the file except for chunk of code that is excluded from compilation by the conditional preprocessor directives like #if, #ifdef and #ifndef. The excluded chunk of code is not parsed by the compiler and if it contains the preprocessor directive it has no effect.
Despite the fact that #pragma once can be placed at any line that is parsed by the compiler, I strongly recommend to follow the common practice and put #pragma once at the beginning of a header file.
Also, as #user7860670 mentioned, arguments of #pragma directive is a subject to macro expansion for MSVC compiler. But neither gcc nor clang support it:
example for msvc
example for gcc
example for clang
There isn't really a complete answer on this question covering more than the big 3 compilers, so here's my attempt at a more complete answer.
Summary
TL;DR: If you care for portability, put it before any #include or #define statements that may conflict with it (e.g. put it first in the header).
Supported by all major compilers ("the big 3" x86_64 compilers as well as intel, and embedded compilers)
Placement generally does not matter as long as it reaches the preprocessor (e.g. not blocked by an #if-branch)
Different compilers are opinionated on whether it should be first, without documenting what happens if not.
Most compilers already detect include guards and treat it as a pragma once anyway, making the benefit largely just not creating a unique guard name.
Below is a quick, summarized guide:
Compiler
Support
Documentation
Clang
Supported
GNU-compatible. Not documented, but code shows it as normal preprocessing
GCC
Supported
gcc pragmas
MSVC
Supported (1)
MSVC one pragma
Intel (ICC)
Supported (1)
Intel Compiler Reference Manual - Supported Pragmas
Intel (ICL)
Supported (1)
ICL uses MSVC front-end
Intel (ICX)
Supported
ICX is based on Clang
Texas Instruments
Supported (2)
Reference Manual 5.11.23
Texas Instruments (Clang)
Supported
This is a fork of Clang with all major features still in effect
ArmCC
Supported (3)
Compiler Docs for #pragma once
(1) - Supported, but is subject to macro expansion
(2) - Supported, but is documented to be expected at the beginning of the header.
(3) - Supported, but not recommended.
Details
GCC
From the GCC reference manual:
If #pragma once is seen when scanning a header file, that file will never be read again, no matter what. It is a less-portable alternative to using ‘#ifndef’ to guard the contents of header files against multiple inclusions.
(emphasis mine)
Scanning is done at preprocessing time, and so as long as the #pragma statement is visible to the preprocessor (not in an unreachable conditional block from #if), then it will take effect.
GCC's #pragma once is not affected by preprocessor substitution.
Live Example
Clang
Clang's reference manual doesn't actually specify #pragma once so far as I can tell, however Clang is meant to be compatible with most, if not all, GCC builtins and features.
Viewing the source code for Clang's preprocessor phase indicates what you would expect; it handles #pragma once during preprocessing (source)
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
...
// Mark the file as a once-only file now.
HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
}
Like GCC, the placement of the #pragma once does not matter if it's first, and is not affected by preprocessor substitution.
Live Example
MSVC
MSVC's documentation on #pragma once does not indicate where it belongs, just that it should be in a source (and has an example of it at the top).
As mentioned by others, when using #pragma once in MSVC, it is subject to preprocessor-expansion.
With Substitution
Live Example
Without Substitution
Live Example
Intel (CL-Based)
When using the Intel compiler on Windows, the compiler uses an MSVC Compatibility mode (ICL). Although it's not documented in the Supported Pragma, though it does appear to be supported.
The placement does not appear to matter as well so long as the preprocessor reaches it.
ICL's #pragma once is subject to the preprocessor-expansion issue that MSVC experiences.
Note: icl is not supported on compiler-explorer, so no example is available.
Intel (GNU-Based)
When using the Intel compiler on Linux or older macOS versions (ICC), the compiler uses a GNU compatibility mode.
Like above, it's not explicitly listed as a Supported Pragma, though it does appear to be supported in practice. The placement does not appear to matter as well so long as the preprocessor reaches it.
ICC's #pragma once is subject to the preprocessor-expansion issue that MSVC experiences.
With Substitution
Live Example
Without Substitution
Live Example
Intel (Clang-Based)
The newer Intel ICX NextGen compiler is based off of Clang / LLVM technology. Behaviourally, this matches what Clang does.
Unlike other Intel compilers, but like Clang, thisdoes not suffer from the preprocessor-expansion issue.
Live Example
Arm (armcc)
The armcc compiler advises against #pragma once, but does also provide an example of it existing after #define statements as an optional feature to work with inclusion guards.
Given the example, placement should likely not be an issue.
It's unclear where this will experience any preprocessor expansion.
Note: armcc is not supported on compiler-explorer, so no example is available.
Texas Instruments (TI ArmCL)
As mentioned in the reference manual, section 5.11.23:
This pragma should be used at the beginning of a header file that should only be included once. For example:
// hdr.h
#pragma once
#warn You will only see this message one time
struct foo
{
int member;
};
(Emphasis mine)
I haven't tested what happens if it's moved anywhere lower than the comment header, but the compiler only officially supports it at the beginning of the file.
I would suspect this should not matter, but cannot confirm.
It's unclear where this will experience any preprocessor expansion.
Note: tiarmcl (and other similar ti compilers) are not supported on compiler-explorer, so no example is available.
Texas Instruments (tiarmclang)
This is a fork of clang, so it behaves the same as clang does.
The #pragma once in this implementation can be effectively placed anywhere the preprocessor reaches, and does not deal with preprocessor substitution.
Note: tiarmclang is not supported on compiler-explorer, so no example is available.

Cannot disable warnings caused by the Boost Library

I am trying to eliminate the warnings in my project so I can turn on the flag that treats warnings as errors. The project uses the boost library, specifically the Concept_check.hpp and cuthill_mckee_ordering.hpp files. The warnings 4510 and 4610 are shown in the concept_check.hpp file and I have tried to disable them using #pragma warning push and pop. The warnings are caused by the boost library trying to instantiate a class using the template found in concept_check.cpp when there is no constructor written for it.
My Question is this: Is there a more sure fire way that I can disable these warnings without modifying the boost code? I am using Visual studio 2010.
Perhaps you are looking in the wrong direction. As Alan Stokes pointed out, the warning is there for a reason. I have three hints that are perhaps not the answers you expect, but may bring an acceptable solution:
Instead of silencing the warning, just fix the error. I don't know your code, but there are other people that had a similar problem which was possible to fix by just declaring a variable.
Another question is: why do you want to turn all your warnings into errors? Is it really neccessary? I agree that normal code should always compile without warnings. But these warnings are not originating from your own code. Consider a static code-checker that warns you about issues where your compiler is blind about.
If you have to use -WX, move the offending code into a static object/library/module so you will be bothered about the warning only when you need to recompile this module. You could use specific compile options for this module, to get the warnings completely out of your way.
There is another possibility, but I'm not able to check whether it really works. According the Microsoft Documentation it is possible to set the warning level of specific warnings. (there are similar options for GCC). First, switch all warnings to error:
/WX
Then, set the warning level of the two offending warnings to zero:
/W04510 /W04610
A complete commandline would look like this:
cl source.cpp /WX /W04510 /W04610
The best solution would be to combine this with hint 3 above. This way, the specific compiler options are only used for the files that cause the warnings.
Maybe these solutions work.
You can disable specific warning from a .h file (#pragma warning( disable: ... ).

With GCC, can I disable -Wframe-larger-than on a per-function basis?

Using GCC, is it possible to specify a set of functions that are exempt from -Wframe-larger-than? (For example, main.)
GCC supplies you with pragmas for this purpose:
http://gcc.gnu.org/onlinedocs/gcc-4.5.2/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
Currently it won't do exactly what you want, since it seems to do it on a file by file basis, but in the next version of gcc (4.6), it appears as though it is context aware:
http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
This is a bit old, but I came across it looking for the same answer, so I thought I'd post my solution (found by trial and error):
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-larger-than="
void func()
{ int x[2000] = {}; printf("%d",x[1]); }
#pragma GCC diagnostic pop
seems to work. For some reason, trying to use diagnostic warning did not work. It does not seem possible to change the stack size that generates the warning. Also, you need the = at the end. Maybe the next guy will find this and save themselves some time :). This is 4.6.2 (on an ARM cross compiler).
John
You can use the GCC diagnostic pragma.

C++ Disabling warnings on a specific include

I'm wondering if there's a way to disable all warnings on a specific file (for example, using a preprocessor directive).
I'm using CImg.h and I want to get rid of the warnings involving that code.
I'm compiling both with VS (the version for Windows) and gcc (the Linux one), so I would like to have a generic way...
Thanks!
You can do it using #pragma in Microsoft compiler:
http://msdn.microsoft.com/en-us/library/2c8f766e%28VS.80%29.aspx
Something like this:
#pragma warning (push, 0)
//....header file
#pragma warning (pop)
Can't help you with gcc compiler, some info here: Selectively disable GCC warnings for only part of a translation unit?
EDIT EDIT Try push, 0.
Look into #pragma warning.