From d14c547abd484d3540b692bb8048c4a6efe92c8b Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 28 Aug 2020 13:13:28 -0600 Subject: Add -Wstringop-overread for reading past the end by string functions. gcc/ChangeLog: * attribs.c (init_attr_rdwr_indices): Use global access_mode. * attribs.h (struct attr_access): Same. * builtins.c (fold_builtin_strlen): Add argument. (compute_objsize): Declare. (get_range): Declare. (check_read_access): New function. (access_ref::access_ref): Define ctor. (warn_string_no_nul): Add arguments. Handle -Wstrintop-overread. (check_nul_terminated_array): Handle source strings of different ranges of sizes. (expand_builtin_strlen): Remove warning code, call check_read_access instead. Declare locals closer to their initialization. (expand_builtin_strnlen): Same. (maybe_warn_for_bound): New function. (warn_for_access): Remove argument. Handle -Wstrintop-overread. (inform_access): Change argument type. (get_size_range): New function. (check_access): Remove unused arguments. Add new arguments. Handle -Wstrintop-overread. Move warning code to helpers and call them. Call check_nul_terminated_array. (check_memop_access): Remove unnecessary and provide additional arguments in calls. (expand_builtin_memchr): Call check_read_access. (expand_builtin_strcat): Remove unnecessary and provide additional arguments in calls. (expand_builtin_strcpy): Same. (expand_builtin_strcpy_args): Same. Avoid testing no-warning bit. (expand_builtin_stpcpy_1): Remove unnecessary and provide additional arguments in calls. (expand_builtin_stpncpy): Same. (check_strncat_sizes): Same. (expand_builtin_strncat): Remove unnecessary and provide additional arguments in calls. Adjust comments. (expand_builtin_strncpy): Remove unnecessary and provide additional arguments in calls. (expand_builtin_memcmp): Remove warning code. Call check_access. (expand_builtin_strcmp): Call check_access instead of check_nul_terminated_array. (expand_builtin_strncmp): Handle -Wstrintop-overread. (expand_builtin_fork_or_exec): Call check_access instead of check_nul_terminated_array. (expand_builtin): Same. (fold_builtin_1): Pass additional argument. (fold_builtin_n): Same. (fold_builtin_strpbrk): Remove calls to check_nul_terminated_array. (expand_builtin_memory_chk): Add comments. (maybe_emit_chk_warning): Remove unnecessary and provide additional arguments in calls. (maybe_emit_sprintf_chk_warning): Same. Adjust comments. * builtins.h (warn_string_no_nul): Add arguments. (struct access_ref): Add member and ctor argument. (struct access_data): Add members and ctor. (check_access): Adjust signature. * calls.c (maybe_warn_nonstring_arg): Return an indication of whether a warning was issued. Issue -Wstrintop-overread instead of -Wstringop-overflow. (append_attrname): Adjust to naming changes. (maybe_warn_rdwr_sizes): Same. Remove unnecessary and provide additional arguments in calls. * calls.h (maybe_warn_nonstring_arg): Return bool. * doc/invoke.texi (-Wstringop-overread): Document new option. * gimple-fold.c (gimple_fold_builtin_strcpy): Provide an additional argument in call. (gimple_fold_builtin_stpcpy): Same. * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Adjust to naming changes. * tree.h (enum access_mode): New type. gcc/c-family/ChangeLog: * c.opt (Wstringop-overread): New option. gcc/testsuite/ChangeLog: * c-c++-common/Warray-bounds-7.c: Adjust expected warnings. * c-c++-common/Wrestrict.c: Remove xfail. * c-c++-common/attr-nonstring-3.c: Adjust text of expected warnings. * c-c++-common/attr-nonstring-6.c: Suppress -Wstringop-overread instead of -Wstringop-overflow. * c-c++-common/attr-nonstring-8.c: Adjust text of expected warnings. * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Also suppress -Wstringop-overread. * g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same. * gcc.dg/Warray-bounds-39.c: Adjust expected warnings. * gcc.dg/Warray-bounds-40.c: Also suppress -Wstringop-overread. * gcc.dg/Warray-bounds-58.c: Remove xfail. Also expect -Wstringop-overread. Adjust text of expected warnings. * gcc.dg/Wsizeof-pointer-memaccess1.c: Also suppress -Wstringop-overread. * gcc.dg/Wstringop-overflow-22.c: Adjust text of expected warnings. * gcc.dg/Wstringop-overflow-33.c: Expect -Wstringop-overread. * gcc.dg/Wstringop-overflow-9.c: Expect -Wstringop-overread. * gcc.dg/attr-nonstring-2.c: Adjust text of expected warnings. * gcc.dg/attr-nonstring-3.c: Same. * gcc.dg/attr-nonstring-4.c: Same. * gcc.dg/attr-nonstring.c: Expect -Wstringop-overread. * gcc.dg/builtin-stringop-chk-5.c: Adjust comment. * gcc.dg/builtin-stringop-chk-8.c: Enable -Wstringop-overread instead of -Wstringop-overflow. * gcc.dg/pr78902.c: Also expect -Wstringop-overread. * gcc.dg/pr79214.c: Adjust text of expected warnings. * gcc.dg/strcmpopt_10.c: Suppress valid -Wno-stringop-overread. * gcc.dg/strlenopt-57.c: Also expect -Wstringop-overread. * gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Also suppress valid -Wno-stringop-overread. * gcc.dg/tree-ssa/builtins-folding-gimple-ub.c: Same. * gcc.dg/uninit-33.c: Same. * gcc.dg/warn-strnlen-no-nul-2.c: Adjust text of expected warning. * gcc.dg/warn-strnlen-no-nul.c: Same. * gcc.target/i386/strcmpopt_6.c: Suppress -Wstringop-overread. * gcc.dg/Wstringop-overread-2.c: New test. * gcc.dg/Wstringop-overread.c: New test. --- gcc/attribs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gcc/attribs.c') diff --git a/gcc/attribs.c b/gcc/attribs.c index 71dae12..7c0c18f 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -2045,10 +2045,10 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype) switch (*m) { - case 'r': acc.mode = acc.read_only; break; - case 'w': acc.mode = acc.write_only; break; - case 'x': acc.mode = acc.read_write; break; - case '-': acc.mode = acc.none; break; + case 'r': acc.mode = access_read_only; break; + case 'w': acc.mode = access_write_only; break; + case 'x': acc.mode = access_read_write; break; + case '-': acc.mode = access_none; break; default: gcc_unreachable (); } -- cgit v1.1 From 6450f07388f9fe575a489c9309c36012b17b88b0 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Sat, 19 Sep 2020 17:21:52 -0600 Subject: Infrastructure & C front end changes for array parameter checking (PR c/50584). gcc/ChangeLog: PR c/50584 * attribs.c (decl_attributes): Also pass decl along with type attributes to handlers. (init_attr_rdwr_indices): Change second argument to attribute chain. Handle internal attribute representation in addition to external. (get_parm_access): New function. (attr_access::to_internal_string): Define new member function. (attr_access::to_external_string): Define new member function. (attr_access::vla_bounds): Define new member function. * attribs.h (struct attr_access): Declare new members. (attr_access::from_mode_char): Define new member function. (get_parm_access): Declare new function. * calls.c (initialize_argument_information): Pass function type attributes to init_attr_rdwr_indices. * doc/invoke.texi (-Warray-parameter, -Wvla-parameter): Document. * tree-pretty-print.c (dump_generic_node): Correct handling of qualifiers. * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Same. * tree.h (access_mode): Add new enumerator. gcc/c-family/ChangeLog: PR c/50584 * c-attribs.c (c_common_attribute_table): Add "arg spec" attribute. (handle_argspec_attribute): New function. (get_argument, get_argument_type): New functions. (append_access_attrs): Add overload. Handle internal attribute representation in addition to external. (handle_access_attribute): Handle internal attribute representation in addition to external. (build_attr_access_from_parms): New function. gcc/c-family/ChangeLog: PR c/50584 * c-common.h (warn_parm_array_mismatch): Declare new function. (has_attribute): Move declaration of an existing function. (build_attr_access_from_parms): Declare new function. * c-warn.c (parm_array_as_string): Define new function. (plus_one): Define new function. (warn_parm_ptrarray_mismatch): Define new function. (warn_parm_array_mismatch): Define new function. (vla_bound_parm_decl): New function. * c.opt (-Warray-parameter, -Wvla-parameter): New options. * c-pretty-print.c (pp_c_type_qualifier_list): Don't print array type qualifiers here... (c_pretty_printer::direct_abstract_declarator): ...but instead print them in brackets here. Also print [static]. Strip extraneous expressions from VLA bounds. gcc/c/ChangeLog: PR c/50584 * c-decl.c (lookup_last_decl): Define new function. (c_decl_attributes): Call it. (start_decl): Add argument and use it. (finish_decl): Call build_attr_access_from_parms and decl_attributes. (get_parm_array_spec): Define new function. (push_parm_decl): Call get_parm_array_spec. (start_function): Call warn_parm_array_mismatch. Build attribute access and add it to current function. * c-parser.c (c_parser_declaration_or_fndef): Diagnose mismatches in forms of array parameters. * c-tree.h (start_decl): Add argument. gcc/testsuite/ChangeLog: PR c/50584 * gcc.dg/attr-access-read-write-2.c: Adjust text of expected message. * c-c++-common/Warray-bounds-6.c: Correct C++ declaration, adjust text of expected diagnostics. * gcc.dg/Wbuiltin-declaration-mismatch-9.c: Prune expected warning. * gcc.dg/Warray-parameter-2.c: New test. * gcc.dg/Warray-parameter-3.c: New test. * gcc.dg/Warray-parameter-4.c: New test. * gcc.dg/Warray-parameter-5.c: New test. * gcc.dg/Warray-parameter.c: New test. * gcc.dg/Wvla-parameter-2.c: New test. * gcc.dg/Wvla-parameter-3.c: New test. * gcc.dg/Wvla-parameter.c: New test. --- gcc/attribs.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 266 insertions(+), 27 deletions(-) (limited to 'gcc/attribs.c') diff --git a/gcc/attribs.c b/gcc/attribs.c index 7c0c18f..abc7536 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ +#define INCLUDE_STRING #include "config.h" #include "system.h" #include "coretypes.h" @@ -25,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "diagnostic-core.h" #include "attribs.h" +#include "fold-const.h" #include "stor-layout.h" #include "langhooks.h" #include "plugin.h" @@ -32,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "hash-set.h" #include "diagnostic.h" #include "pretty-print.h" +#include "tree-pretty-print.h" #include "intl.h" /* Table of the tables of attributes (common, language, format, machine) @@ -707,10 +710,16 @@ decl_attributes (tree *node, tree attributes, int flags, int cxx11_flag = (cxx11_attr_p ? ATTR_FLAG_CXX11 : 0); /* Pass in an array of the current declaration followed - by the last pushed/merged declaration if one exists. + by the last pushed/merged declaration if one exists. + For calls that modify the type attributes of a DECL + and for which *ANODE is *NODE's type, also pass in + the DECL as the third element to use in diagnostics. If the handler changes CUR_AND_LAST_DECL[0] replace *ANODE with its value. */ - tree cur_and_last_decl[] = { *anode, last_decl }; + tree cur_and_last_decl[3] = { *anode, last_decl }; + if (anode != node && DECL_P (*node)) + cur_and_last_decl[2] = *node; + tree ret = (spec->handler) (cur_and_last_decl, name, args, flags|cxx11_flag, &no_add_attrs); @@ -2017,65 +2026,295 @@ maybe_diag_alias_attributes (tree alias, tree target) } } -/* Initialize a mapping for a call to function FNDECL declared with - attribute access. Each attribute positional operand inserts one - entry into the mapping with the operand number as the key. */ +/* Initialize a mapping RWM for a call to a function declared with + attribute access in ATTRS. Each attribute positional operand + inserts one entry into the mapping with the operand number as + the key. */ void -init_attr_rdwr_indices (rdwr_map *rwm, tree fntype) +init_attr_rdwr_indices (rdwr_map *rwm, tree attrs) { - if (!fntype) + if (!attrs) return; - for (tree access = TYPE_ATTRIBUTES (fntype); + for (tree access = attrs; (access = lookup_attribute ("access", access)); access = TREE_CHAIN (access)) { /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE is the attribute argument's value. */ tree mode = TREE_VALUE (access); - gcc_assert (TREE_CODE (mode) == TREE_LIST); + if (!mode) + return; + + /* The (optional) list of VLA bounds. */ + tree vblist = TREE_CHAIN (mode); + mode = TREE_VALUE (mode); + if (TREE_CODE (mode) != STRING_CST) + continue; gcc_assert (TREE_CODE (mode) == STRING_CST); - const char *modestr = TREE_STRING_POINTER (mode); - for (const char *m = modestr; *m; ) + for (const char *m = TREE_STRING_POINTER (mode); *m; ) { attr_access acc = { }; - switch (*m) + /* Skip the internal-only plus sign. */ + if (*m == '+') + ++m; + + acc.str = m; + acc.mode = acc.from_mode_char (*m); + acc.sizarg = UINT_MAX; + + const char *end; + acc.ptrarg = strtoul (++m, const_cast(&end), 10); + m = end; + + if (*m == '[') { - case 'r': acc.mode = access_read_only; break; - case 'w': acc.mode = access_write_only; break; - case 'x': acc.mode = access_read_write; break; - case '-': acc.mode = access_none; break; - default: gcc_unreachable (); + /* Forms containing the square bracket are internal-only + (not specified by an attribute declaration), and used + for various forms of array and VLA parameters. */ + acc.internal_p = true; + + /* Search to the closing bracket and look at the preceding + code: it determines the form of the most significant + bound of the array. Others prior to it encode the form + of interior VLA bounds. They're not of interest here. */ + end = strchr (m, ']'); + const char *p = end; + gcc_assert (p); + + while (ISDIGIT (p[-1])) + --p; + + if (ISDIGIT (*p)) + { + /* A digit denotes a constant bound (as in T[3]). */ + acc.static_p = p[-1] == 's'; + acc.minsize = strtoull (p, NULL, 10); + } + else if (' ' == p[-1]) + { + /* A space denotes an ordinary array of unspecified bound + (as in T[]). */ + acc.minsize = 0; + } + else if ('*' == p[-1] || '$' == p[-1]) + { + /* An asterisk denotes a VLA. When the closing bracket + is followed by a comma and a dollar sign its bound is + on the list. Otherwise it's a VLA with an unspecified + bound. */ + acc.minsize = HOST_WIDE_INT_M1U; + } + + m = end + 1; } - char *end; - acc.ptrarg = strtoul (++m, &end, 10); - m = end; if (*m == ',') { - acc.sizarg = strtoul (++m, &end, 10); - m = end; + ++m; + do + { + if (*m == '$') + { + ++m; + if (!acc.size) + { + /* Extract the list of VLA bounds for the current + parameter, store it in ACC.SIZE, and advance + to the list of bounds for the next VLA parameter. + */ + acc.size = TREE_VALUE (vblist); + vblist = TREE_CHAIN (vblist); + } + } + + if (ISDIGIT (*m)) + { + /* Extract the positional argument. It's absent + for VLAs whose bound doesn't name a function + parameter. */ + unsigned pos = strtoul (m, const_cast(&end), 10); + if (acc.sizarg == UINT_MAX) + acc.sizarg = pos; + m = end; + } + } + while (*m == '$'); + } + + acc.end = m; + + bool existing; + auto &ref = rwm->get_or_insert (acc.ptrarg, &existing); + if (existing) + { + /* Merge the new spec with the existing. */ + if (acc.minsize == HOST_WIDE_INT_M1U) + ref.minsize = HOST_WIDE_INT_M1U; + + if (acc.sizarg != UINT_MAX) + ref.sizarg = acc.sizarg; + + if (acc.mode) + ref.mode = acc.mode; } else - acc.sizarg = UINT_MAX; - - acc.ptr = NULL_TREE; - acc.size = NULL_TREE; + ref = acc; /* Unconditionally add an entry for the required pointer operand of the attribute, and one for the optional size operand when it's specified. */ - rwm->put (acc.ptrarg, acc); if (acc.sizarg != UINT_MAX) rwm->put (acc.sizarg, acc); } } } +/* Return the access specification for a function parameter PARM + or null if the current function has no such specification. */ + +attr_access * +get_parm_access (rdwr_map &rdwr_idx, tree parm, + tree fndecl /* = current_function_decl */) +{ + tree fntype = TREE_TYPE (fndecl); + init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype)); + + if (rdwr_idx.is_empty ()) + return NULL; + + unsigned argpos = 0; + tree fnargs = DECL_ARGUMENTS (fndecl); + for (tree arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos) + if (arg == parm) + return rdwr_idx.get (argpos); + + return NULL; +} + +/* Return the internal representation as STRING_CST. Internal positional + arguments are zero-based. */ + +tree +attr_access::to_internal_string () const +{ + return build_string (end - str, str); +} + +/* Return the human-readable representation of the external attribute + specification (as it might appear in the source code) as STRING_CST. + External positional arguments are one-based. */ + +tree +attr_access::to_external_string () const +{ + char buf[80]; + gcc_assert (mode != access_deferred); + int len = snprintf (buf, sizeof buf, "access (%s, %u", + mode_names[mode], ptrarg + 1); + if (sizarg != UINT_MAX) + len += snprintf (buf + len, sizeof buf - len, ", %u", sizarg + 1); + strcpy (buf + len, ")"); + return build_string (len + 2, buf); +} + +/* Return the number of specified VLA bounds and set *nunspec to + the number of unspecified ones (those designated by [*]). */ + +unsigned +attr_access::vla_bounds (unsigned *nunspec) const +{ + *nunspec = 0; + for (const char* p = strrchr (str, ']'); p && *p != '['; --p) + if (*p == '*') + ++*nunspec; + return list_length (size); +} + + +/* Defined in attr_access. */ +constexpr char attr_access::mode_chars[]; +constexpr char attr_access::mode_names[][11]; + +/* Format an array, including a VLA, pointed to by TYPE and used as + a function parameter as a human-readable string. ACC describes + an access to the parameter and is used to determine the outermost + form of the array including its bound which is otherwise obviated + by its decay to pointer. Return the formatted string. */ + +std::string +attr_access::array_as_string (tree type) const +{ + std::string typstr; + + if (type == error_mark_node) + return std::string (); + + if (this->str) + { + /* For array parameters (but not pointers) create an array type + that corresponds to the form of the parameter including its + qualifiers even though they apply to the pointer, not the array + type. */ + const bool vla_p = minsize == HOST_WIDE_INT_M1U; + tree eltype = TREE_TYPE (type); + tree artype; + + tree index_type = NULL_TREE; + if (minsize == HOST_WIDE_INT_M1U) + { + /* Determine if this is a VLA (an array whose most significant + bound is nonconstant and whose access string has "$]" in it) + extract the bound expression from SIZE. */ + const char *p = end; + for ( ; *p-- != ']'; ); + if (*p == '$') + index_type = build_index_type (TREE_VALUE (size)); + } + else if (minsize) + index_type = build_index_type (size_int (minsize - 1)); + + artype = build_array_type (eltype, index_type); + + if (static_p || vla_p) + { + tree flag = static_p ? integer_one_node : NULL_TREE; + /* Hack: there's no language-independent way to encode + the "static" specifier or the "*" notation in an array type. + Temporarily add an attribute to have the pretty printer add + "static" or "*", and remove it later. The static notation + is only valid in the most significant bound but [*] can be + used for any bound. Because [*] is represented the same as + [0] this hack only works for the most significant bound like + static and the others are rendered as [0]. */ + tree at = tree_cons (get_identifier ("array"), flag, NULL_TREE); + TYPE_ATTRIBUTES (artype) = at; + } + + TYPE_ATOMIC (artype) = TYPE_ATOMIC (type); + TYPE_READONLY (artype) = TYPE_READONLY (type); + TYPE_RESTRICT (artype) = TYPE_RESTRICT (type); + TYPE_VOLATILE (artype) = TYPE_VOLATILE (type); + type = artype; + } + + /* Format the type using the current pretty printer. The generic tree + printer does a terrible job. */ + pretty_printer *pp = global_dc->printer->clone (); + pp_printf (pp, "%qT", type); + typstr = pp_formatted_text (pp); + delete pp; + + if (this->str) + /* Remove the attribute that wasn't installed by decl_attributes. */ + TYPE_ATTRIBUTES (type) = NULL_TREE; + + return typstr; +} #if CHECKING_P -- cgit v1.1 From e808f3fdfa8f31066da19011b55acb8c0446c72d Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 30 Sep 2020 09:31:29 -0600 Subject: PR c/97206 - ICE in composite_type on declarations of a similar array types gcc/ChangeLog: PR c/97206 * attribs.c (attr_access::array_as_string): Avoid modifying a shared type in place and use build_type_attribute_qual_variant instead. gcc/testsuite/ChangeLog: PR c/97206 * gcc.dg/Warray-parameter-7.c: New test. * gcc.dg/Warray-parameter-8.c: New test. * gcc.dg/Wvla-parameter-5.c: New test. --- gcc/attribs.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) (limited to 'gcc/attribs.c') diff --git a/gcc/attribs.c b/gcc/attribs.c index abc7536..3f6ec3d 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -2256,15 +2256,14 @@ attr_access::array_as_string (tree type) const if (this->str) { - /* For array parameters (but not pointers) create an array type - that corresponds to the form of the parameter including its + /* For array parameters (but not pointers) create a temporary array + type that corresponds to the form of the parameter including its qualifiers even though they apply to the pointer, not the array type. */ const bool vla_p = minsize == HOST_WIDE_INT_M1U; tree eltype = TREE_TYPE (type); - tree artype; - tree index_type = NULL_TREE; + if (minsize == HOST_WIDE_INT_M1U) { /* Determine if this is a VLA (an array whose most significant @@ -2278,28 +2277,24 @@ attr_access::array_as_string (tree type) const else if (minsize) index_type = build_index_type (size_int (minsize - 1)); - artype = build_array_type (eltype, index_type); - + tree arat = NULL_TREE; if (static_p || vla_p) { tree flag = static_p ? integer_one_node : NULL_TREE; /* Hack: there's no language-independent way to encode the "static" specifier or the "*" notation in an array type. - Temporarily add an attribute to have the pretty printer add - "static" or "*", and remove it later. The static notation - is only valid in the most significant bound but [*] can be - used for any bound. Because [*] is represented the same as - [0] this hack only works for the most significant bound like - static and the others are rendered as [0]. */ - tree at = tree_cons (get_identifier ("array"), flag, NULL_TREE); - TYPE_ATTRIBUTES (artype) = at; + Add a "fake" attribute to have the pretty-printer add "static" + or "*". The "[static N]" notation is only valid in the most + significant bound but [*] can be used for any bound. Because + [*] is represented the same as [0] this hack only works for + the most significant bound like static and the others are + rendered as [0]. */ + arat = build_tree_list (get_identifier ("array"), flag); } - TYPE_ATOMIC (artype) = TYPE_ATOMIC (type); - TYPE_READONLY (artype) = TYPE_READONLY (type); - TYPE_RESTRICT (artype) = TYPE_RESTRICT (type); - TYPE_VOLATILE (artype) = TYPE_VOLATILE (type); - type = artype; + const int quals = TYPE_QUALS (type); + type = build_array_type (eltype, index_type); + type = build_type_attribute_qual_variant (type, arat, quals); } /* Format the type using the current pretty printer. The generic tree @@ -2309,10 +2304,6 @@ attr_access::array_as_string (tree type) const typstr = pp_formatted_text (pp); delete pp; - if (this->str) - /* Remove the attribute that wasn't installed by decl_attributes. */ - TYPE_ATTRIBUTES (type) = NULL_TREE; - return typstr; } -- cgit v1.1 From 7dbc7ad524a540e34ce25d120d0968f36c571bbb Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 30 Sep 2020 12:58:09 -0600 Subject: Avoid assuming a VLA access specification string contains a closing bracket (PR middle-end/97189). Resolves: PR middle-end/97189 - ICE on redeclaration of a function with VLA argument and attribute access gcc/ChangeLog: PR middle-end/97189 * attribs.c (attr_access::array_as_string): Avoid assuming a VLA access specification string contains a closing bracket. gcc/c-family/ChangeLog: PR middle-end/97189 * c-attribs.c (append_access_attr): Use the function declaration location for a warning about an attribute access argument. gcc/testsuite/ChangeLog: PR middle-end/97189 * gcc.dg/attr-access-2.c: Adjust caret location. * gcc.dg/Wvla-parameter-6.c: New test. * gcc.dg/Wvla-parameter-7.c: New test. --- gcc/attribs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc/attribs.c') diff --git a/gcc/attribs.c b/gcc/attribs.c index 3f6ec3d..94b9e02 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -2270,11 +2270,11 @@ attr_access::array_as_string (tree type) const bound is nonconstant and whose access string has "$]" in it) extract the bound expression from SIZE. */ const char *p = end; - for ( ; *p-- != ']'; ); + for ( ; p != str && *p-- != ']'; ); if (*p == '$') index_type = build_index_type (TREE_VALUE (size)); } - else if (minsize) + else if (minsize) index_type = build_index_type (size_int (minsize - 1)); tree arat = NULL_TREE; -- cgit v1.1