C Вариадные макросы __VA_ARGS__ против ##__VA_ARGS__ в clang

У меня есть следующие два макроса:

#define F1(...) [NSString stringWithFormat:__VA_ARGS__]
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]

Когда я их вставляю, F1 работает, но F2 не компилируется.

Этот код:

    F1(@"%@", F1(@"%@", @"a"));
    F2(@"%@", F2(@"%@", @"a"));

Приводит к следующим ошибкам clang:

foo.m:51:15: warning: implicit declaration of function 'F2' is invalid in C99 [-Wimplicit-function-declaration]
    F2(@"%@", F2(@"%@", @"a"));
          ^
foo.m:18:64: note: expanded from macro 'F2'
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
                                                           ^
foo.m:51:15: warning: format specifies type 'id' but the argument has type 'int' [-Wformat]
    F2(@"%@", F2(@"%@", @"a"));
         ~~   ^~~~~~~~~~~~~~~
         %d
foo.m:18:64: note: expanded from macro 'F2'
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]

Обратите внимание, что для F1 нет предупреждений или ошибок, только F2 имеет проблемы.

Что здесь происходит: это ожидаемое поведение или ошибка в clang?

Что еще более важно, есть ли способ настроить F2, чтобы заставить его работать. Я действительно предпочитаю синтаксис F2.


Обновить

Следуя совету @KenThomases, я побежал clang -E -o foo.i foo.m

# 1 "foo.m"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 178 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "foo.m" 2



NSLog([NSString stringWithFormat:@"%@", [NSString stringWithFormat:@"%@", @"a"]]);
NSLog([NSString stringWithFormat:(@"%@"), F2(@"%@", @"a")]);

Я отправил это как дефект на llvm.org: Ошибка 19141


person Jeffery Thomas    schedule 13.03.2014    source источник
comment
В качестве обходного пути используйте #define F3(...) F2(__VA_ARGS__), а затем используйте F3 вместо F2. ;)   -  person augurar    schedule 14.03.2014


Ответы (1)


Мне кажется, что препроцессор не расширяет внутреннее использование макроса F2. По-видимому, использование ##__VA_ARGS__ просто вставляет аргументы внешнего использования F2 дословно, а не выполняет дальнейшее раскрытие.

Вы можете предварительно обработать код компилятором, и он покажет вам, что произошло. cc -E -o foo.i foo.c

person Ken Thomases    schedule 14.03.2014