Is this macro legal C ++ or something else? And if it's legal, how does it work

WebKit has many pre-processor lines: #if MACRO1(MACRO2)

For instance:

 #if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT)) #include "MediaPlayerPrivateQTKit.h" #if USE(AVFOUNDATION) #include "MediaPlayerPrivateAVFoundationObjC.h" #endif ... 

So, my first thought was that they were functional macros, but I did not see how this would work, and I could not find any #defines for these macros anywhere in the source code.

I asked another engineer what it was, and he never saw multiple macros used the same way as inside #if. I found this wiki page that talks about them, but it’s still not clear to me where they came from,

So my question is: is it really C ++ or is it being replaced by code in another tool / language like CMake or something else, and if it is valid, C ++ has a specification that everyone knows about it?

I am a support engineer for a C ++ static analysis tool that does not handle this syntax. The client asked us to handle this, but if I am going to take it from a senior engineer, I would like not to seem like an idiot :) Therefore, I would like someone to know this.

+6
source share
3 answers

As mentioned in the wiki, in root / trunk / Source / JavaScriptCore / wtf / Platform.h we get a definition for each of these defines. For example, the PLATFORM macro is defined as:

 #define PLATFORM(WTF_FEATURE) \ (defined WTF_PLATFORM_##WTF_FEATURE \ && WTF_PLATFORM_##WTF_FEATURE) 

The value of WTF_FEATURE will be replaced by the platform name to create a macro called WTF_PLATFORM_WTF_FEATRE . For example, if WTF_FEATURE passed to the macro as a MAC , you will get the extension WTF_PLATFORM_MAC . The defined preprocessor directive, combined with a logical AND , basically asks if this macro value is defined and if it is defined if its value is a "true" value. You should use this macro somewhere else in the preprocess, for example:

 #ifdef __APPLE__ #define WTF_PLATFORM_MAC 1 #end if #define PLATFORM(WTF_FEATURE) \ (defined WTF_PLATFORM_##WTF_FEATURE \ && WTF_PLATFORM_##WTF_FEATURE) #if PLATFORM(MAC) //...some code #end if 

You would not use it in C ++ code, for example

 if (PLATFORM(MAC)) { //...some code } 

which will cause a bunch of errors from the compiler, since defined not a C ++ keyword, and evaluating and replacing a macro in C ++ code will ultimately reset the pre-processor defined directive to any C ++ code that is directly called a macro. This is invalid C ++.

Thanks to Johannes for pointing out some of these issues.

+5
source

The #if directive works roughly, replacing all macros, and then replacing all identifiers and keywords with what remains of 0 , and then processes what remains, has a constant expression in accordance with the rules of the C ++ language (a subset of those rules which apply to what remains of this replacement - quite a bit :)).

So PLATFORM(MAC) can give 1 if MAC is defined as 1 , and MAC if it is not defined, if PLATFORM simply defined as

 #define PLATFORM(X) X 

The resulting MAC is an identifier and will later be replaced with 0 . Most likely, they combine X with something like PLATFORM to support multiple requests using MAC as an argument, checking for the existence of different macros. As a developer of the C ++ Static Analysis tool, you probably have access to the C ++ specification. Take a look at section 16.1 .

+3
source

Definitions may come from build scripts. Most C ++ compilers allow you to define macros on the command line.

One way to define a USE macro, as in your example, would be:

 #define USE_QTKIT 1 #define USE(x) USE_ ## x 

Or maybe like:

 gcc -DUSE_QTKIT=1 '-DUSE(x)=USE_ ## x' 
0
source

Source: https://habr.com/ru/post/893911/


All Articles