This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Add builtins [v]asprintf and [v]dprintf
- From: "Kaveh R. Ghazi" <ghazi at caip dot rutgers dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 2 Jun 2005 13:38:49 -0400 (EDT)
- Subject: [PATCH]: Add builtins [v]asprintf and [v]dprintf
This patch adds "extention" builtins for asprintf, vasprintf, dprintf
and vdprintf (as declared by glibc's stdio.h.) This ensures format
checking is done for these functions.
Bootstrapped on x86_64-unknown-linux-gnu, no regressions and the
relevant testcases all pass.
Okay for mainline?
Thanks,
--Kaveh
2005-06-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtin-types.def (BT_STRING_PTR,
BT_FN_INT_STRINGPTR_CONST_STRING_VALIST_ARG,
BT_FN_INT_INT_CONST_STRING_VALIST_ARG,
BT_FN_INT_STRINGPTR_CONST_STRING_VAR,
BT_FN_INT_INT_CONST_STRING_VAR): New.
* builtins.def (BUILT_IN_ASPRINTF, BUILT_IN_DPRINTF,
BUILT_IN_VASPRINTF, BUILT_IN_VDPRINTF): New.
* c-common.c (string_ptr_type_node): Initialize.
* c-common.h (c_tree_index): Add CTI_STRING_PTR_TYPE.
(string_ptr_type_node): Define.
* doc/extend.texi (asprintf, dprintf, vasprintf, vdprintf):
Document new builtins.
testsuite:
* gcc.dg/format/builtin-1.c, gcc.dg/format/c90-printf-3.c,
gcc.dg/format/c99-printf-3.c, gcc.dg/format/ext-6.c: Test new
builtins asprintf, dprintf, vasprintf and vdprintf.
* gcc.dg/format/format.h (asprintf, dprintf, vasprintf, vdprintf):
Declare.
diff -rup orig/egcc-CVS20050601/gcc/builtin-types.def egcc-CVS20050601/gcc/builtin-types.def
--- orig/egcc-CVS20050601/gcc/builtin-types.def 2005-04-14 22:24:52.000000000 -0400
+++ egcc-CVS20050601/gcc/builtin-types.def 2005-06-02 08:42:24.000000000 -0400
@@ -95,6 +95,7 @@ DEF_PRIMITIVE_TYPE (BT_SSIZE, signed_siz
DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node)
DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
+DEF_PRIMITIVE_TYPE (BT_STRING_PTR, string_ptr_type_node)
DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
@@ -275,6 +276,10 @@ DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CO
BT_INT, BT_STRING, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRINGPTR_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING_PTR, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_INT_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG,
BT_INT, BT_FILEPTR, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_CONST_STRING_CONST_STRING_INT,
@@ -337,6 +342,10 @@ DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_STRIN
BT_INT, BT_STRING, BT_CONST_STRING)
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
BT_INT, BT_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_STRINGPTR_CONST_STRING_VAR,
+ BT_INT, BT_STRING_PTR, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_INT_CONST_STRING_VAR,
+ BT_INT, BT_INT, BT_CONST_STRING)
DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING)
diff -rup orig/egcc-CVS20050601/gcc/builtins.def egcc-CVS20050601/gcc/builtins.def
--- orig/egcc-CVS20050601/gcc/builtins.def 2005-05-30 23:11:42.000000000 -0400
+++ egcc-CVS20050601/gcc/builtins.def 2005-06-02 08:43:29.000000000 -0400
@@ -498,6 +498,8 @@ DEF_LIB_BUILTIN (BUILT_IN_STRSPN,
DEF_LIB_BUILTIN (BUILT_IN_STRSTR, "strstr", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
/* Category: stdio builtins. */
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ASPRINTF, "asprintf", BT_FN_INT_STRINGPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DPRINTF, "dprintf", BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
DEF_LIB_BUILTIN (BUILT_IN_FPRINTF, "fprintf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_UNLOCKED, "fprintf_unlocked", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
DEF_LIB_BUILTIN (BUILT_IN_FPUTC, "fputc", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
@@ -517,6 +519,8 @@ DEF_LIB_BUILTIN (BUILT_IN_SCANF,
DEF_C99_BUILTIN (BUILT_IN_SNPRINTF, "snprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_3_4)
DEF_LIB_BUILTIN (BUILT_IN_SPRINTF, "sprintf", BT_FN_INT_STRING_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
DEF_LIB_BUILTIN (BUILT_IN_SSCANF, "sscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VASPRINTF, "vasprintf", BT_FN_INT_STRINGPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VDPRINTF, "vdprintf", BT_FN_INT_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
DEF_LIB_BUILTIN (BUILT_IN_VFPRINTF, "vfprintf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
DEF_C99_BUILTIN (BUILT_IN_VFSCANF, "vfscanf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
DEF_LIB_BUILTIN (BUILT_IN_VPRINTF, "vprintf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_1_0)
diff -rup orig/egcc-CVS20050601/gcc/c-common.c egcc-CVS20050601/gcc/c-common.c
--- orig/egcc-CVS20050601/gcc/c-common.c 2005-05-26 21:26:52.000000000 -0400
+++ egcc-CVS20050601/gcc/c-common.c 2005-06-02 07:59:01.000000000 -0400
@@ -3086,6 +3086,7 @@ c_common_nodes_and_builtins (void)
const_string_type_node
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
+ string_ptr_type_node = build_pointer_type (string_type_node);
/* This is special for C++ so functions can be overloaded. */
wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
diff -rup orig/egcc-CVS20050601/gcc/c-common.h egcc-CVS20050601/gcc/c-common.h
--- orig/egcc-CVS20050601/gcc/c-common.h 2005-05-28 20:43:15.000000000 -0400
+++ egcc-CVS20050601/gcc/c-common.h 2005-06-02 07:58:12.000000000 -0400
@@ -142,6 +142,7 @@ enum c_tree_index
CTI_INT_ARRAY_TYPE,
CTI_STRING_TYPE,
CTI_CONST_STRING_TYPE,
+ CTI_STRING_PTR_TYPE,
/* Type for boolean expressions (bool in C++, int in C). */
CTI_TRUTHVALUE_TYPE,
@@ -193,6 +194,7 @@ struct c_common_identifier GTY(())
#define int_array_type_node c_global_trees[CTI_INT_ARRAY_TYPE]
#define string_type_node c_global_trees[CTI_STRING_TYPE]
#define const_string_type_node c_global_trees[CTI_CONST_STRING_TYPE]
+#define string_ptr_type_node c_global_trees[CTI_STRING_PTR_TYPE]
#define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE]
diff -rup orig/egcc-CVS20050601/gcc/doc/extend.texi egcc-CVS20050601/gcc/doc/extend.texi
--- orig/egcc-CVS20050601/gcc/doc/extend.texi 2005-05-30 23:11:44.000000000 -0400
+++ egcc-CVS20050601/gcc/doc/extend.texi 2005-06-02 09:46:42.000000000 -0400
@@ -1810,7 +1810,8 @@ modify the header file @file{stdio.h}.
@code{snprintf}, @code{vsnprintf}, @code{vscanf}, @code{vfscanf} and
@code{vsscanf} are also checked. Except in strictly conforming C
standard modes, the X/Open function @code{strfmon} is also checked as
-are @code{printf_unlocked} and @code{fprintf_unlocked}.
+are @code{printf_unlocked}, @code{fprintf_unlocked}, @code{asprintf},
+@code{dprintf}, @code{vasprintf} and @code{vdprintf}.
@xref{C Dialect Options,,Options Controlling C Dialect}.
The target may provide additional types of format checks.
@@ -4737,6 +4738,7 @@ are not prevented from being speculated
@findex asinhf
@findex asinhl
@findex asinl
+@findex asprintf
@findex atan
@findex atan2
@findex atan2f
@@ -4832,6 +4834,7 @@ are not prevented from being speculated
@findex ctanl
@findex dcgettext
@findex dgettext
+@findex dprintf
@findex drem
@findex dremf
@findex dreml
@@ -5073,6 +5076,8 @@ are not prevented from being speculated
@findex trunc
@findex truncf
@findex truncl
+@findex vasprintf
+@findex vdprintf
@findex vfprintf
@findex vfscanf
@findex vprintf
@@ -5111,22 +5116,23 @@ be emitted.
@opindex std
Outside strict ISO C mode (@option{-ansi}, @option{-std=c89} or
@option{-std=c99}), the functions
-@code{_exit}, @code{alloca}, @code{bcmp}, @code{bzero},
-@code{dcgettext}, @code{dgettext}, @code{dremf}, @code{dreml},
-@code{drem}, @code{exp10f}, @code{exp10l}, @code{exp10}, @code{ffsll},
-@code{ffsl}, @code{ffs}, @code{fprintf_unlocked}, @code{fputs_unlocked},
-@code{gammaf}, @code{gammal}, @code{gamma}, @code{gettext},
-@code{index}, @code{isascii}, @code{j0f}, @code{j0l}, @code{j0},
-@code{j1f}, @code{j1l}, @code{j1}, @code{jnf}, @code{jnl}, @code{jn},
+@code{_exit}, @code{alloca}, @code{asprintf}, @code{bcmp},
+@code{bzero}, @code{dcgettext}, @code{dgettext}, @code{dprintf},
+@code{dremf}, @code{dreml}, @code{drem}, @code{exp10f}, @code{exp10l},
+@code{exp10}, @code{ffsll}, @code{ffsl}, @code{ffs},
+@code{fprintf_unlocked}, @code{fputs_unlocked}, @code{gammaf},
+@code{gammal}, @code{gamma}, @code{gettext}, @code{index},
+@code{isascii}, @code{j0f}, @code{j0l}, @code{j0}, @code{j1f},
+@code{j1l}, @code{j1}, @code{jnf}, @code{jnl}, @code{jn},
@code{mempcpy}, @code{pow10f}, @code{pow10l}, @code{pow10},
@code{printf_unlocked}, @code{rindex}, @code{scalbf}, @code{scalbl},
@code{scalb}, @code{signbit}, @code{signbitf}, @code{signbitl},
@code{significandf}, @code{significandl}, @code{significand},
@code{sincosf}, @code{sincosl}, @code{sincos}, @code{stpcpy},
@code{stpncpy}, @code{strcasecmp}, @code{strdup}, @code{strfmon},
-@code{strncasecmp}, @code{strndup}, @code{toascii}, @code{y0f},
-@code{y0l}, @code{y0}, @code{y1f}, @code{y1l}, @code{y1}, @code{ynf},
-@code{ynl} and @code{yn}
+@code{strncasecmp}, @code{strndup}, @code{toascii}, @code{vasprintf},
+@code{vdprintf}, @code{y0f}, @code{y0l}, @code{y0}, @code{y1f},
+@code{y1l}, @code{y1}, @code{ynf}, @code{ynl} and @code{yn}
may be handled as built-in functions.
All these functions have corresponding versions
prefixed with @code{__builtin_}, which may be used even in strict C89
diff -rup orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/builtin-1.c egcc-CVS20050601/gcc/testsuite/gcc.dg/format/builtin-1.c
--- orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/builtin-1.c 2001-12-20 21:36:37.000000000 -0500
+++ egcc-CVS20050601/gcc/testsuite/gcc.dg/format/builtin-1.c 2005-06-02 08:45:40.000000000 -0400
@@ -8,12 +8,20 @@
#include "format.h"
void
-foo (int i)
+foo (int i, char **sp, va_list v0)
{
+ __builtin_asprintf (sp, "%d", i);
+ __builtin_asprintf (sp, "%ld", i); /* { dg-warning "format" "__builtin_asprintf" } */
+ __builtin_dprintf (i, "%d", i);
+ __builtin_dprintf (i, "%ld", i); /* { dg-warning "format" "__builtin_dprintf" } */
__builtin_fprintf (stdout, "%d", i);
__builtin_fprintf (stdout, "%ld", i); /* { dg-warning "format" "__builtin_fprintf" } */
__builtin_printf ("%d", i);
__builtin_printf ("%ld", i); /* { dg-warning "format" "__builtin_printf" } */
+ __builtin_vasprintf (sp, "%d", v0);
+ __builtin_vasprintf (sp, "%Y", v0); /* { dg-warning "format" "__builtin_vasprintf" } */
+ __builtin_vdprintf (i, "%d", v0);
+ __builtin_vdprintf (i, "%Y", v0); /* { dg-warning "format" "__builtin_vdprintf" } */
__builtin_fprintf_unlocked (stdout, "%d", i);
__builtin_fprintf_unlocked (stdout, "%ld", i); /* { dg-warning "format" "__builtin_fprintf_unlocked" } */
diff -rup orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c90-printf-3.c egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c90-printf-3.c
--- orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c90-printf-3.c 2001-12-20 21:36:37.000000000 -0500
+++ egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c90-printf-3.c 2005-06-02 08:47:33.000000000 -0400
@@ -9,16 +9,20 @@
#include "format.h"
void
-foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3,
- va_list v4, va_list v5, va_list v6, va_list v7, va_list v8)
+foo (int i, char *s, char **sp, size_t n, va_list v0, va_list v1, va_list v2,
+ va_list v3, va_list v4, va_list v5, va_list v6, va_list v7, va_list v8)
{
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
printf ("%ld", i); /* { dg-warning "format" "printf" } */
- /* The "unlocked" functions shouldn't warn in c90 mode. */
+ /* Any "extention" functions shouldn't warn in c90 mode. */
fprintf_unlocked (stdout, "%ld", i); /* { dg-bogus "format" "fprintf_unlocked" } */
printf_unlocked ("%ld", i); /* { dg-bogus "format" "printf_unlocked" } */
+ asprintf (sp, "%ld", i); /* { dg-bogus "format" "asprintf" } */
+ vasprintf (sp, "%Y", v0); /* { dg-bogus "format" "vasprintf" } */
+ dprintf (i, "%ld", i); /* { dg-bogus "format" "dprintf" } */
+ vdprintf (i, "%Y", v0); /* { dg-bogus "format" "vdprintf" } */
sprintf (s, "%d", i);
sprintf (s, "%ld", i); /* { dg-warning "format" "sprintf" } */
vfprintf (stdout, "%d", v0);
diff -rup orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c99-printf-3.c egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c99-printf-3.c
--- orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c99-printf-3.c 2001-12-20 21:36:37.000000000 -0500
+++ egcc-CVS20050601/gcc/testsuite/gcc.dg/format/c99-printf-3.c 2005-06-02 08:48:10.000000000 -0400
@@ -8,16 +8,20 @@
#include "format.h"
void
-foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3,
- va_list v4, va_list v5, va_list v6, va_list v7)
+foo (int i, char *s, char **sp, size_t n, va_list v0, va_list v1, va_list v2,
+ va_list v3, va_list v4, va_list v5, va_list v6, va_list v7)
{
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
printf ("%ld", i); /* { dg-warning "format" "printf" } */
- /* The "unlocked" functions shouldn't warn in c99 mode. */
+ /* Any "extension" functions shouldn't warn in c99 mode. */
fprintf_unlocked (stdout, "%ld", i); /* { dg-bogus "format" "fprintf_unlocked" } */
printf_unlocked ("%ld", i); /* { dg-bogus "format" "printf_unlocked" } */
+ asprintf (sp, "%ld", i); /* { dg-bogus "format" "asprintf" } */
+ vasprintf (sp, "%Y", v0); /* { dg-bogus "format" "vasprintf" } */
+ dprintf (i, "%ld", i); /* { dg-bogus "format" "dprintf" } */
+ vdprintf (i, "%Y", v0); /* { dg-bogus "format" "vdprintf" } */
sprintf (s, "%d", i);
sprintf (s, "%ld", i); /* { dg-warning "format" "sprintf" } */
snprintf (s, n, "%d", i);
diff -rup orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/ext-6.c egcc-CVS20050601/gcc/testsuite/gcc.dg/format/ext-6.c
--- orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/ext-6.c 2001-12-20 21:36:37.000000000 -0500
+++ egcc-CVS20050601/gcc/testsuite/gcc.dg/format/ext-6.c 2005-06-02 08:48:57.000000000 -0400
@@ -8,10 +8,15 @@
#include "format.h"
void
-foo (int i, char *s, size_t n, int *ip, va_list v0, va_list v1, va_list v2,
- va_list v3, va_list v4, va_list v5, va_list v6, va_list v7, va_list v8,
- va_list v9, va_list v10, va_list v11, va_list v12, va_list v13)
+foo (int i, char *s, char **sp, size_t n, int *ip, va_list v0, va_list v1,
+ va_list v2, va_list v3, va_list v4, va_list v5, va_list v6, va_list v7,
+ va_list v8, va_list v9, va_list v10, va_list v11, va_list v12,
+ va_list v13)
{
+ asprintf (sp, "%d", i);
+ asprintf (sp, "%ld", i); /* { dg-warning "format" "asprintf" } */
+ dprintf (i, "%d", i);
+ dprintf (i, "%ld", i); /* { dg-warning "format" "dprintf" } */
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
@@ -24,6 +29,10 @@ foo (int i, char *s, size_t n, int *ip,
sprintf (s, "%ld", i); /* { dg-warning "format" "sprintf" } */
snprintf (s, n, "%d", i);
snprintf (s, n, "%ld", i); /* { dg-warning "format" "snprintf" } */
+ vasprintf (sp, "%d", v0);
+ vasprintf (sp, "%Y", v1); /* { dg-warning "format" "vasprintf" } */
+ vdprintf (i, "%d", v0);
+ vdprintf (i, "%Y", v1); /* { dg-warning "format" "vdprintf" } */
vfprintf (stdout, "%d", v0);
vfprintf (stdout, "%Y", v1); /* { dg-warning "format" "vfprintf" } */
vprintf ("%d", v2);
diff -rup orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/format.h egcc-CVS20050601/gcc/testsuite/gcc.dg/format/format.h
--- orig/egcc-CVS20050601/gcc/testsuite/gcc.dg/format/format.h 2004-09-03 14:09:33.000000000 -0400
+++ egcc-CVS20050601/gcc/testsuite/gcc.dg/format/format.h 2005-06-02 08:46:15.000000000 -0400
@@ -42,11 +42,15 @@ typedef struct _FILE FILE;
extern FILE *stdin;
extern FILE *stdout;
+extern int asprintf (char **restrict, const char *restrict, ...);
+extern int dprintf (int, const char *restrict, ...);
extern int fprintf (FILE *restrict, const char *restrict, ...);
extern int printf (const char *restrict, ...);
extern int fprintf_unlocked (FILE *restrict, const char *restrict, ...);
extern int printf_unlocked (const char *restrict, ...);
extern int sprintf (char *restrict, const char *restrict, ...);
+extern int vasprintf (char **restrict, const char *restrict, va_list);
+extern int vdprintf (int, const char *restrict, va_list);
extern int vfprintf (FILE *restrict, const char *restrict, va_list);
extern int vprintf (const char *restrict, va_list);
extern int vsprintf (char *restrict, const char *restrict, va_list);