return pp_formatted_text (&pp);
}
-/* Detect and diagnose a mismatch between an attribute access specification
- on the original declaration of FNDECL and that on the parameters NEWPARMS
- from its redeclaration. ORIGLOC is the location of the first declaration
- (FNDECL's is set to the location of the redeclaration). */
+/* Helper for warn_parms_array_mismatch. Compare the mappings of
+ two function parameters and diagnose mismatches. ORIGLOC is the
+ location of the first function declaration. CURP and NEWP are the
+ parameters in the first and second function declarators,
+ respectively. PARMPOS is the position of the parameters within the
+ list of parameter declarations. BUILTIN is true if the function is
+ a builtin. */
-void
-warn_parms_array_mismatch (location_t origloc, tree fndecl, tree newparms)
+static void
+warn_parm_array_mismatch (location_t origloc, rdwr_map *cur_idx,
+ rdwr_map *new_idx, tree curp, tree newp,
+ unsigned parmpos, bool builtin)
{
- /* The original parameter list (copied from the original declaration
- into the current [re]declaration, FNDECL)). The two are equal if
- and only if FNDECL is the first declaration. */
- tree curparms = DECL_ARGUMENTS (fndecl);
- if (!curparms || !newparms || curparms == newparms)
- return;
+ /* Create an empty access specification and use it for pointers with
+ no spec of their own. */
+ attr_access ptr_spec = { };
- if (TREE_CODE (curparms) != PARM_DECL
- || TREE_CODE (newparms) != PARM_DECL)
+ /* Only check pointers and C++ references. */
+ tree curptype = TREE_TYPE (curp);
+ tree newptype = TREE_TYPE (newp);
+ if (!POINTER_TYPE_P (curptype) || !POINTER_TYPE_P (newptype))
return;
- /* Extract the (possibly empty) attribute access specification from
- the declaration and its type (it doesn't yet reflect those created
- in response to NEWPARMS). */
- rdwr_map cur_idx;
- tree fntype = TREE_TYPE (fndecl);
- init_attr_rdwr_indices (&cur_idx, TYPE_ATTRIBUTES (fntype));
- /* Build a (possibly null) chain of access attributes corresponding
- to NEWPARMS. */
- const bool builtin = fndecl_built_in_p (fndecl);
- tree newattrs = build_attr_access_from_parms (newparms, builtin);
+ /* Skip mismatches in __builtin_va_list that is commonly
+ an array but that in declarations of built-ins decays
+ to a pointer. */
+ if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node))
+ return;
- /* Extract the (possibly empty) attribute access specification from
- NEWATTRS. */
- rdwr_map new_idx;
- init_attr_rdwr_indices (&new_idx, newattrs);
+ /* Access specs for the argument on the current (previous) and
+ new (to replace the current) declarations. Either may be null,
+ indicating the parameter is an ordinary pointer with no size
+ associated with it. */
+ attr_access *cura = cur_idx->get (parmpos);
+ attr_access *newa = new_idx->get (parmpos);
- if (cur_idx.is_empty () && new_idx.is_empty ())
+ if (!newa)
{
- /* If both specs are empty check pointers to VLAs for mismatches. */
- warn_parm_ptrarray_mismatch (origloc, curparms, newparms);
- return;
- }
- /* ...otherwise, if at least one spec isn't empty there may be mismatches,
- such as between f(T*) and f(T[1]), where the former mapping would be
- empty. */
+ /* Continue if both parameters are pointers with no size
+ associated with them. */
+ if (!cura)
+ return;
- /* Iterate over the two lists of function parameters, comparing their
- respective mappings and diagnosing mismatches. */
- unsigned parmpos = 0;
- for (tree curp = curparms, newp = newparms; curp;
- curp = TREE_CHAIN (curp), newp = TREE_CHAIN (newp), ++parmpos)
+ /* Otherwise point at PTR_SPEC and set its parameter pointer
+ and number. */
+ newa = &ptr_spec;
+ newa->ptr = newp;
+ newa->ptrarg = parmpos;
+ }
+ else if (!cura)
{
- if (!newp)
- /* Bail on invalid redeclarations with fewer arguments. */
- return;
+ cura = &ptr_spec;
+ cura->ptr = curp;
+ cura->ptrarg = parmpos;
+ }
- /* Create an empty access specification and use it for pointers with
- no spec of their own. */
- attr_access ptr_spec = { };
+ /* Set if the parameter is [re]declared as a VLA. */
+ const bool cur_vla_p = cura->size || cura->minsize == HOST_WIDE_INT_M1U;
+ const bool new_vla_p = newa->size || newa->minsize == HOST_WIDE_INT_M1U;
- /* Only check pointers and C++ references. */
- tree curptype = TREE_TYPE (curp);
- tree newptype = TREE_TYPE (newp);
- if (!POINTER_TYPE_P (curptype) || !POINTER_TYPE_P (newptype))
- continue;
+ if (DECL_P (curp))
+ origloc = DECL_SOURCE_LOCATION (curp);
+ else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp))
+ origloc = EXPR_LOCATION (curp);
- /* Skip mismatches in __builtin_va_list that is commonly
- an array but that in declarations of built-ins decays
- to a pointer. */
- if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node))
- continue;
+ /* The location of the parameter in the current redeclaration. */
+ location_t newloc = DECL_SOURCE_LOCATION (newp);
+ if (origloc == UNKNOWN_LOCATION)
+ origloc = newloc;
- /* Access specs for the argument on the current (previous) and
- new (to replace the current) declarations. Either may be null,
- indicating the parameter is an ordinary pointer with no size
- associated with it. */
- attr_access *cura = cur_idx.get (parmpos);
- attr_access *newa = new_idx.get (parmpos);
+ const std::string newparmstr = newa->array_as_string (newptype);
+ const std::string curparmstr = cura->array_as_string (curptype);
+ if (new_vla_p && !cur_vla_p)
+ {
+ if (warning_at (newloc, OPT_Wvla_parameter,
+ "argument %u of type %s "
+ "declared as a variable length array",
+ parmpos + 1, newparmstr.c_str ()))
+ inform (origloc,
+ (cura == &ptr_spec
+ ? G_("previously declared as a pointer %s")
+ : G_("previously declared as an ordinary array %s")),
+ curparmstr.c_str ());
+ return;
+ }
- if (!newa)
+ if (newa == &ptr_spec)
+ {
+ /* The new declaration uses the pointer form. Detect mismatches
+ between the pointer and a previous array or VLA forms. */
+ if (cura->minsize == HOST_WIDE_INT_M1U)
{
- /* Continue if both parameters are pointers with no size
- associated with them. */
- if (!cura)
- continue;
-
- /* Otherwise point at PTR_SPEC and set its parameter pointer
- and number. */
- newa = &ptr_spec;
- newa->ptr = newp;
- newa->ptrarg = parmpos;
+ /* Diagnose a pointer/VLA mismatch. */
+ if (warning_at (newloc, OPT_Wvla_parameter,
+ "argument %u of type %s declared as a pointer",
+ parmpos + 1, newparmstr.c_str ()))
+ inform (origloc,
+ "previously declared as a variable length array %s",
+ curparmstr.c_str ());
+ return;
}
- else if (!cura)
+
+ if (cura->minsize && cura->minsize != HOST_WIDE_INT_M1U)
{
- cura = &ptr_spec;
- cura->ptr = curp;
- cura->ptrarg = parmpos;
+ /* Diagnose mismatches between arrays with a constant
+ bound and pointers. */
+ if (warning_at (newloc, OPT_Warray_parameter_,
+ "argument %u of type %s declared as a pointer",
+ parmpos + 1, newparmstr.c_str ()))
+ inform (origloc, "previously declared as an array %s",
+ curparmstr.c_str ());
+ return;
}
+ }
- /* Set if the parameter is [re]declared as a VLA. */
- const bool cur_vla_p = cura->size || cura->minsize == HOST_WIDE_INT_M1U;
- const bool new_vla_p = newa->size || newa->minsize == HOST_WIDE_INT_M1U;
+ if (!new_vla_p && cur_vla_p)
+ {
+ if (warning_at (newloc, OPT_Wvla_parameter,
+ "argument %u of type %s declared as an ordinary array",
+ parmpos + 1, newparmstr.c_str ()))
+ inform (origloc, "previously declared as a variable length array %s",
+ curparmstr.c_str ());
+ return;
+ }
- if (DECL_P (curp))
- origloc = DECL_SOURCE_LOCATION (curp);
- else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp))
- origloc = EXPR_LOCATION (curp);
+ /* Move on to the next pair of parameters if both of the current
+ pair are VLAs with a single variable bound that refers to
+ a parameter at the same position. */
+ if (newa->size && cura->size
+ && newa->sizarg != UINT_MAX
+ && newa->sizarg == cura->sizarg
+ && newa->minsize == cura->minsize
+ && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size))
+ return;
- /* The location of the parameter in the current redeclaration. */
- location_t newloc = DECL_SOURCE_LOCATION (newp);
- if (origloc == UNKNOWN_LOCATION)
- origloc = newloc;
+ if (newa->size || cura->size)
+ {
+ unsigned newunspec, curunspec;
+ unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec;
+ unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec;
- const std::string newparmstr = newa->array_as_string (newptype);
- const std::string curparmstr = cura->array_as_string (curptype);
- if (new_vla_p && !cur_vla_p)
+ if (newbnds != curbnds)
{
- if (warning_at (newloc, OPT_Wvla_parameter,
- "argument %u of type %s declared as "
- "a variable length array",
- parmpos + 1, newparmstr.c_str ()))
- inform (origloc,
- (cura == &ptr_spec
- ? G_("previously declared as a pointer %s")
- : G_("previously declared as an ordinary array %s")),
- curparmstr.c_str ());
- continue;
+ if (warning_n (newloc, OPT_Wvla_parameter, newbnds,
+ "argument %u of type %s declared with "
+ "%u variable bound",
+ "argument %u of type %s declared with "
+ "%u variable bounds",
+ parmpos + 1, newparmstr.c_str (),
+ newbnds))
+ inform_n (origloc, curbnds,
+ "previously declared as %s with %u variable bound",
+ "previously declared as %s with %u variable bounds",
+ curparmstr.c_str (), curbnds);
+ return;
}
- if (newa == &ptr_spec)
+ if (newunspec > curunspec)
{
- /* The new declaration uses the pointer form. Detect mismatches
- between the pointer and a previous array or VLA forms. */
- if (cura->minsize == HOST_WIDE_INT_M1U)
- {
- /* Diagnose a pointer/VLA mismatch. */
- if (warning_at (newloc, OPT_Wvla_parameter,
- "argument %u of type %s declared "
- "as a pointer",
- parmpos + 1, newparmstr.c_str ()))
- inform (origloc,
- "previously declared as a variable length array %s",
- curparmstr.c_str ());
- continue;
- }
-
- if (cura->minsize && cura->minsize != HOST_WIDE_INT_M1U)
+ location_t warnloc = newloc, noteloc = origloc;
+ const char *warnparmstr = newparmstr.c_str ();
+ const char *noteparmstr = curparmstr.c_str ();
+ unsigned warnunspec = newunspec, noteunspec = curunspec;
+
+ if (warning_n (warnloc, OPT_Wvla_parameter, warnunspec,
+ "argument %u of type %s declared with "
+ "%u unspecified variable bound",
+ "argument %u of type %s declared with "
+ "%u unspecified variable bounds",
+ parmpos + 1, warnparmstr, warnunspec))
{
- /* Diagnose mismatches between arrays with a constant
- bound and pointers. */
- if (warning_at (newloc, OPT_Warray_parameter_,
- "argument %u of type %s declared "
- "as a pointer",
- parmpos + 1, newparmstr.c_str ()))
- inform (origloc, "previously declared as an array %s",
- curparmstr.c_str ());
- continue;
+ if (warnloc == newloc)
+ inform_n (noteloc, noteunspec,
+ "previously declared as %s with "
+ "%u unspecified variable bound",
+ "previously declared as %s with "
+ "%u unspecified variable bounds",
+ noteparmstr, noteunspec);
+ else
+ inform_n (noteloc, noteunspec,
+ "subsequently declared as %s with "
+ "%u unspecified variable bound",
+ "subsequently declared as %s with "
+ "%u unspecified variable bounds",
+ noteparmstr, noteunspec);
}
+ return;
}
+ }
- if (!new_vla_p && cur_vla_p)
- {
- if (warning_at (newloc, OPT_Wvla_parameter,
- "argument %u of type %s declared "
- "as an ordinary array",
- parmpos + 1, newparmstr.c_str ()))
- inform (origloc,
- "previously declared as a variable length array %s",
- curparmstr.c_str ());
- continue;
- }
+ /* Iterate over the lists of VLA variable bounds, comparing each
+ pair for equality, and diagnosing mismatches. */
+ for (tree newvbl = newa->size, curvbl = cura->size; newvbl && curvbl;
+ newvbl = TREE_CHAIN (newvbl), curvbl = TREE_CHAIN (curvbl))
+ {
+ tree newpos = TREE_PURPOSE (newvbl);
+ tree curpos = TREE_PURPOSE (curvbl);
+
+ tree newbnd = vla_bound_parm_decl (TREE_VALUE (newvbl));
+ tree curbnd = vla_bound_parm_decl (TREE_VALUE (curvbl));
- /* Move on to the next pair of parameters if both of the current
- pair are VLAs with a single variable bound that refers to
- a parameter at the same position. */
- if (newa->size && cura->size
- && newa->sizarg != UINT_MAX
- && newa->sizarg == cura->sizarg
- && newa->minsize == cura->minsize
- && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size))
+ if (newpos == curpos && newbnd == curbnd)
+ /* In the expected case when both bounds either refer to
+ the same positional parameter or when neither does,
+ and both are the same expression they are necessarily
+ the same. */
continue;
- if (newa->size || cura->size)
- {
- unsigned newunspec, curunspec;
- unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec;
- unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec;
+ pretty_printer pp1, pp2;
+ const char* const newbndstr = expr_to_str (pp1, newbnd, "*");
+ const char* const curbndstr = expr_to_str (pp2, curbnd, "*");
- if (newbnds != curbnds)
+ if (!newpos != !curpos
+ || (newpos && !tree_int_cst_equal (newpos, curpos)))
+ {
+ /* Diagnose a mismatch between a specified VLA bound and
+ an unspecified one. This can only happen in the most
+ significant bound.
+
+ Distinguish between the common case of bounds that are
+ other function parameters such as in
+ f (int n, int[n]);
+ and others. */
+
+ gcc_rich_location richloc (newloc);
+ bool warned;
+ if (newpos)
{
- if (warning_n (newloc, OPT_Wvla_parameter, newbnds,
- "argument %u of type %s declared with "
- "%u variable bound",
- "argument %u of type %s declared with "
- "%u variable bounds",
- parmpos + 1, newparmstr.c_str (),
- newbnds))
- inform_n (origloc, curbnds,
- "previously declared as %s with %u variable bound",
- "previously declared as %s with %u variable bounds",
- curparmstr.c_str (), curbnds);
- continue;
+ /* Also underline the VLA bound argument. */
+ richloc.add_range (DECL_SOURCE_LOCATION (newbnd));
+ warned = warning_at (&richloc, OPT_Wvla_parameter,
+ "argument %u of type %s "
+ "declared with mismatched bound argument %E",
+ parmpos + 1, newparmstr.c_str (),
+ plus_one (newpos));
}
+ else
+ warned = warning_at (&richloc, OPT_Wvla_parameter,
+ "argument %u of type %s "
+ "declared with mismatched bound %qs",
+ parmpos + 1, newparmstr.c_str (),
+ newbndstr);
- if (newunspec > curunspec)
+ if (warned)
{
- location_t warnloc = newloc, noteloc = origloc;
- const char *warnparmstr = newparmstr.c_str ();
- const char *noteparmstr = curparmstr.c_str ();
- unsigned warnunspec = newunspec, noteunspec = curunspec;
-
- if (warning_n (warnloc, OPT_Wvla_parameter, warnunspec,
- "argument %u of type %s declared with "
- "%u unspecified variable bound",
- "argument %u of type %s declared with "
- "%u unspecified variable bounds",
- parmpos + 1, warnparmstr, warnunspec))
+ gcc_rich_location richloc (origloc);
+ if (curpos)
{
- if (warnloc == newloc)
- inform_n (noteloc, noteunspec,
- "previously declared as %s with %u unspecified "
- "variable bound",
- "previously declared as %s with %u unspecified "
- "variable bounds",
- noteparmstr, noteunspec);
- else
- inform_n (noteloc, noteunspec,
- "subsequently declared as %s with %u unspecified "
- "variable bound",
- "subsequently declared as %s with %u unspecified "
- "variable bounds",
- noteparmstr, noteunspec);
+ /* Also underline the VLA bound argument. */
+ richloc.add_range (DECL_SOURCE_LOCATION (curbnd));
+ inform (&richloc,
+ "previously declared as %s with bound argument %E",
+ curparmstr.c_str (), plus_one (curpos));
}
+ else
+ inform (&richloc,
+ "previously declared as %s with bound %qs",
+ curparmstr.c_str (), curbndstr);
+
continue;
}
}
- /* Iterate over the lists of VLA variable bounds, comparing each
- pair for equality, and diagnosing mismatches. */
- for (tree newvbl = newa->size, curvbl = cura->size; newvbl && curvbl;
- newvbl = TREE_CHAIN (newvbl), curvbl = TREE_CHAIN (curvbl))
+ if (!newpos && newbnd && curbnd)
{
- tree newpos = TREE_PURPOSE (newvbl);
- tree curpos = TREE_PURPOSE (curvbl);
+ /* The VLA bounds don't refer to other function parameters.
+ Compare them lexicographically to detect gross mismatches
+ such as between T[foo()] and T[bar()]. */
+ if (operand_equal_p (newbnd, curbnd,
+ OEP_DECL_NAME | OEP_LEXICOGRAPHIC))
+ continue;
- tree newbnd = vla_bound_parm_decl (TREE_VALUE (newvbl));
- tree curbnd = vla_bound_parm_decl (TREE_VALUE (curvbl));
+ if (warning_at (newloc, OPT_Wvla_parameter,
+ "argument %u of type %s "
+ "declared with mismatched bound %qs",
+ parmpos + 1, newparmstr.c_str (), newbndstr))
+ inform (origloc, "previously declared as %s with bound %qs",
+ curparmstr.c_str (), curbndstr);
+ continue;
+ }
+ }
- if (newpos == curpos && newbnd == curbnd)
- /* In the expected case when both bounds either refer to
- the same positional parameter or when neither does,
- and both are the same expression they are necessarily
- the same. */
- continue;
+ if (newa->minsize == cura->minsize
+ || (((newa->minsize == 0 && newa->mode != access_deferred)
+ || (cura->minsize == 0 && cura->mode != access_deferred))
+ && newa != &ptr_spec
+ && cura != &ptr_spec))
+ return;
- pretty_printer pp1, pp2;
- const char* const newbndstr = expr_to_str (pp1, newbnd, "*");
- const char* const curbndstr = expr_to_str (pp2, curbnd, "*");
+ if (!newa->static_p && !cura->static_p && warn_array_parameter < 2)
+ /* Avoid warning about mismatches in ordinary (non-static) arrays
+ at levels below 2. */
+ return;
- if (!newpos != !curpos
- || (newpos && !tree_int_cst_equal (newpos, curpos)))
- {
- /* Diagnose a mismatch between a specified VLA bound and
- an unspecified one. This can only happen in the most
- significant bound.
-
- Distinguish between the common case of bounds that are
- other function parameters such as in
- f (int n, int[n]);
- and others. */
-
- gcc_rich_location richloc (newloc);
- bool warned;
- if (newpos)
- {
- /* Also underline the VLA bound argument. */
- richloc.add_range (DECL_SOURCE_LOCATION (newbnd));
- warned = warning_at (&richloc, OPT_Wvla_parameter,
- "argument %u of type %s declared "
- "with mismatched bound argument %E",
- parmpos + 1, newparmstr.c_str (),
- plus_one (newpos));
- }
- else
- warned = warning_at (&richloc, OPT_Wvla_parameter,
- "argument %u of type %s declared "
- "with mismatched bound %qs",
- parmpos + 1, newparmstr.c_str (),
- newbndstr);
+ if (warning_at (newloc, OPT_Warray_parameter_,
+ "argument %u of type %s with mismatched bound",
+ parmpos + 1, newparmstr.c_str ()))
+ inform (origloc, "previously declared as %s", curparmstr.c_str ());
+}
- if (warned)
- {
- gcc_rich_location richloc (origloc);
- if (curpos)
- {
- /* Also underline the VLA bound argument. */
- richloc.add_range (DECL_SOURCE_LOCATION (curbnd));
- inform (&richloc, "previously declared as %s with "
- "bound argument %E",
- curparmstr.c_str (), plus_one (curpos));
- }
- else
- inform (&richloc, "previously declared as %s with bound "
- "%qs", curparmstr.c_str (), curbndstr);
+/* Detect and diagnose a mismatch between an attribute access specification
+ on the original declaration of FNDECL and that on the parameters NEWPARMS
+ from its redeclaration. ORIGLOC is the location of the first declaration
+ (FNDECL's is set to the location of the redeclaration). */
- continue;
- }
- }
+void
+warn_parms_array_mismatch (location_t origloc, tree fndecl, tree newparms)
+{
+ /* The original parameter list (copied from the original declaration
+ into the current [re]declaration, FNDECL)). The two are equal if
+ and only if FNDECL is the first declaration. */
+ tree curparms = DECL_ARGUMENTS (fndecl);
+ if (!curparms || !newparms || curparms == newparms)
+ return;
- if (!newpos && newbnd && curbnd)
- {
- /* The VLA bounds don't refer to other function parameters.
- Compare them lexicographically to detect gross mismatches
- such as between T[foo()] and T[bar()]. */
- if (operand_equal_p (newbnd, curbnd,
- OEP_DECL_NAME | OEP_LEXICOGRAPHIC))
- continue;
-
- if (warning_at (newloc, OPT_Wvla_parameter,
- "argument %u of type %s declared with "
- "mismatched bound %qs",
- parmpos + 1, newparmstr.c_str (), newbndstr))
- inform (origloc, "previously declared as %s with bound %qs",
- curparmstr.c_str (), curbndstr);
- continue;
- }
- }
+ if (TREE_CODE (curparms) != PARM_DECL
+ || TREE_CODE (newparms) != PARM_DECL)
+ return;
+ /* Extract the (possibly empty) attribute access specification from
+ the declaration and its type (it doesn't yet reflect those created
+ in response to NEWPARMS). */
+ rdwr_map cur_idx;
+ tree fntype = TREE_TYPE (fndecl);
+ init_attr_rdwr_indices (&cur_idx, TYPE_ATTRIBUTES (fntype));
- if (newa->minsize == cura->minsize
- || (((newa->minsize == 0 && newa->mode != access_deferred)
- || (cura->minsize == 0 && cura->mode != access_deferred))
- && newa != &ptr_spec
- && cura != &ptr_spec))
- continue;
+ /* Build a (possibly null) chain of access attributes corresponding
+ to NEWPARMS. */
+ const bool builtin = fndecl_built_in_p (fndecl);
+ tree newattrs = build_attr_access_from_parms (newparms, builtin);
- if (!newa->static_p && !cura->static_p && warn_array_parameter < 2)
- /* Avoid warning about mismatches in ordinary (non-static) arrays
- at levels below 2. */
- continue;
+ /* Extract the (possibly empty) attribute access specification from
+ NEWATTRS. */
+ rdwr_map new_idx;
+ init_attr_rdwr_indices (&new_idx, newattrs);
- if (warning_at (newloc, OPT_Warray_parameter_,
- "argument %u of type %s with mismatched bound",
- parmpos + 1, newparmstr.c_str ()))
- inform (origloc, "previously declared as %s", curparmstr.c_str ());
+ if (cur_idx.is_empty () && new_idx.is_empty ())
+ {
+ /* If both specs are empty check pointers to VLAs for mismatches. */
+ warn_parm_ptrarray_mismatch (origloc, curparms, newparms);
+ return;
+ }
+ /* ...otherwise, if at least one spec isn't empty there may be mismatches,
+ such as between f(T*) and f(T[1]), where the former mapping would be
+ empty. */
+
+ /* Iterate over the two lists of function parameters, comparing their
+ respective mappings and diagnosing mismatches. */
+ unsigned parmpos = 0;
+ for (tree curp = curparms, newp = newparms; curp;
+ curp = TREE_CHAIN (curp), newp = TREE_CHAIN (newp), ++parmpos)
+ {
+ if (!newp)
+ /* Bail on invalid redeclarations with fewer arguments. */
+ return;
+
+ warn_parm_array_mismatch (origloc, &cur_idx, &new_idx, curp, newp, parmpos,
+ builtin);
}
}