mark Perl_my_strftime with format attribute
authorDavid Mitchell <davem@iabyn.com>
Tue, 26 Nov 2013 15:50:45 +0000 (15:50 +0000)
committerDavid Mitchell <davem@iabyn.com>
Thu, 28 Nov 2013 17:03:49 +0000 (17:03 +0000)
mark this function with

    __attribute__format__null_ok__(__strftime__,pTHX_1,0)

so that compiler checks and warnings about strftime-style format args
can be checked.

Rather than adding new flag(s) to embed.fnc, I just enhanced the f flag
to treat it as strftime-style rather than printf if the function name
matches /strftime/. This was quicker, and we're unlikely to have many
such functions.

embed.fnc
proto.h
regen/embed.pl

index 825ebc9..abb2b1b 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
 :        1) must be static to its containing file ("i" or "s" flag); or
 :         2) be combined with the "X" flag.
 :
-:   f  Function takes printf style format string, varargs (hence any entry that
-:      would otherwise go in embed.h is suppressed):
+:   f  Function takes a format string. If the function name /strftime/
+:      then its assumed to take a strftime-style format string as 1st arg;
+:      otherwise it's assumed to be a printf style format string, varargs
+:      (hence any entry that would otherwise go in embed.h is suppressed):
 :
 :         proto.h: add __attribute__format__ (or ...null_ok__)
 :
@@ -898,7 +900,7 @@ Ap  |PerlIO*|my_popen_list  |NN const char* mode|int n|NN SV ** args
 Ap     |void   |my_setenv      |NULLOK const char* nam|NULLOK const char* val
 Apmb   |I32    |my_stat
 pX     |I32    |my_stat_flags  |NULLOK const U32 flags
-Ap     |char * |my_strftime    |NN const char *fmt|int sec|int min|int hour|int mday|int mon|int year|int wday|int yday|int isdst
+Afp    |char * |my_strftime    |NN const char *fmt|int sec|int min|int hour|int mday|int mon|int year|int wday|int yday|int isdst
 : Used in pp_ctl.c
 p      |void   |my_unexec
 ADMnoPR        |UV     |NATIVE_TO_NEED |const UV enc|const UV ch
diff --git a/proto.h b/proto.h
index 54a501d..80dfa5a 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -2681,6 +2681,7 @@ PERL_CALLCONV int Perl_my_socketpair(int family, int type, int protocol, int fd[
 /* PERL_CALLCONV I32   Perl_my_stat(pTHX); */
 PERL_CALLCONV I32      Perl_my_stat_flags(pTHX_ const U32 flags);
 PERL_CALLCONV char *   Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, int mon, int year, int wday, int yday, int isdst)
+                       __attribute__format__null_ok__(__strftime__,pTHX_1,0)
                        __attribute__nonnull__(pTHX_1);
 #define PERL_ARGS_ASSERT_MY_STRFTIME   \
        assert(fmt)
index 521217d..6571aec 100755 (executable)
@@ -184,8 +184,13 @@ my ($embed, $core, $ext, $api) = setup_embed();
            my $macro   = @nonnull && $nonnull[-1] == $pat  
                                ? '__attribute__format__'
                                : '__attribute__format__null_ok__';
-           push @attrs, sprintf "%s(__printf__,%s%d,%s%d)", $macro,
-                               $prefix, $pat, $prefix, $args;
+           if ($plain_func =~ /strftime/) {
+               push @attrs, sprintf "%s(__strftime__,%s1,0)", $macro, $prefix;
+           }
+           else {
+               push @attrs, sprintf "%s(__printf__,%s%d,%s%d)", $macro,
+                                   $prefix, $pat, $prefix, $args;
+           }
        }
        if ( @nonnull ) {
            my @pos = map { $has_context ? "pTHX_$_" : $_ } @nonnull;