diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2005-07-03 14:28:03 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2005-07-03 14:28:03 +0000 |
commit | 0ce0154c400c8ee912f32cf62164fbf88bfcfde3 (patch) | |
tree | fc2772efedbf66e55c9a9b40eaefe5699f7ff993 /gcc/c-format.c | |
parent | 4c5bc6f8191db75af2b024bc981562b0c0648ae2 (diff) | |
download | gcc-0ce0154c400c8ee912f32cf62164fbf88bfcfde3.tar.gz |
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
Diffstat (limited to 'gcc/c-format.c')
-rw-r--r-- | gcc/c-format.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/gcc/c-format.c b/gcc/c-format.c index 49af5762298..10a5f21db59 100644 --- a/gcc/c-format.c +++ b/gcc/c-format.c @@ -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 |