aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-format.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-family/c-format.c')
-rw-r--r--gcc/c-family/c-format.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 92bb7edfa3d..c64d50f449b 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -142,6 +142,11 @@ location_from_offset (location_t loc, int offset)
return linemap_position_for_loc_and_offset (line_table, loc, column);
}
+/* Mark the tree and ttype nodes so we can compare for equality when checking
+ for type compatibility. the langhooks type_compatible_p() routine will
+ not consider a derived class to be the same. */
+static ttype *tree_ptr_node = NULL;
+static ttype *ttype_ptr_node = NULL;
/* Check that we have a pointer to a string suitable for use as a format.
The default is to check for a char type.
For objective-c dialects, this is extended to include references to string
@@ -2568,6 +2573,11 @@ check_format_types (location_t loc, format_wanted_type *types)
/* Check the type of the "real" argument, if there's a type we want. */
if (lang_hooks.types_compatible_p (wanted_type, cur_type))
continue;
+ /* ttype is derived from tree, but types_compatible_p wont match derived
+ types... so manually check for ttype passed to a tree. */
+ if (cur_type == ttype_ptr_node && wanted_type == tree_ptr_node
+ && tree_ptr_node && ttype_ptr_node)
+ continue;
/* If we want 'void *', allow any pointer type.
(Anything else would already have got a warning.)
With -Wpedantic, only allow pointers to void and to character
@@ -2859,17 +2869,20 @@ init_dynamic_gfc_info (void)
static void
init_dynamic_diag_info (void)
{
- static ttype *t, *loc, *hwi;
+ static ttype *loc, *hwi;
tree x;
- if (!loc || !t || !hwi)
+ if (!loc || !hwi || !tree_ptr_node || !ttype_ptr_node)
{
static format_char_info *diag_fci, *tdiag_fci, *cdiag_fci, *cxxdiag_fci;
static format_length_info *diag_ls;
unsigned int i;
- loc = t = hwi = 0;
+ loc = hwi = NULL;
+ tree_ptr_node = NULL;
+ ttype_ptr_node = NULL;
+
/* For the GCC-diagnostics custom format specifiers to work, one
must have declared 'tree' and/or 'location_t' prior to using
those attributes. If we haven't seen these declarations then
@@ -2900,10 +2913,24 @@ init_dynamic_diag_info (void)
else if (TREE_CODE (TREE_TYPE (x)) != POINTER_TYPE)
error ("%<tree%> is not defined as a pointer type");
else
- t = TREE_TTYPE (TREE_TYPE (x));
+ tree_ptr_node = TREE_TTYPE (TREE_TYPE (x));
}
}
+ /* Set the ttype pointer node. */
+ if ((x = maybe_get_identifier ("ttype")))
+ {
+ x = identifier_global_value (x);
+ if (x)
+ {
+ if (TREE_CODE (x) != TYPE_DECL)
+ error ("%<ttype%> is not defined as a type");
+ else
+ ttype_ptr_node = TREE_TTYPE (x);
+ }
+ }
+
+
/* 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
@@ -2961,10 +2988,10 @@ init_dynamic_diag_info (void)
xmemdup (gcc_diag_char_table,
sizeof (gcc_diag_char_table),
sizeof (gcc_diag_char_table));
- if (t)
+ if (tree_ptr_node)
{
i = find_char_info_specifier_index (diag_fci, 'K');
- diag_fci[i].types[0].type = &t;
+ diag_fci[i].types[0].type = &tree_ptr_node;
diag_fci[i].pointer_count = 1;
}
@@ -2975,14 +3002,14 @@ init_dynamic_diag_info (void)
xmemdup (gcc_tdiag_char_table,
sizeof (gcc_tdiag_char_table),
sizeof (gcc_tdiag_char_table));
- if (t)
+ if (tree_ptr_node)
{
/* All specifiers taking a tree share the same struct. */
i = find_char_info_specifier_index (tdiag_fci, 'D');
- tdiag_fci[i].types[0].type = &t;
+ tdiag_fci[i].types[0].type = &tree_ptr_node;
tdiag_fci[i].pointer_count = 1;
i = find_char_info_specifier_index (tdiag_fci, 'K');
- tdiag_fci[i].types[0].type = &t;
+ tdiag_fci[i].types[0].type = &tree_ptr_node;
tdiag_fci[i].pointer_count = 1;
}
@@ -2993,14 +3020,14 @@ init_dynamic_diag_info (void)
xmemdup (gcc_cdiag_char_table,
sizeof (gcc_cdiag_char_table),
sizeof (gcc_cdiag_char_table));
- if (t)
+ if (tree_ptr_node)
{
/* All specifiers taking a tree share the same struct. */
i = find_char_info_specifier_index (cdiag_fci, 'D');
- cdiag_fci[i].types[0].type = &t;
+ cdiag_fci[i].types[0].type = &tree_ptr_node;
cdiag_fci[i].pointer_count = 1;
i = find_char_info_specifier_index (cdiag_fci, 'K');
- cdiag_fci[i].types[0].type = &t;
+ cdiag_fci[i].types[0].type = &tree_ptr_node;
cdiag_fci[i].pointer_count = 1;
}
@@ -3011,14 +3038,14 @@ init_dynamic_diag_info (void)
xmemdup (gcc_cxxdiag_char_table,
sizeof (gcc_cxxdiag_char_table),
sizeof (gcc_cxxdiag_char_table));
- if (t)
+ if (tree_ptr_node)
{
/* All specifiers taking a tree share the same struct. */
i = find_char_info_specifier_index (cxxdiag_fci, 'D');
- cxxdiag_fci[i].types[0].type = &t;
+ cxxdiag_fci[i].types[0].type = &tree_ptr_node;
cxxdiag_fci[i].pointer_count = 1;
i = find_char_info_specifier_index (cxxdiag_fci, 'K');
- cxxdiag_fci[i].types[0].type = &t;
+ cxxdiag_fci[i].types[0].type = &tree_ptr_node;
cxxdiag_fci[i].pointer_count = 1;
}
}