How to suppress warnings in external headers in Visual C++ - visual-c++

I'm starting a new BREW project, and I'd like to compile with Warning Level 4 (/W4) to keep the application code nice and clean. The problem is that the BREW headers themselves don't compile cleanly with /W4.
In gcc you can differentiate between application and system headers by using -I and -isystem, and then by default gcc doesn't report any compilation warnings in system headers. Is there an equivalent mechanism in Visual C++?

Use this method around (a) header(s) that you cannot or don't want to change, but which you need to include.
You can selectively, and temporarily disable all warnings like this:
#pragma warning(push, 0)
// Some include(s) with unfixable warnings
#pragma warning(pop)
Instead of 0 you can optionally pass in the warning number to disable, so something like:
#pragma warning(push)
#pragma warning(disable : 4081)
#pragma warning(disable : 4706)
// Some code
#pragma warning(pop)

Visual C++ team has just added support for warning levels in external headers. You can find the details in their blog post: Broken Warnings Theory.
In essence it does automatically what the suggestions here were recommending to do manually: pushes new warning level right before #include directive and pops it up right after. There are additional flags to specify locations of external headers, flag to treat all <> includes as external, #pragma system_header and a feature not available in Clang or GCC (as of this writing) to see warnings in external headers across template instantiation stack when the template was instantiated in the user code.
Besides the comments under that post, you can also find some useful discussion in a reddit announcement for that post.

I don't believe Visual C++ lets you differentiate. You can fake it by using #pragma warning around the include:
#pragma warning(push, 0)
#include "mywarningheader.h"
#pragma warning(pop)

It seems like there is an answer to this.
this post talks about /external:I that can be used to include headers with a special set of warnings.
I have not tested it myself, but the blog post is from 2017.

The /external:anglebrackets /external:W0 compiler flags disable warnings on the headers imported with #include <...>.
You can change the W0 to W1, W2, W3, or W4, to set a different warning level for those.

Related

Building R Package that uses RcppArmadillo, RcppEigen and depends on Cpp11 Plugins

I followed all the procedures explained so far about this matter either in this website or published notes by Dirk, Hadley or others. However, I still have problems in building my package due to the issue regarding cpp11 plugin.
I used RcppArmadillo.package.skeleton() function. I put my cpp file in the src directory. The NAMESPACE file looks as it should which contains importFrom(Rcpp, sourceCpp) line. I also edited DESCRIPTION file and in the LinkingTo section, I added RcppEigen and other packages I use. I finally ran the compileAttributes(verbose=TRUE) function in R and everything looked OK. Therefore, I think I have done everything as I should. I have to also mention that when I compile my code in R using sourceCpp(), it works perfect and is compiled with no errors!
To illustrate better what my dependencies are, I put the first block of my code here:
#include <RcppArmadillo.h>
#include <RcppNumerical.h>
#include <RcppArmadilloExtensions/sample.h>
#include <Eigen/LU>
#include <algorithm>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::depends(RcppNumerical)]]
// [[Rcpp::plugins(cpp11)]]
The problem is when I build my package and I get errors and warnings for the lines I have auto type which relates to cpp11 plugin.
After searching similar posts on this website, I concluded that I have to force my R compiler to use c++11 and there fore I edited my Makvars file located at ~/.R/Makevars and since I use MAC I added this line:
CXX=clang++ -std=c++11 to that file. However, when I do that those 3 errors go away but 50 new errors are generated as all of the Armadillo variable types, such as mat, uvec, etc are not recognized any more. So I don't know how to fix this.
I think basically putting // [[Rcpp::plugins(cpp11)]] should take care of it as the new version of Rcpp supports this plug in and probably that's why when I run sourceCpp in R I get no errors and everything looks fine. But I don't know what happens when building my package. My Rcpp version is 0.12.8 .
Thank you in advance for any sorts of help.
Plugins for both dependencies (ie other headers) and compiler options are for use by sourceCpp().
Packages do this with LinkingTo: and, for the C++11 directive, either src/Makevars or SystemRequirements. See Writing R Extensions which documents this.

To know precompiled header is used

I have a.cpp that is used in several projects. Some of them are using precompiled headers, others - not. Depending on this I must add or remove line :
#include <stdafx.h>
Is it possible somehow play with #define to make this in automatic way?
UPD.
I can't use empty stdafx.h file in case when precompiled headers are not used because I got strange behaviour in my situation when a.cpp is placed in project sub directory libA. In this case projects that use precompiled header must have line:
#include <stdafx.h>
and projects that are not using PCH must have line:
#include "..\stdafx.h"
Wice versa is not working. Actually I still can't understand this behavior. I would like to have a.cpp file identical for all projects.
You can include a preprocessor define in the project settings for those projects which use precompiled headers, and then base the inclusion of stdafx.h based on its existence. Using your example, libA's C++ settings should include /D USE_PCH, and then in a.cpp:
#ifdef USE_PCH
#include <stdafx.h>
#else
#include "../stdafx.h"
#endif
To ensure that the define and precompiled header settings remain in sync, you could create a property sheet with both settings, and link it to your project. However, if it were me, I would just disable precompiled headers for the files which are shared between libraries. Unless the PCH is very large, and the number of shared sources also very large, the compilation time savings likely won't outweigh the maintenance of this approach.

enumeration values not handled in switch

