Является ли этот макрос допустимым C ++ или чем-то еще? И если это законно, как это работает - PullRequest
6 голосов
/ 30 июля 2011

WebKit имеет много строк препроцессора, как это: #if MACRO1(MACRO2)

Например:

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

Итак, моей первой мыслью было то, что они были функциональными макросами, но я не вижу, как это будет работать, и я не смог найти #defines для этих макросов нигде в исходном коде.

Я спросил другого инженера, что это такое, и он никогда не видел, чтобы несколько макросов использовались так же внутри #if. Я нашел эту вики-страницу , в которой говорится о них, но мне все еще не было ясно, откуда они взялись,

Итак, мой вопрос: действительно ли это C ++ или он заменяется в коде другим инструментом / языком, таким как CMake или что-то еще, и если это действительно C ++, есть ли какая-нибудь спецификация, которая знает об этом?

Я инженер поддержки для инструмента статического анализа C ++, который не обрабатывает этот синтаксис. Заказчик попросил нас разобраться с этим, но если я собираюсь передать это старшему инженеру, я бы не хотел звучать как идиот :) Так что я бы хотел, чтобы кто-нибудь знал, что это не так.

Ответы [ 3 ]

5 голосов
/ 30 июля 2011

Как упоминалось в вики, в root / trunk / Source / JavaScriptCore / wtf / Platform.h мы получаем определение для каждого из этих определений. Например, макрос PLATFORM определяется как:

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

Значение WTF_FEATURE будет заменено именем платформы для создания макроса с именем WTF_PLATFORM_WTF_FEATRE. Например, если WTF_FEATURE передано в макрос как MAC, вы получите расширение WTF_PLATFORM_MAC. Директива препроцессора defined в сочетании с логической AND в основном спрашивает, определено ли это значение макроса и определено ли его значение как «истинное» значение. Вы бы использовали этот макрос где-то еще в препроцессоре, например:

#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

Вы бы не использовали его в самом коде C ++, как

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

, что может вызвать кучу ошибок у компилятора, так как defined не является ключевым словом C ++, а вычисление и замена макроса в коде C ++ приведет к сбросу директивы препроцессора defined в любой код C ++ это напрямую называется макросом. Это не правильно C ++.

Спасибо, Йоханнес, за указание на некоторые из этих вопросов.

3 голосов
/ 30 июля 2011

Директива #if примерно работает, заменяя все макросы, а затем заменяя все идентификаторы и ключевые слова того, что осталось, на 0, а затем обрабатывая то, что осталось, имеет постоянное выражение в соответствии с правилами языка C ++ (подмножествоэти правила применимы к тому, что осталось от этой замены - совсем немного :)).

Таким образом, PLATFORM(MAC) может дать 1, если MAC определено как 1, и MAC, если оно не определено, если PLATFORM просто определено как

#define PLATFORM(X) X

Полученный MAC является идентификатором и будет позже заменен на 0.Скорее всего, они объединяют X с чем-то вроде PLATFORM, чтобы поддерживать несколько запросов с MAC в качестве аргумента, проверяя наличие различных макросов.Как разработчик инструмента «Статический анализ C ++», вы, вероятно, имеете доступ к спецификации C ++.Взгляните на статью 16.1.

0 голосов
/ 30 июля 2011

Определения могут исходить из сценариев сборки.Большинство компиляторов C ++ позволяют определять макросы в командной строке.

Один из способов определить макрос USE, как в вашем примере, будет:

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

Или, может быть, как:

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