On Sun, Oct 12, 2025 at 02:52:27PM +0200, Alejandro Colomar wrote: > Not sure about moving the definition of ptr_spec.
Oops, I should have removed that line. > > No functional change intended. > > gcc/c-family/ChangeLog: > > * c-warn.cc (warn_parms_array_mismatch): Split out body of > per-pair in parameter lists iteration into... > (warn_parm_array_mismatch): ...this new function. > > Signed-off-by: Alejandro Colomar <[email protected]> > --- > gcc/c-family/c-warn.cc | 582 +++++++++++++++++++++-------------------- > 1 file changed, 294 insertions(+), 288 deletions(-) > > diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc > index d50129f0396..ada7fad8d54 100644 > --- a/gcc/c-family/c-warn.cc > +++ b/gcc/c-family/c-warn.cc > @@ -3425,6 +3425,298 @@ expr_to_str (pretty_printer &pp, tree expr, const > char *dflt) > return pp_formatted_text (&pp); > } > > +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) > +{ > + /* Create an empty access specification and use it for pointers with > + no spec of their own. */ > + attr_access ptr_spec = { }; > + > + /* 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; > + > + /* 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; > + > + /* 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 (!newa) > + { > + /* Continue if both parameters are pointers with no size > + associated with them. */ > + if (!cura) > + return; > + > + /* Otherwise point at PTR_SPEC and set its parameter pointer > + and number. */ > + newa = &ptr_spec; > + newa->ptr = newp; > + newa->ptrarg = parmpos; > + } > + else if (!cura) > + { > + cura = &ptr_spec; > + cura->ptr = curp; > + cura->ptrarg = parmpos; > + } > + > + /* 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 (DECL_P (curp)) > + origloc = DECL_SOURCE_LOCATION (curp); > + else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp)) > + origloc = EXPR_LOCATION (curp); > + > + /* The location of the parameter in the current redeclaration. */ > + location_t newloc = DECL_SOURCE_LOCATION (newp); > + if (origloc == UNKNOWN_LOCATION) > + origloc = newloc; > + > + 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 == &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) > + { > + /* 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; > + } > + > + if (cura->minsize && cura->minsize != HOST_WIDE_INT_M1U) > + { > + /* 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; > + } > + } > + > + 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; > + } > + > + /* 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; > + > + if (newa->size || cura->size) > + { > + unsigned newunspec, curunspec; > + unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec; > + unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec; > + > + if (newbnds != curbnds) > + { > + 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 (newunspec > curunspec) > + { > + 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)) > + { > + 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; > + } > + } > + > + /* 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)); > + > + 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; > + > + pretty_printer pp1, pp2; > + const char* const newbndstr = expr_to_str (pp1, newbnd, "*"); > + const char* const curbndstr = expr_to_str (pp2, curbnd, "*"); > + > + 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 (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); > + > + continue; > + } > + } > + > + 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 (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; > + > + 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 (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 ()); > +} > + > /* 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 > @@ -3480,294 +3772,8 @@ warn_parms_array_mismatch (location_t origloc, tree > fndecl, tree newparms) > /* Bail on invalid redeclarations with fewer arguments. */ > return; > > - /* Create an empty access specification and use it for pointers with > - no spec of their own. */ > - attr_access ptr_spec = { }; > - > - /* 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; > - > - /* 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; > - > - /* 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 (!newa) > - { > - /* 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; > - } > - else if (!cura) > - { > - cura = &ptr_spec; > - cura->ptr = curp; > - cura->ptrarg = parmpos; > - } > - > - /* 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 (DECL_P (curp)) > - origloc = DECL_SOURCE_LOCATION (curp); > - else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp)) > - origloc = EXPR_LOCATION (curp); > - > - /* The location of the parameter in the current redeclaration. */ > - location_t newloc = DECL_SOURCE_LOCATION (newp); > - if (origloc == UNKNOWN_LOCATION) > - origloc = newloc; > - > - 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 ()); > - continue; > - } > - > - 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) > - { > - /* 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) > - { > - /* 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 (!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; > - } > - > - /* 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)) > - continue; > - > - if (newa->size || cura->size) > - { > - unsigned newunspec, curunspec; > - unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec; > - unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec; > - > - if (newbnds != curbnds) > - { > - 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; > - } > - > - if (newunspec > curunspec) > - { > - 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)) > - { > - 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); > - } > - 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)); > - > - 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; > - > - pretty_printer pp1, pp2; > - const char* const newbndstr = expr_to_str (pp1, newbnd, "*"); > - const char* const curbndstr = expr_to_str (pp2, curbnd, "*"); > - > - 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 (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); > - > - continue; > - } > - } > - > - 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 (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; > - > - 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; > - > - 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 ()); > + warn_parm_array_mismatch (origloc, &cur_idx, &new_idx, curp, newp, > parmpos, > + builtin); > } > } > > -- > 2.51.0 > -- <https://www.alejandro-colomar.es> Use port 80 (that is, <...:80/>).
signature.asc
Description: PGP signature
