Redeclaring a function that takes a VLA parameter with attribute access that references the same parameter can cause conflicts when the two aren't in sync. The conflicts are detected and diagnosed but also have to be resolved. The code wasn't robust enough to handle all cases gracefully, leading to the ICE reported in the PR. After testing on x86_64-linux I have committed in r11-3571 the attached fix to improve it and avoid the ICE.
Martin
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. diff --git a/gcc/attribs.c b/gcc/attribs.c index 3f6ec3d3aa3..94b9e02699f 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; diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 70b00037d98..c779d13f023 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -4151,18 +4151,12 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr, "missing in previous designation", attrstr); else if (newa->internal_p || cura->internal_p) - { - /* Mismatch in the value of the size argument and a VLA - bound. */ - location_t argloc = curloc; - if (tree arg = get_argument (node[2], newa->sizarg)) - argloc = DECL_SOURCE_LOCATION (arg); - warned = warning_at (argloc, OPT_Wattributes, - "attribute %qs positional argument 2 " - "conflicts with previous designation " - "by argument %u", - attrstr, cura->sizarg + 1); - } + /* Mismatch in the value of the size argument and a VLA bound. */ + warned = warning_at (curloc, OPT_Wattributes, + "attribute %qs positional argument 2 " + "conflicts with previous designation " + "by argument %u", + attrstr, cura->sizarg + 1); else /* Mismatch in the value of the size argument between two explicit access attributes. */ diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-6.c b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c new file mode 100644 index 00000000000..268aeec9251 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-6.c @@ -0,0 +1,34 @@ +/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument + and attribute access + Also verify the right arguments are underlined in the notes. + { dg-do compile } + { dg-options "-Wall -fdiagnostics-show-caret" } */ + +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) + +RW (2, 3) void f1 (int n, int[n], int); +/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2, 3) void f1 (int n, int[n], int); + ^~ + { dg-end-multiline-output "" } + { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-6 } + { dg-begin-multiline-output "" } + RW (2, 3) void f1 (int n, int[n], int); + ~~~~^ ~~~~~~ + { dg-end-multiline-output "" } */ + + +RW (2) void f2 (int, int[*], int); +/* { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2, 3) void f2 (int, int[], int); + ^~~~~ + { dg-end-multiline-output "" } */ + +RW (2, 3) void f2 (int, int[], int); +/* { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 } + { dg-begin-multiline-output "" } + RW (2) void f2 (int, int[*], int); + ^~~~~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-7.c b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c new file mode 100644 index 00000000000..14ce75f3e2e --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-7.c @@ -0,0 +1,36 @@ +/* PR middle-end/97189 - ICE on redeclaration of a function with VLA argument + and attribute access + { dg-do compile } + { dg-options "-Wall" } */ + +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) + +RW (2, 3) void f1 (int n, int[n], int); +/* { dg-warning "attribute 'access \\(read_write, 2, 3\\)' positional argument 2 conflicts with previous designation by argument 3" "warning" { target *-*-* } .-1 } + { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-2 } */ + +void call_f1 (int *p) +{ + /* Verify that a warning is issued. Ideally, it seems the VLA bound + should take precedence over the attribute and the warning would + reference argument 1 but since the conflict in the redeclarations + of the function is already diagnosed don't test that (and let it + be acceptable for this warning to reference argument 3). */ + f1 (-1, p, -1); + // { dg-warning "argument \\d value -1 is negative" "warning" { target *-*-* } .-1 } +} + +RW (2) void f2 (int, int[*], int); +// { dg-message "previously declared as a variable length array 'int\\\[\\\*]'" "note" { target *-*-* } .-1 } +RW (2, 3) void f2 (int, int[], int); +// { dg-warning "argument 2 of type 'int\\\[]' declared as an ordinary array" "warning" { target *-*-* } .-1 } + +void call_f2 (int *p) +{ + f2 (-1, p, 0); + + /* Verify that the attribute access on the redeclaration of f2() takes + precedence over the one on the first declaration. */ + f2 (0, p, -1); + // { dg-warning "argument 3 value -1 is negative" "warning" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/gcc.dg/attr-access-2.c b/gcc/testsuite/gcc.dg/attr-access-2.c index 74762610f98..76baddffc9f 100644 --- a/gcc/testsuite/gcc.dg/attr-access-2.c +++ b/gcc/testsuite/gcc.dg/attr-access-2.c @@ -112,5 +112,11 @@ typedef void G1 (int n, int[n], int); G1 g1; -RW (2, 3) void g1 (int n, int[n], int); // { dg-warning "24: attribute 'access *\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 3" } -// { dg-message "designating the bound of variable length array argument 2" "note" { target *-*-* } .-1 } +/* The warning is about the attribute positional argument 2 which refers + to the last function argument. Ideally, the caret would be under + the corresponding function argument, i.e., the last one here) but + that location isn't available yet. Verify that the caret doesn't + point to function argument 1 which is the VLA bound (that's what + the caret in the note points to). */ +RW (2, 3) void g1 (int n, int[n], int); // { dg-warning "16: attribute 'access *\\\(read_write, 2, 3\\\)' positional argument 2 conflicts with previous designation by argument 3" } +// { dg-message "24:designating the bound of variable length array argument 2" "note" { target *-*-* } .-1 }