Replacing the arguments in the attribute list would lead to problems, because
when we're processing the constructor clone without the additional parameters,
the adjusted argument position would be out of whack at this point.
I've attempted to reduce the number of parameters, but it hardly seemed like
a win, here's the patch I came up with:
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 6e17847ec9e..972476fbdf4 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -594,7 +594,7 @@ attribute_takes_identifier_p (const_tree attr_id)
}
/* Verify that argument value POS at position ARGNO to attribute NAME
- applied to function TYPE refers to a function parameter at position
+ applied to function FNTYPE refers to a function parameter at position
POS and the expected type CODE. Treat CODE == INTEGER_TYPE as
matching all C integral types except bool. If successful, return
POS after default conversions, if any. Otherwise, issue appropriate
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 6f08b55d4a7..ffa36673ec0 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -6069,7 +6069,7 @@ check_function_arguments (location_t loc, const_tree
fndecl, const_tree fntype,
/* Check for errors in format strings. */
if (warn_format || warn_suggest_attribute_format)
- check_function_format (fntype, fndecl, TYPE_ATTRIBUTES (fntype), nargs,
+ check_function_format (fndecl, TYPE_ATTRIBUTES (fntype), nargs,
argarray, arglocs);
if (warn_format)
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index db6ff07db37..b68dc8f7d69 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -857,7 +857,7 @@ extern void check_function_arguments_recurse (void (*)
opt_code);
extern bool check_builtin_function_arguments (location_t, vec<location_t>,
tree, tree, int, tree *);
-extern void check_function_format (const_tree, const_tree, tree, int, tree *,
+extern void check_function_format (const_tree, tree, int, tree *,
vec<location_t> *);
extern bool attribute_fallthrough_p (tree);
extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index 87ae7bb73b0..6f0199dfcff 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -70,7 +70,7 @@ static GTY(()) tree local_gimple_ptr_node;
static GTY(()) tree local_cgraph_node_ptr_node;
static GTY(()) tree locus;
-static bool decode_format_attr (const_tree, const_tree, tree, tree,
+static bool decode_format_attr (const_tree, tree, tree,
function_format_info *, bool);
static format_type decode_format_type (const char *, bool * = NULL);
@@ -330,17 +330,19 @@ get_constant (const_tree fntype, const_tree atname, tree
expr, int argno,
return NULL_TREE;
}
-/* Decode the arguments to a "format" attribute into a
- function_format_info structure. It is already known that the list
- is of the right length. If VALIDATED_P is true, then these
- attributes have already been validated and must not be erroneous;
- if false, it will give an error message. Returns true if the
- attributes are successfully decoded, false otherwise. */
+/* Decode the arguments to a "format" attribute into a function_format_info
+ structure. It is already known that the list is of the right length. If
+ VALIDATED_P is true, then these attributes have already been validated and
+ must not be erroneous; if false, it will give an error message. FN is
+ either a FUNCTION_TYPE or a FUNCTION_DECL. Returns true if the attributes
+ are successfully decoded, false otherwise. */
static bool
-decode_format_attr (const_tree fntype, const_tree fndecl, tree atname,
- tree args, function_format_info *info, bool validated_p)
+decode_format_attr (const_tree fn, tree atname, tree args,
+ function_format_info *info, bool validated_p)
{
+ const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn;
+ const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn);
tree format_type_id = TREE_VALUE (args);
/* Note that TREE_VALUE (args) is changed in place below. Ditto
for the value of the next element on the list. */
@@ -1170,7 +1172,7 @@ decode_format_type (const char *s, bool *is_raw /* = NULL
*/)
attribute themselves. */
void
-check_function_format (const_tree fntype, const_tree fndecl, tree attrs,
+check_function_format (const_tree fndecl, tree attrs,
int nargs, tree *argarray, vec<location_t> *arglocs)
{
tree a;
@@ -1184,7 +1186,7 @@ check_function_format (const_tree fntype, const_tree
fndecl, tree attrs,
{
/* Yup; check it. */
function_format_info info;
- decode_format_attr (fntype, fndecl, atname, TREE_VALUE (a), &info,
+ decode_format_attr (fndecl, atname, TREE_VALUE (a), &info,
/*validated=*/true);
if (warn_format)
{
@@ -5190,7 +5192,7 @@ handle_format_attribute (tree node[3], tree atname, tree
args,
if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args));
- if (!decode_format_attr (type, fndecl, atname, args, &info,
+ if (!decode_format_attr (fndecl ? fndecl : type, atname, args, &info,
/* validated_p = */false))
{
*no_add_attrs = true;