};
-/* For now, the Fortran front-end routines only use l as length modifier. */
+/* Length modifiers used by the fortran/error.c routines. */
static const format_length_info gcc_gfc_length_specs[] =
{
- { "l", FMT_LEN_l, STD_C89, NO_FMT, 0 },
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
+ { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
{ NO_FMT, NO_FMT, 0 }
};
static const format_char_info gcc_gfc_char_table[] =
{
/* C89 conversion specifiers. */
- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
+ { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
+ { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
+ { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
/* gfc conversion specifiers. */
}
}
+static const format_length_info*
+get_init_dynamic_hwi (void)
+{
+ static tree hwi;
+ static format_length_info *diag_ls;
+
+ if (!hwi)
+ {
+ unsigned int i;
+
+ /* Find the underlying type for HOST_WIDE_INT. For the 'w'
+ length modifier to work, one must have issued: "typedef
+ HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
+ prior to using that modifier. */
+ if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
+ {
+ hwi = identifier_global_value (hwi);
+ if (hwi)
+ {
+ if (TREE_CODE (hwi) != TYPE_DECL)
+ {
+ error ("%<__gcc_host_wide_int__%> is not defined as a type");
+ hwi = 0;
+ }
+ else
+ {
+ hwi = DECL_ORIGINAL_TYPE (hwi);
+ gcc_assert (hwi);
+ if (hwi != long_integer_type_node
+ && hwi != long_long_integer_type_node)
+ {
+ error ("%<__gcc_host_wide_int__%> is not defined"
+ " as %<long%> or %<long long%>");
+ hwi = 0;
+ }
+ }
+ }
+ }
+ if (!diag_ls)
+ diag_ls = (format_length_info *)
+ xmemdup (gcc_diag_length_specs,
+ sizeof (gcc_diag_length_specs),
+ sizeof (gcc_diag_length_specs));
+ if (hwi)
+ {
+ /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
+ i = find_length_info_modifier_index (diag_ls, 'w');
+ if (hwi == long_integer_type_node)
+ diag_ls[i].index = FMT_LEN_l;
+ else if (hwi == long_long_integer_type_node)
+ diag_ls[i].index = FMT_LEN_ll;
+ else
+ gcc_unreachable ();
+ }
+ }
+ return diag_ls;
+}
+
/* 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)
{
+ dynamic_format_types[gcc_gfc_format_type].length_char_specs
+ = get_init_dynamic_hwi ();
+
if (!locus)
{
static format_char_info *gfc_fci;
|| local_event_ptr_node == void_type_node)
local_event_ptr_node = get_named_type ("diagnostic_event_id_t");
- static tree hwi;
-
- if (!hwi)
- {
- static format_length_info *diag_ls;
- unsigned int i;
-
- /* Find the underlying type for HOST_WIDE_INT. For the 'w'
- length modifier to work, one must have issued: "typedef
- HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
- prior to using that modifier. */
- if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
- {
- hwi = identifier_global_value (hwi);
- if (hwi)
- {
- if (TREE_CODE (hwi) != TYPE_DECL)
- {
- error ("%<__gcc_host_wide_int__%> is not defined as a type");
- hwi = 0;
- }
- else
- {
- hwi = DECL_ORIGINAL_TYPE (hwi);
- gcc_assert (hwi);
- if (hwi != long_integer_type_node
- && hwi != long_long_integer_type_node)
- {
- error ("%<__gcc_host_wide_int__%> is not defined"
- " as %<long%> or %<long long%>");
- hwi = 0;
- }
- }
- }
- }
-
- /* Assign the new data for use. */
-
- /* All the GCC diag formats use the same length specs. */
- if (!diag_ls)
- dynamic_format_types[gcc_diag_format_type].length_char_specs =
- dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
- diag_ls = (format_length_info *)
- xmemdup (gcc_diag_length_specs,
- sizeof (gcc_diag_length_specs),
- sizeof (gcc_diag_length_specs));
- if (hwi)
- {
- /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
- i = find_length_info_modifier_index (diag_ls, 'w');
- if (hwi == long_integer_type_node)
- diag_ls[i].index = FMT_LEN_l;
- else if (hwi == long_long_integer_type_node)
- diag_ls[i].index = FMT_LEN_ll;
- else
- gcc_unreachable ();
- }
- }
+ /* All the GCC diag formats use the same length specs. */
+ dynamic_format_types[gcc_diag_format_type].length_char_specs =
+ dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_dump_printf_format_type].length_char_specs
+ = get_init_dynamic_hwi ();
/* It's safe to "re-initialize these to the same values. */
dynamic_format_types[gcc_diag_format_type].conversion_specs =
#define IBUF_LEN 60
static void
-error_uinteger (unsigned long int i)
+error_uinteger (unsigned long long int i)
{
char *p, int_buf[IBUF_LEN];
}
static void
-error_integer (long int i)
+error_integer (long long int i)
{
- unsigned long int u;
+ unsigned long long int u;
if (i < 0)
{
- u = (unsigned long int) -i;
+ u = (unsigned long long int) -i;
+ error_char ('-');
+ }
+ else
+ u = i;
+
+ error_uinteger (u);
+}
+
+
+static void
+error_hwuint (unsigned HOST_WIDE_INT i)
+{
+ char *p, int_buf[IBUF_LEN];
+
+ p = int_buf + IBUF_LEN - 1;
+ *p-- = '\0';
+
+ if (i == 0)
+ *p-- = '0';
+
+ while (i > 0)
+ {
+ *p-- = i % 10 + '0';
+ i = i / 10;
+ }
+
+ error_string (p + 1);
+}
+
+static void
+error_hwint (HOST_WIDE_INT i)
+{
+ unsigned HOST_WIDE_INT u;
+
+ if (i < 0)
+ {
+ u = (unsigned HOST_WIDE_INT) -i;
error_char ('-');
}
else
error_print (const char *type, const char *format0, va_list argp)
{
enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_UINTEGER,
- TYPE_LONGINT, TYPE_ULONGINT, TYPE_CHAR, TYPE_STRING,
- NOTYPE };
+ TYPE_LONGINT, TYPE_ULONGINT, TYPE_LLONGINT, TYPE_ULLONGINT,
+ TYPE_HWINT, TYPE_HWUINT, TYPE_CHAR, TYPE_STRING, NOTYPE };
struct
{
int type;
unsigned int uintval;
long int longintval;
unsigned long int ulongintval;
+ long long int llongintval;
+ unsigned long long int ullongintval;
+ HOST_WIDE_INT hwintval;
+ unsigned HOST_WIDE_INT hwuintval;
char charval;
const char * stringval;
} u;
case 'l':
c = *format++;
- if (c == 'u')
+ if (c == 'l')
+ {
+ c = *format++;
+ if (c == 'u')
+ arg[pos].type = TYPE_ULLONGINT;
+ else if (c == 'i' || c == 'd')
+ arg[pos].type = TYPE_LLONGINT;
+ else
+ gcc_unreachable ();
+ }
+ else if (c == 'u')
arg[pos].type = TYPE_ULONGINT;
else if (c == 'i' || c == 'd')
arg[pos].type = TYPE_LONGINT;
gcc_unreachable ();
break;
+ case 'w':
+ c = *format++;
+ if (c == 'u')
+ arg[pos].type = TYPE_HWUINT;
+ else if (c == 'i' || c == 'd')
+ arg[pos].type = TYPE_HWINT;
+ else
+ gcc_unreachable ();
+ break;
+
case 'c':
arg[pos].type = TYPE_CHAR;
break;
arg[pos].u.ulongintval = va_arg (argp, unsigned long int);
break;
+ case TYPE_LLONGINT:
+ arg[pos].u.llongintval = va_arg (argp, long long int);
+ break;
+
+ case TYPE_ULLONGINT:
+ arg[pos].u.ullongintval = va_arg (argp, unsigned long long int);
+ break;
+
+ case TYPE_HWINT:
+ arg[pos].u.hwintval = va_arg (argp, HOST_WIDE_INT);
+ break;
+
+ case TYPE_HWUINT:
+ arg[pos].u.hwuintval = va_arg (argp, unsigned HOST_WIDE_INT);
+ break;
+
case TYPE_CHAR:
arg[pos].u.charval = (char) va_arg (argp, int);
break;
case 'l':
format++;
+ if (*format == 'l')
+ {
+ format++;
+ if (*format == 'u')
+ error_uinteger (spec[n++].u.ullongintval);
+ else
+ error_integer (spec[n++].u.llongintval);
+ }
if (*format == 'u')
error_uinteger (spec[n++].u.ulongintval);
else
error_integer (spec[n++].u.longintval);
break;
+ case 'w':
+ format++;
+ if (*format == 'u')
+ error_hwuint (spec[n++].u.hwintval);
+ else
+ error_hwint (spec[n++].u.hwuintval);
+ break;
}
}