When compiling my project as a 64bit target (this isn't considered a warning on 32bit target) I get this warning:
5 enumeration values not handled in switch: 'kCreated', 'kLoaded', 'kConnected'...
I have somehow managed to turn off the error/warning message numbers, so I don't know what number to suppress in my code with #pragma warn.
I need to use #pragma warn because I only want to suppress approved places in my code (turning the warning off and on again).
Bonus question: Does anyone know how to get back the error/warning numbers again?
The 64bit compiler is based on CLang, which does not use warning numbers, which is why you do not see them. The following info comes from Bruneau Babet, one of C++Builder's chief developers, in the Embarcadero forums:
How do I suppress 64bit XE3 warnings?
Warnings in clang, hence bcc64, don't have the Wxxxx numbers. Behind the
scene there is a unique id generated for each warning but it's
auto-generated and cannot be assumed to remain constant across builds.
Instead each warning has a group. Related warnings are often in the same
group. Some groups have just one warning. To disable warnings of a group
you can use "-Wno-" on the command line, or via something like
the following in code:
#pragma clang diagnostic ignored "-W<groupname>".
For example, the first warning you listed is under the group "float-equal".
So, "-Wno-float-equal" should disable that warning. And to disable the one
about an enumerator not handled in the switch you can use the following in
code:
#pragma clang diagnostic ignored "-Wswitch"
So the next obvious question is how to find out about each group. The
"-fdiagnostics-show-option" should trigger the compiler to display the
option but unfortunately the IDE does not honor that option. So you must
either use the command line to find out about the group ach warning belongs
to, or you can peek at the Warning declarations here:
https://github.com/llvm/llvm-project/tree/main/clang/include/clang/Basic
The *.td files declare the various warnings. The ones mentioned above are
https://github.com/llvm/llvm-project/tree/main/clang/include/clang/Basic/DiagnosticSemaKinds.td
Oddly, #pragma clang is still not documented on the Embarcadero DocWiki.

Is there a way to detect whether #pragma unmanaged is in effect in C++/CLI?

I have a project that includes some performance sensitive native C++ headers making heavy use of templates. For this project we also wrap the headers and add some glue code to expose the functionality to c# and other .NET languages. We'll call this header "layout.h", and we'll assume it's a third party header that I can't change.
In a mixed mode C++/CLI assembly it is relatively easy to make a mistake and #include from a place in the code where #pragma unmanaged (or #pramga managed(push,off) ) . When that happens the templates generate IL, and I get extra managed/unmanaged transitions when running the code and performance goes down the drain.
My question is whether there is a way I can do a compile-time check just before the #include so that compilation fails if I am accidently #including from the wrong context.
// File1.cpp, compiled in a mixed mode C++/CLI assembly with /clr
ASSERT_UNMANAGED()
#include <layout.h>
My naive 1st attempt checked #ifdef _MANAGED, but that is always defined whether I'm in a #pragma unmanaged block of code or not.
The pragma directives must be inserted directly in the include file. In this way, everywhere you include the file an unmanaged section is declared.
Sorry that you have to modify your include file.
You may write ASSERT_MANAGED or ASSERT_UNMANAGED code that would use construct that is available ONLY while compiling managed or unmanaged. A ref class declaration is an example which is avaiable only when using managed.
This is somewhat a dirty solution, but it would work.
Here's a possible solution, making use of the fact that intrinsics are always compiled as native (unmanaged) code:
#include <intrin.h>
#define ASSERT_UNMANAGED() \
int TestFunc(void) { \
__pragma(warning(push)) \
__pragma(warning(error:4793)) \
auto aumt = [] () { return _bextr_u64(65537, 0, 8); }; \
__pragma(warning(pop)) \
return int(aumt()); }
#pragma unmanaged // Comment out this line and the assertion fails!
ASSERT_UNMANAGED()
#pragma managed
EDIT: Of course, if you just want warnings rather than compilation failure, you can remove the 3 __pragma(warning()) lines.

Which is efficient to use #pragma once or #ifndef #endif?

To avoid multiple includes of a header file, one of my friend suggested the following way
#ifndef _INTERFACEMESSAGE_HPP
#define _INTERFACEMESSAGE_HPP
class CInterfaceMessage
{
/ /Declaration of class goes here
//i.e declaration of member variables and methods
private:
int m_nCount;
CString m_cStrMessage;
public:
CString foo(int);
}
#endif
where _INTERFACEMESSAGE_HPP is just an identifier
but when i declare a class using visual studio 2005 IDE I get a statement as
#pragma once
at the starting of the class definition
when i took the help of msdn to find the purpose of #pragma once
it gave me the following explanation
"Specifies that the file will be included (opened) only once by the compiler when compiling a source code file. "
Someone please tell which is the right approach?, if both are correct then what is the difference? is one approach is better than the other?
gcc has pragma once as deprecated. You should use the standard include guards. All pragma directives are by definition implementation defined. So, if you want portability, don't use them.
Pragmas are compiler-specific, so I'd use #ifndef.
Preprocessor directives are resolved during (actually, before) compilation, so they do not make a difference in runtime except maybe for compile time.
However, you will never notice a difference in compile time from these two alternatives unless you use them several thousand times I guess.
The first approach is the generic approach that works with all compilers and is also the older one around. The #pragma once approach is compiler specific.

Resources