c-format.c (gcc_gfc_format_type, [...]): New.

* c-format.c (gcc_gfc_format_type, gcc_gfc_flag_pairs,
	gcc_gfc_char_table, init_dynamic_gfc_info): New.
	(format_types_orig, handle_format_attribute): Add support for
	format "gcc_gfc".

fortran:
	* error.c (error_printf, error_print): Use ATTRIBUTE_GCC_GFC.
	* gfortran.h (ATTRIBUTE_GCC_GFC): New.
	(gfc_warning, gfc_warning_now, gfc_error, gfc_error_now,
	gfc_fatal_error, gfc_internal_error, gfc_notify_std): Use
	ATTRIBUTE_GCC_GFC.

testsuite:
	* gcc.dg/format/gcc_gfc-1.c: New.

From-SVN: r101552
This commit is contained in:
Kaveh R. Ghazi 2005-07-03 14:28:03 +00:00 committed by Kaveh Ghazi
parent 4c5bc6f819
commit 0ce0154c40
7 changed files with 149 additions and 10 deletions

View File

@ -1,3 +1,10 @@
2005-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* c-format.c (gcc_gfc_format_type, gcc_gfc_flag_pairs,
gcc_gfc_char_table, init_dynamic_gfc_info): New.
(format_types_orig, handle_format_attribute): Add support for
format "gcc_gfc".
2005-07-03 Gabriel Dos Reis <gdr@integrable-solutions.net>
* varasm.c (assemble_variable): Fix format specifier thinko.

View File

