Avoid gcc warning for (generated) tokens after preprocessing directive? - c++

Microsoft's MIDL compiler generates C/C++ source code files that are slightly invalid, like the code in this extract:
#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID;
#endif // CLSID_DEFINED
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#endif !_MIDL_USE_GUIDDEF_
The tokens after #endif are ignored by Visual C++, but the Holy Standard require nothing there, and so g++ errs out, and even gcc (compiling as C) yields a warning:
H:\dev\tools\better keyboard\test>gcc com_server\com_server_i.c -c
com_server\com_server_i.c:68:8: warning: extra tokens at end of #endif directive
#endif !_MIDL_USE_GUIDDEF_
^
H:\dev\tools\better keyboard\test>_
It gets tiresome and annoying to manually fix up that code each time that it's generated.
Is there some better way to avoid this apparently unnamed warning, assuming that gcc must compile the code?
I have looked at an existing question roughly about this, but to no avail.

Converting comments into an answer.
The simplest mechanism is probably to post-process the generated code:
sed -i.bak -e 's/^#endif .*/#endif/' com_server/com_server_i.c
or equivalent. Or you can preserve the material after the #endif but put a comment there:
sed -i.bak -e 's%^#endif \(.*\)%#endif // \1%' com_server/com_server_i.c
If you're using a makefile, it is pretty easy to add the post-processing as an extra operation after the invocation of the MIDL compiler.
The cross-referenced question won't readily help; the ! cannot be removed by macro definition. Actually, the presence of a macro after the #endif elicits the warning even if the macro expands to nothing.
Have you checked the Microsoft bug reports for the MIDL compiler (to see whether it is a known problem that they decline to fix)? And have you checked the options to the MIDL compiler to see if there's anything that would fix this?

Related

What kind of code is in that file *.cpp.. #define mdTyVzgFy4_0UFy9GimmM

I just downloaded an open source code from a library called aruco for QR code detection written in C++, and while I was examing the code I found some files that doesn't look like c++..
Would anyone understand what kind of code is that? It looks like that
#define mUXyv8dbk5ppT_acPhWw1 mFzTZaNOrvPJ32i9gU3Wr9J28M8DBzQ(a,:,[,+,c,+,:,^,Z,Z,/,-,r,O,[,;,9,e,;,P)
#define mmdgJNaGE2dbCM6TccQ56 mkzSZJDew824aa0gKauM6fZ2VRvPUyZ(^,Q,5,r,j,P,t,B,c,;,T,A,o,W,},u,*,e,7,/)
#define mVBw_rTkATYMOTRmsNe_B mGJoExPsp9LQpgvTNdOhH4AqaFjFPrq(+,W,4,t,i,o,d,2,e,P,1,A,:,a,E,S,v,F,Y,V)
#define mH9xkXr1In9WhMDYLLAkQ mhN2hPhnFFq5alNSwVOjtfx8xECWu2g(R,r,R,z,t,2,i,b,!,k,S,n,e,C,k,K,5,o,K,a)
#define mSye5PefiM2uFq__QqZRQ m_dk3EP_dRaChCeAYkjUT4mGB6eHLjG(s,Y,^,r,*,P,D,X,y,^,b,},k,4,a,=,i,X,!,v)
#define mJpQJFURUc57_1UwCTPvr mByXC_NAGVGzCcmUEv_c9mAYK8t5jBN(t,R,.,>,!,i,W,0,R,C,*,Y,A,>,K,h,T,-,*,8)
#define my9E4sAt6II28meWefBqO mu1aRcYPGwwmkdvLrXjWyYkshrNbQfZ(8,N,+,t,},r,I,T,=,C,*,h,!,m,{,/,D,y,_,T)
#define mRtPBvwiZzHWglctKPmaF msiqIfe8Aci2FIHOTIR3qsdKyqc9jUO(7,i,j,^,_,^,6,},I,<,E,-,/,d,j,=,:,N,+,s)
#endif
#ifndef _ARUCO_MarkerDetector_Impl_H
#define _ARUCO_MarkerDetector_Impl_H
#include "aruco_export.h"
#include "markerdetector.h"
#include <opencv2/imgproc/imgproc.hpp>
mH83V9yQZ4TlJHtn2Baef
aruco
mBduW7dqSuFrUAvwh7kHo
mTj14DRd7xgEPvsp5xhPs
CameraParameters mVlbuMLWi_vwpED0hDKIw
mrJuVHPe96ExiggCdsmDG
MarkerLabeler mv0LWHXRSvGJF76ckeLfO
mPXYuzTL9RZjjZA9XYUV9
MarkerDetector_Impl
mYwjl00gOK3Vja3UkLMIP
friend mukY8albO2VdJSsWPXwW4
MarkerDetector mD07x3flmZMPVC6kwqG6P
public:
MarkerDetector_Impl mnODdIJiXbJxgUNOnnK7Q
mYCDBBfn03HaGvoHBxAMq
MarkerDetector_Impl mK8B3zN6mQAB0xYXFlxGO
int dict_type, mYJJZNT6RsQUQcGvcjw6s
error_correction_rate mRUhvrauugCIk8ZFUtFF5
0 mswZzmsb_awITT3YY34kR
What kind of code is in that file *.cpp.. #define mdTyVzgFy4_0UFy9GimmM
#define mdTyVzgFy4_0UFy9GimmM is a pre-processor directive that defines a macro. Macros are used to replace text during pre-processing.
Would anyone understand what kind of code is that?
Probably no human can understand it. And that is probably the reason why that has been done in the first place: It seems to be an attempt to obfuscate the source code.
You can use a pre-processor to generate the processed code to see what the compiler sees. For example, gcc -E. Note that the pre-processor will expand the include directives, so you'll need to scroll past the included files first.
Would anyone understand what kind of code is that?
Yes! Wow this is fun. That is indeed an obfuscated source code.
It is still C/C++. It is using pre-processor definitions. Basically it is a key that can be used multiple times. (like a variable).
The compiler will search for all preprocessor definitions and replaces them by the actual text.
I guess you want to deobfuscate it to have a closer look in the source code.
For gcc and clang, you can use the -E option (see similar answer) to output the preprocessor output without compiling.
To also show comments like in your sample output, you can add in the -CC and -P flags:
clang++ -E -CC -P fileA.cpp
All of the processor options for -E can be found on here, on
gcc.gnu.org.
-CC Do not discard comments, including during macro expansion. This is like -C, except that comments contained within macros are also passed
through to the output file where the macro is expanded.
-P Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on
something that is not C code, and will be sent to a program which
might be confused by the linemarkers.
For the Visual C++ compiler, you can use /E.

