views:

824

answers:

2

Hello,

Here is a little piece of code:

#include <stdio.h>
#include <stdarg.h>

void MyPrintf(char const* format, va_list args);
void MyVariadicPrintf(char const* format, ...);

void MyPrintf(char const* format, va_list args)
{
    vprintf(format, args);
}

void MyVariadicPrintf(char const* format, ...)
{
    va_list args;
    va_start(args, format);
    MyPrintf(format, args);
    va_end(args);
}

int main(int, char*)
{
    MyVariadicPrintf("%s" /* missing 2nd argument */);

    return 0;
}

I'm compiling it with GCC 4.0, running Xcode on Mac OS X Leopard.
-Wformat and -Wmissing-format-attribute are enabled.
This code gives a warning on line 9 (call to vprintf), suggesting that MyPrintf could use the 'format' attribute:

function might be possible candidate for 'printf' format attribute

So I add the attribute this way (not sure if this is right):

void MyPrintf(char const* format, va_list args) __attribute__((format(printf, 1, 0)));

The previous warning disappears and the same warning now appears on line 16 (call to MyPrintf), suggesting that MyVariadicPrintf could use the 'format' attribute.
So I add the attribute this way (pretty sure this is right this time):

void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2)));

And now I get the expected warning on line 22 (call to MyVariadicPrintf):

too few arguments for format

  1. Did I do this right?
  2. I noticed that on MyPrintf declaration, if I delete the attribute part, I'll still get the wanted warning on line 22. I also noticed that in this attribute part, changing the index from 1 to 2 won't give any warning or error. Which one is right and what is the goal of the attribute on this function?
  3. If I add the following function MyVariadicPrintfT and call it (specialized with char), I'll get the warning suggesting to use the 'format' attribute on this function. I think it's impossible because the format argument is dependent on the templated type. Am I right?

    template<typename Type>
    void MyVariadicPrintfT(Type const* format, ...)
    {
        va_list args;
        va_start(args, format);
        MyPrintf(format, args);
        va_end(args);
    }
    

Documentation can be found on Apple's website.
Warning Options are in section 3.8 (look for "-Wmissing-format-attribute").
Function Attributes are in section 5.24 (look for "format (archetype, string-index, first-to-check)").

Thanks.

+2  A: 

Take a look at the GCC docs on gnu.org. As for the last question, my guess is that MyPrintf is not a template function and the only definition available takes char const* as the first argument so it feels safe making the suggestion.

D.Shawley
+2  A: 

The documentation has the answer you need. Particularly:

  1. Yes
  2. The one you have posted is correct (format(printf, 1, 0)). 1 because the format string is parameter 1, 0 because there are no variadic arguments to be checked.
jpalecek
In MyVariadicPrintf, I understand that the compiler will check the number and types of the arguments beginning at position 2 against the string at position 1. But in the case of MyPrintf, what does the compiler check?
Guillaume
In case of MyPrintf, it will only check for validity of the format string (eg. that it isn't something like "%_%")
jpalecek
Ok, thanks a lot!
Guillaume