diff options
Diffstat (limited to 'gcc/c-family/c-format.c')
-rw-r--r-- | gcc/c-family/c-format.c | 57 |
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; } } |