Question

I have the following two macros:

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

When I nest them, F1 works, but F2 fails to compile.

This code:

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

Results in the following clang errors:

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__]

Note that there is no warning or error for F1, only F2 has problems.

What is going on here: is this the expected behavior or a bug in clang?

More importantly, is there a way for me to tweak F2 to get it to work. I really prefer the syntax of F2.


Update

Following @KenThomases advice I ran 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")]);

I submitted this as a defect to llvm.org: Bug 19141

Was it helpful?

Solution

It looks to me like the preprocessor is not expanding the inner use of the F2 macro. Apparently, the use of ##__VA_ARGS__ is just inserting the arguments of the outer use of F2 verbatim and not performing further expansion.

You can have the compiler preprocess the code and it will show you what happened. cc -E -o foo.i foo.c

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top