Avoid superfluous warnings when compiling Qt code with ccache / clang

I am having the same problem as this guy.
Compiling with clang and ccache I get this warning everytime it encounters a Q_OBJECT:
warning: explicitly assigning value of variable of type 'int' to itself [-Wself-assign]
This only happens when using ccache, compiling the same code with clang alone works fine.
There seems to be a similar issue with macro expansions where the suggested solution is to set the environment variable
CCACHE_CPP2=yes
Unfortunately, this does not seems to fix my issue, or maybe I'm doing it wrong.
I have tried:
Building from command line with
CCACHE_CPP2=yes ninja
export CCACHE_CPP2=yes
ninja
Building from Qt Creator, adding CCACHE_CPP2 to "Build Environment"
Is there anything else I can do to fix this macro expansion issue? I specifically do not want to disable warnings globally (because that's bad) or locally (because that means wrapping all macros in compiler-specific boilerplate).
Try adding -Wno-self-assign to the CPP flags . It should allow you to disable self-assign errors :
CXXFLAGS= $(CXXFLAGS) -Wno-self-assign
or
CPPFLAGS=$(CPPFLAGS) -Wno-self-assign
Forgive me for not having clang to test this with, but I felt I should help anyway. Expanding on Marek's answer, there's the possibility of placing the pragma inside another macro expansion. It's a very ugly solution, but that way you only need to define the macro once, instead of spawning pragmas all over your code base.
#define WARN int&x = x;
#define NO_WARN _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \
WARN \
_Pragma("GCC diagnostic pop")
int main(){
NO_WARN
}
As you can see, I tested it with gcc(I have no means of testing with clang right now), but that should work fine in clang by substituting "GCC" with "clang" inside the macro(and using -Wself_assign). Applying to your problem(pseudocode):
#ifdef clang
#define MY_Q_OBJECT _Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wself-assign\"") \
Q_OBJECT \
_Pragma("clang diagnostic pop")
#else
#define MY_Q_OBJECT Q_OBJECT
#endif
class A{
MY_Q_OBJECT // Unfortunately you still need to replace Q_OBJECT on your classes
}
Another ugly downside is that, at least on gcc, I had to run the preprocessor twice for it to work. Can't tell if the same is necessary for clang.
IMO ignoring this warning globally is not a problem. It warns about dummy code, not about potential logic errors caused by typo. That is why I've voted up #MichaelCMS answer.
But there is a way to disable warning only is some section of code:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wself-assign"
Q_OBJECT
#pragma clang diagnostic pop
This should do the trick (if I didn't mess up the flag name), but I don't like it, to much boiler plate macros.

detecting deprecated functions in C++

In a C++ project documented with Doxygen, I have marked some functions as \deprecated in the Doxygen comments. Is there any way to use these comments (with Doxygen or another tool) in order to detect that another non-deprecated function is calling a deprecated one ? (The project is pretty big and going through all the classes would take a lot of time).
Thanks
If you are using GCC or clang to compile your code you could manually annotate functions.
__attribute__((__deprecated__))
void dep_fun() { }
Then calling dep_fun anywhere in your code will emit a diagnostic message.
If you placed doxygen's \deprecated annotation consistently you should be able to update the code automatically with tools like sed.
Building on Benjamins answer:
Some useful compiler directives:
#ifdef _MSC_VER
#define DEPRECATED __declspec(deprecated)
#elif defined(__GNUC__) | defined(__clang__)
#define DEPRECATED __attribute__((__deprecated__))
#else
#define DEPRECATED
#endif
//usage:
DEPRECATED void foo(int bar);
(warning: untested under clang and msc, only tested on GNUC.)

Is there a way to escape a C preprocessor directive?

What I am trying to do is have the C preprocessor output #ifdef, #else, and #endif directives. That is, I would like to somehow "escape" a directive so that the output of the preprocessor includes the directive were the preprocessor to run on the output.
Is it possible to "escape" a CPP directive so that it is outputted by the preprocessor such that the output of an escaped directive would be a preprocessor directive if the CPP output were to be itself preprocessed?
A slight variant of Marcelo Cantos's answer works for me on GNU cpp 4.4.3:
#define HASH(x) x
...
HASH(#)ifdef __cplusplus
class foo { };
HASH(#)endif
EDIT: The following answer only appears to work on earlier versions of cpp. It breaks somewhere between 4.2.1 and 4.3.2. gcc -E and g++ -E break even earlier. See comments for the details.
Here's one trick that seems to work:
#define HASH() #
...
HASH()ifdef __cplusplus
class foo { };
HASH()endif
You'll have to use cpp directly, since a compiler will try to immediately consume the preprocessor output and won't know what to do with the unprocessed directives.
Another trick that seems to work is:
#define EMPTY
EMPTY#ifdef
With GCC's preprocessor (version 4.5.2) I get:
#ifdef
For some reason, this technique has the same leading space issue as Ilmari Karonen's solution, but this is probably not an issue with modern standards-conforming C preprocessors.

fail compile if required flags aren't present

I have some legacy code that needs certain gcc flags passed in. Can I add pre-processor checks for these flags?
For example, let's say I need -fno-strict-aliasing, can I do something like this:
#ifndef _FNO_STRICT_ALIASING
#error -fno-strict-aliasing is required!
#endif
You can use
#pragma GCC optimize "no-strict-aliasing"
to compile the file with that flag (overriding what was specified on the command line).
You can also use
__attribute__((optimize("no-strict-aliasing")))
to apply the flag to a single function within a source file...
There is definitely no #define for it, at least on my version of GCC.
To see all predefined preprocessor symbols:
g++ -dM -E - < /dev/null
I do not think there is any way to test these options. However, if you are using GCC 4.4 or later, you can use the "optimize" function attribute or the "optimize" #pragma to enable specific options on a per-function or per-file basis.
For example, if you add this to a common header file:
#if defined(__GNUC__)
#pragma GCC optimize ("no-strict-aliasing")
#else
#error "You are not using GCC"
#endif
...it should enable the option for every file that includes the header.
[update]
OK so it took me about 10 minutes too long to compose this answer. I am going to leave it here anyway for the links to the GCC docs.