mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 08:30:28 +08:00
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:
parent
4c5bc6f819
commit
0ce0154c40
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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) \
|
||||
|
@ -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.
|
||||
|
30
gcc/testsuite/gcc.dg/format/gcc_gfc-1.c
Normal file
30
gcc/testsuite/gcc.dg/format/gcc_gfc-1.c
Normal 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" } */
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user