How to prevent macro redefinition - c++

After working some time on my project, this warning begins to appear:
2>Game.cpp
2>c:\program files\microsoft sdks\windows\v6.0a\include\windef.h(126) : warning C4005: 'APIENTRY' : redefinición de macro
2> c:\users\ferran\directo\gameprojects\dev-libs\glfw\include\glfw.h(72) : vea la definición anterior de 'APIENTRY'
2>c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(23) : warning C4005: 'WINGDIAPI' : redefinición de macro
2> c:\users\ferran\directo\gameprojects\dev-libs\glfw\include\glfw.h(88) : vea la definición anterior de 'WINGDIAPI'
I'm sure that it's a matter of the order of the include files to solve, because none of these files are mine. My question is if there is a generic way to prevent this or to find which files must to be reordered to avoid this message.

The error message itself is telling you the incorrect order. It says that windef.h and wingdi.h are redefining symbols that were defined in glfw.h.
Put glfw.h after the Windows include files.

Microsoft doesn't generally design headers to be free-standing. Most of the Windows-oriented headers require that you have first included <windows.h>. Except for the dependency on that Mother Of All Headers, usually there are no specific header dependencies so by including <windows.h> first you shouldn't have any problem.

The problem is in the file Game.cpp. Try to include windows.h before glfw.h. There is a guard in glfw.h which will prevent that warning:
#ifndef APIENTRY
#ifdef _WIN32
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#define GL_APIENTRY_DEFINED
#endif // APIENTRY

Unfortunately or fortunately, no. There is no such tool that automates it. You have to go read the code in those header files, figure out what is going on and take appropriate actions.
The most you can do is
Check if macro is defined using ifdef or if defined(...) or if !defined(...) preprocessor constructs.
Undefine macro using undef.
Only ANSI C considers macro redefinition an error.

This may be caused by Visual Studio pre-compiling headers for you. Be sure that all standard and microsoft headers are included before yours. Don't include microsoft headers in any of your .h files (it looks like you have windef.h and wingdi.h inlcuded in your glfw.h). Be sure that all your headers are side-effect free. The problem should then go away. Figuring out exactly what is causing it is generally very hard.

Related

Macro redefinitions with header units

I'm experimenting with header units. Currently, I'm testing in Visual Studio 2022(Version 17.2.3).
I'm currently importing multiple header units, for example
import <windows.h>;
import <thread>;
warning warning C4005: '__analysis_assume': macro redefinition 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared\specstrings_strict.h(933): message : see previous definition of '__analysis_assume'
It kind of make senses because if <thread> and <windows.h> have any shared headers normally the inclusion guards or pragma once would prevent them from being included and being multiply defined.
I'm not really sure how header units can work if they shared header files with macros which a majority of header files of external libraries use.
I'm sure I can ignore the warning but I'm curious if anyone else has a better solution.
It seems this is a known issue with import causing multiple macro redefinitions when using windows.h.
https://developercommunity.visualstudio.com/t/warning-C4005:-Outptr:-macro-redefinit/1546919
We will have to wait for Microsoft to address this issue.

CS2061 syntax error in commoncontrols.h

I have begun writing a little C++ recently, and I decided to write a Qt program as an introduction, since I already know many of the function names etc. I have a file that gets the Jumbo icons using some win32 api. To use this I have the following includes:
#include <commoncontrols.h>
#include <shellapi.h>
#include <CommCtrl.h>
//other include statements for Qt
I keep getting an error
C:\Program Files (x86)\Windows Kits\8.1\Include\um\commoncontrols.h:198: error: C2061: syntax error : identifier 'IMAGELISTDRAWPARAMS'
and
C:\Program Files (x86)\Windows Kits\8.1\Include\um\commoncontrols.h:212: error: C2061: syntax error : identifier 'IMAGEINFO'
How could the error be in commoncontrols.h? As I understand it, the compiler cannot find a reference to those structs since CommCtrl is included after commoncontrols. So I reversed their include positions, thinking that would solve the problem, but that caused 127 other errors, so it seems not the correct direction. I am using Qt creator with Qt 5.4.1 and I am on Windows 8.1, so I am using the windows SDK for that. The kit is x64, since I am using the MSVC x64 compiler in VS 2013.
What am I doing wrong and why is it wrong?
You have a circular dependency problem. You didn't provide much information about the other header files.Example;
Header A.h might depend on header B.h and header B.h depend on header A.h.
You mostly solve this problem by replacing #include "A.h" in header B.h with a forward declaration of header A.h like so; class A in header B.h or vice versa.

unwanted header file WinGDI.h

I am doing some macros like
#define report_msg(type,msg_str).......my_special_##type(......)
#define report_error(msg_str) report_msg(ERROR,msg_str)
It works perfect under linux while when I compile with visual studio 2010 express, I see it gives error that
error C3861: 'my_special_0': identifier not found
The reason is that "ERROR" is interpreted as 0. And when I use "Go to defination" in MSVC, it goes to WinGDI.h
/* Region Flags */
#define ERROR 0
Question is why this WinGDI.h is included? How can I eliminated it without touching the code?
Solution 1:
Swap include orders of some headers -> tedious task
Solution 2:
Put NOGDI in preprocessor. In Visual Studio: Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions -> add NOGDI.
Explanation:
Paul pointed me in the right direction. I don't use precompiled headers, so I don't include stdafx.h. My problem is related to Linux vs. Windows libraries.
In my case I use a library, which defines the constant 'ERROR' for log messages. For timestamps ctime.h is included, which uses Windows.h/WinGDI.h.
This is why macros are evil. I've seen cases where TRUE and FALSE are defined with different values in different headers. In any project of decent size it may become tedious to follow the chains of headers. Try
#undef ERROR
#define report_msg(type,msg_str).......my_special_##type(......)
#define report_error(msg_str) report_msg(ERROR,msg_str)
and hope that the "real" definition of ERROR is not needed after these statements.
WinGDI.h is probably included via Windows.h from your stdafx.h. To be sure where it is included from enable "Show includes" option here: Project settings->Configuration Properties->C/C++->Advanced->Show Includes->Yes and recompile your source.

