Skip to content

Commit

Permalink
locale.c: fix format string for __LINE__ output (debugging)
Browse files Browse the repository at this point in the history
On some platforms, building a -DDEBUGGING perl triggers the following
compiler warnings:

    In file included from locale.c:385:
    locale.c: In function ‘S_bool_setlocale_2008_i’:
    locale.c:2494:29: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 7 has type ‘int’ [-Wformat=]
                                 "bool_setlocale_2008_i: creating new object"    \
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    perl.h:4983:33: note: in definition of macro ‘DEBUG__’
                     DEBUG_PRE_STMTS a; DEBUG_POST_STMTS                     \
                                     ^
    locale.c:2493:7: note: in expansion of macro ‘DEBUG_L’
           DEBUG_L(PerlIO_printf(Perl_debug_log,                                 \
           ^~~~~~~
    locale.c:2523:17: note: in expansion of macro ‘DEBUG_NEW_OBJECT_FAILED’
                     DEBUG_NEW_OBJECT_FAILED(category_names[index], new_locale,
                     ^~~~~~~~~~~~~~~~~~~~~~~
    In file included from locale.c:322:
    config.h:4052:18: note: format string is defined here
     #define U32uf  "lu"  /**/

This is because the code tries to format __LINE__ with a varargs
function using %"LINE_Tf".

Things are slightly tricky here because in a varargs function, no type
context is available, so the format string absolutely has to match the
intrinsic type of each argument. The __LINE__ macro expands to a simple
(decimal) integer constant. According to C, such a constant has type int
if its value fits, otherwise unsigned int if it fits, otherwise long
int, etc. None of the *.c files in the perl distribution exceed 32767
lines (the minimum INT_MAX required by C), so even on ancient 16-bit
systems, our __LINE__ will always be of type int.

The %"LINE_Tf" format is designed to match a line_t argument, not int.
(On some platforms, line_t is defined as unsigned long and incompatible
with int for formatting purposes.) Therefore it is an error to use
%"LINE_Tf" with __LINE__.

One way to fix this is to convert the argument to match the format
string: ... %"LINE_Tf" ...", (line_t)__LINE__.

The other way is to change the format string to match the (int)
argument: "... %d ...", __LINE__.

I chose option Perl#2 because it is by far the most common way to output
__LINE__ elsewhere in the perl source.
  • Loading branch information
mauke committed Feb 8, 2024
1 parent 85a3d70 commit d8d7b3d
Showing 1 changed file with 6 additions and 6 deletions.
12 changes: 6 additions & 6 deletions locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,14 @@ static int debug_initialization = 0;
# if defined(USE_THREADS) && ! defined(NO_LOCALE_THREADS)
# define DEBUG_PRE_STMTS \
DEBUG_ERRNO; \
PerlIO_printf(Perl_debug_log, "\n%s: %" LINE_Tf ": 0x%p%s: ", \
__FILE__, (line_t)__LINE__, aTHX_ \
PerlIO_printf(Perl_debug_log, "\n%s: %d: 0x%p%s: ", \
__FILE__, __LINE__, aTHX_ \
errno_string);
# else
# define DEBUG_PRE_STMTS \
DEBUG_ERRNO; \
PerlIO_printf(Perl_debug_log, "\n%s: %" LINE_Tf "%s: ", \
__FILE__, (line_t)__LINE__, \
PerlIO_printf(Perl_debug_log, "\n%s: %d%s: ", \
__FILE__, __LINE__, \
errno_string);
# endif
# define DEBUG_POST_STMTS RESTORE_ERRNO;
Expand Down Expand Up @@ -2486,14 +2486,14 @@ S_bool_setlocale_2008_i(pTHX_
DEBUG_Lv(PerlIO_printf(Perl_debug_log, \
"bool_setlocale_2008_i(%s, %s): created %p" \
" while freeing %p; called from %" LINE_Tf \
" via %" LINE_Tf "\n", \
" via %d\n", \
category, locale, new, old, \
caller_line, __LINE__))
# define DEBUG_NEW_OBJECT_FAILED(category, locale, basis_obj) \
DEBUG_L(PerlIO_printf(Perl_debug_log, \
"bool_setlocale_2008_i: creating new object" \
" for (%s '%s') from %p failed; called from %" \
LINE_Tf " via %" LINE_Tf "\n", \
LINE_Tf " via %d\n", \
category, locale, basis_obj, \
caller_line, __LINE__));

Expand Down

0 comments on commit d8d7b3d

Please sign in to comment.