@ -60,7 +60,7 @@ set_Wformat (int setting)
enum format_type { printf_format_type, asm_fprintf_format_type,
gcc_diag_format_type, gcc_tdiag_format_type,
gcc_cdiag_format_type,
gcc_cxxdiag_format_type,
gcc_cxxdiag_format_type, gcc_gfc_format_type,
scanf_format_type, strftime_format_type,
strfmon_format_type, format_type_error = -1};
@ -392,6 +392,11 @@ static const format_flag_pair gcc_diag_flag_pairs[] =
#define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
#define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
static const format_flag_pair gcc_gfc_flag_pairs[] =
{
{ 0, 0, 0, 0 }
};
static const format_flag_spec gcc_diag_flag_specs[] =
{
{ '+', 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
@ -619,6 +624,23 @@ static const format_char_info gcc_cxxdiag_char_table[] =
{ NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info gcc_gfc_char_table[] =
{
/* C89 conversion specifiers. */
{ "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL },
/* gfc conversion specifiers. */
{ "C", 0, STD_C89, NOARGUMENTS, "", "", NULL },
/* This will require a "locus" at runtime. */
{ "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
};
static const format_char_info scan_char_table[] =
{
/* C89 conversion specifiers. */
@ -711,6 +733,12 @@ static const format_kind_info format_types_orig[] =
0, 0, 'p', 0, 'L',
NULL, &integer_type_node
},
{ "gcc_gfc", NULL, gcc_gfc_char_table, "", NULL,
NULL, gcc_gfc_flag_pairs,
FMT_FLAG_ARG_CONVERT,
0, 0, 0, 0, 0,
NULL, NULL
},
{ "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
scanf_flag_specs, scanf_flag_pairs,
FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
@ -2383,6 +2411,55 @@ init_dynamic_asm_fprintf_info (void)
}
}
/* Determine the type of a "locus" in the code being compiled for use
in GCC's __gcc_gfc__ custom format attribute. You must have set
dynamic_format_types before calling this function. */
static void
init_dynamic_gfc_info (void)
{
static tree locus;
if (!locus)
{
static format_char_info *gfc_fci;
/* For the GCC __gcc_gfc__ custom format specifier to work, one
must have declared 'locus' prior to using this attribute. If
we haven't seen this declarations then you shouldn't use the
specifier requiring that type. */
if ((locus = maybe_get_identifier ("locus")))
{
locus = identifier_global_value (locus);
if (locus)
{
if (TREE_CODE (locus) != TYPE_DECL)
{
error ("%<locus%> is not defined as a type");
locus = 0;
}
else
locus = TREE_TYPE (locus);
}
}
/* Assign the new data for use. */
/* Handle the __gcc_gfc__ format specifics. */
if (!gfc_fci)
dynamic_format_types[gcc_gfc_format_type].conversion_specs =
gfc_fci = (format_char_info *)
xmemdup (gcc_gfc_char_table,
sizeof (gcc_gfc_char_table),
sizeof (gcc_gfc_char_table));
if (locus)
{
const unsigned i = find_char_info_specifier_index (gfc_fci, 'L');
gfc_fci[i].types[0].type = &locus;
gfc_fci[i].pointer_count = 1;
}
}
}
/* Determine the types of "tree" and "location_t" in the code being
compiled for use in GCC's diagnostic custom format attributes. You
must have set dynamic_format_types before calling this function. */
@ -2660,6 +2737,7 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
/* If this is a custom GCC-internal format type, we have to
initialize certain bits a runtime. */
if (info.format_type == asm_fprintf_format_type
|| info.format_type == gcc_gfc_format_type
|| info.format_type == gcc_diag_format_type
|| info.format_type == gcc_tdiag_format_type
|| info.format_type == gcc_cdiag_format_type
@ -2676,6 +2754,10 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
GCC's notion of HOST_WIDE_INT for checking %wd. */
if (info.format_type == asm_fprintf_format_type)
init_dynamic_asm_fprintf_info ();
/* If this is format __gcc_gfc__, we have to initialize GCC's
notion of 'locus' at runtime for %L. */
else if (info.format_type == gcc_gfc_format_type)
init_dynamic_gfc_info ();
/* If this is one of the diagnostic attributes, then we have to
initialize 'location_t' and 'tree' at runtime. */
else if (info.format_type == gcc_diag_format_type

View File

@ -1,3 +1,11 @@
2005-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* error.c (error_printf, error_print): Use ATTRIBUTE_GCC_GFC.
* gfortran.h (ATTRIBUTE_GCC_GFC): New.
(gfc_warning, gfc_warning_now, gfc_error, gfc_error_now,
gfc_fatal_error, gfc_internal_error, gfc_notify_std): Use
ATTRIBUTE_GCC_GFC.
2005-07-03 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR fortran/20842

View File

@ -118,7 +118,7 @@ error_string (const char *p)
locus. Calls error_printf() recursively, but the recursion is at
most one level deep. */
static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1;
static void error_printf (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
static void
show_locus (int offset, locus * loc)
@ -314,7 +314,7 @@ separate:
#define IBUF_LEN 30
#define MAX_ARGS 10
static void
static void ATTRIBUTE_GCC_GFC(2,0)
error_print (const char *type, const char *format0, va_list argp)
{
char c, *p, int_buf[IBUF_LEN], c_arg[MAX_ARGS], *cp_arg[MAX_ARGS];

View File

@ -501,6 +501,14 @@ typedef struct
gfc_linebuf *lb;
} locus;
/* In order for the "gfc" format checking to work correctly, you must
have declared a typedef locus first. */
#if GCC_VERSION >= 4001
#define ATTRIBUTE_GCC_GFC(m, n) __attribute__ ((__format__ (__gcc_gfc__, m, n))) ATTRIBUTE_NONNULL(m)
#else
#define ATTRIBUTE_GCC_GFC(m, n) ATTRIBUTE_NONNULL(m)
#endif
#include <limits.h>
#ifndef PATH_MAX
@ -1543,19 +1551,19 @@ typedef struct gfc_error_buf
void gfc_error_init_1 (void);
void gfc_buffer_error (int);
void gfc_warning (const char *, ...);
void gfc_warning_now (const char *, ...);
void gfc_warning (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_warning_now (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_clear_warning (void);
void gfc_warning_check (void);
void gfc_error (const char *, ...);
void gfc_error_now (const char *, ...);
void gfc_fatal_error (const char *, ...) ATTRIBUTE_NORETURN;
void gfc_internal_error (const char *, ...) ATTRIBUTE_NORETURN;
void gfc_error (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_error_now (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_fatal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_GCC_GFC(1,2);
void gfc_internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_GCC_GFC(1,2);
void gfc_clear_error (void);
int gfc_error_check (void);
try gfc_notify_std (int, const char *, ...);
try gfc_notify_std (int, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
/* A general purpose syntax error. */
#define gfc_syntax_error(ST) \

View File

@ -1,3 +1,7 @@
2005-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/format/gcc_gfc-1.c: New.
2005-07-03 Andrew Pinski <pinskia@physics.uc.edu>
* pr14490-[1-4].c: Fix typos scan-tree-dump-times so they now pass.

View File

@ -0,0 +1,30 @@
/* Test for gcc_gfc formats. */
/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
/* { dg-do compile } */
/* { dg-options "-Wformat" } */
#include "format.h"
/* Magic identifier must be set before the attribute is used. */
typedef struct locus locus;
extern int gfc_warn (const char *, ...) __attribute__ ((__format__ (__gcc_gfc__, 1, 2))) __attribute__ ((__nonnull__));
void
foo (int i, char *s, long int l, llong ll, locus *loc)
{
/* Acceptable C90 specifiers, flags and modifiers. */
gfc_warn ("%%");
gfc_warn ("%d%i%c%s%%", i, i, i, s);
/* Extensions provided in gfc_warn. */
gfc_warn ("%C");
gfc_warn ("%L", loc);
/* Various tests of bad argument types. */
gfc_warn ("%d", l); /* { dg-warning "format" "bad argument types" } */
gfc_warn ("%d", ll); /* { dg-warning "format" "bad argument types" } */
gfc_warn ("%s", &i); /* { dg-warning "format" "bad argument types" } */
gfc_warn ("%L", &i); /* { dg-warning "format" "bad argument types" } */
gfc_warn ("%C", i); /* { dg-warning "format" "too many arguments" } */
}