How can I identify the header that generates a warning?

I'm sure that many of you are familiar with this set of warnings. These are most of the time generated by a include file. Solution is pragma push/disable/pop, but identifying the header is not a nice task.
Does anyone knows a way of identifying the header except trial-and-error ?
1>File1.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(49) : warning C4995: 'gets': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(53) : warning C4995: 'sprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(56) : warning C4995: 'vsprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(22) : warning C4995: 'strcat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(23) : warning C4995: 'strcpy': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(36) : warning C4995: 'swprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(37) : warning C4995: 'vswprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(39) : warning C4995: 'wcscat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(41) : warning C4995: 'wcscpy': name was marked as #pragma deprecated
1>Linking...
In my case, moving #include <strsafe.h> to the bottom of the list got rid of the warning without using extra compiler directives.
A good way to find out where #pragma deprecated was being called was to go into the compiler settings under "Preprocessor" and to set Generate Preprocessed File to something like With Line Numbers (/P). Rebuild, then open up the *.i file and search for deprecated. Nearby will be the name of the offending include.
I'm using VS2003, so the dialogs may be slightly different for you.
The standard include files should have include guards. So you may be able to explicitly include those files at the top of your own file, with that warning disabled:
#pragma warning(push)
#pragma warning(disable: 4995)
#include <cstdio>
#include <cstring>
#include <cwchar>
#pragma warning(pop)
// rest of your #includes
That way the warnings will be disabled for the headers where you know there are problems. This needs to be at the top of your code so the headers are included for the first time inside the warning-disabled section.
I would like to second what #Celdecea said.
Clearly it would be nice if MS did what GCC does and specified the included path (stack?) for the file, which I presume is what you were looking for; unfortunately, I was unable to find a compiler directive to do that, so grepping through the .i file was a painful but effective replacement.
I too found that my problem stemmed from adding #includes after <strsafe.h>. Since my error list was (almost?) identical to yours I wouldn't be surprised if that also solves your problem.
If not, or if you wish to employ the pragma push/disable/pop style, then it seems that #Greg has the best solution in preemptively and explicitly defining those headers that are causing you pain.
The notes for #include strsafe.h include the line:
To use the Strsafe functions inline, include the header file as shown here, following the #include statements for all other header files.
In the MSDN offline help it says:
Important: The include line for strsafe.h should follow all other headers' include lines.
Make sure that you've only included in cpp files and after all other c++ library header files and the warnings goes away.
Kevin
To add to Greg Hewgill's post, I found the problem in set and I did not suspect this file.
#pragma warning(push)
#pragma warning(disable: 4995)
#include <set>
#pragma warning(pop)
Doing the above solved my problem.
In Visual Studio 2010 (and probably other versions too) set the C++/advanced 'show includes' option to Yes or add the /showIncludes command line option.
Then compile one file at a time and search the build output window for the warning number that you're looking for and it will show the tree of include files that is generating that warning.
This technique is useful for most build problems caused by include files.
EDIT: make sure you turn off /showIncludes when the problem is fixed as it can interfere with other compiler options (e.g. /MP (Build with Multiple Processes) is disabled).
To suppress the warning add the offending include files to a 4995 suppression block as suggested by Greg Hewgill above. This can either be at the top of the source file or in a precompiled header or in a 'forced' include file included across the project (C++/Advanced/Forced Include File).
The particular problem with 4995 CRT deprecation errors is that they seem to be generated every time code calls deprecated functions even if warning 4995 was suppressed when the deprecated functions were declared.
In my case for VS2008 these warnings were coming from #include <vector> (or some other std library.) It seems like Microsoft can't follow their own advice.
Doing the following fixed the issue:
#pragma warning(push)
#pragma warning(disable: 4995)
#include <vector>
#pragma warning(pop)
Just make sure that you do it as early as possible in your includes.

How to not #include <windows.h>

Using MSVC2008, 32bit on 64bit system.
I was once advised to never include windows.h as 'its a real monster and will slow down my compile times significantly'.
I tried leaving it out and obviously get compile errors. I included windef.h to define all the DWORDs etc, but I quickly come unstuck knowing what else to define to get the code to compile.
I now get:
2>c:\program files\microsoft sdks\windows\v7.0\include\winnt.h(6361) : error C2146: syntax error : missing ';' before identifier 'ContextRecord'
2>c:\program files\microsoft sdks\windows\v7.0\include\winnt.h(12983) : error C2065: 'PCONTEXT' : undeclared identifier
Can anyone suggest the right approach here?
Thanks
Simon
Use precompiled headers to improve compile times, and include windows.h.
Internally, windows.h respects many defines, like NOMINMAX or WIN32_LEAN_AND_MEAN.
It reduces the times significantly.
The correct answer would be "include it in the PCH". Pre-compiled headers reduce compilation time dramatically, and, contrary to popular belief, this is true also for Full Rebuilds.
If you have more than one CPP file in your project, the "Rebuild all" would build it once for the whole project, which merely ads a few seconds to compile time - to have windows.h included in all of them.
Research the APIs and make sure the headers are included in the correct order. It's not hard to not use Windows.h; but you'll learn about the MS headers in the process.
There are a few headers you have to be aware of:
WTypes.h
WinDef.h
WinBase.h
WinObject.h