diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 34959590b37..552a29f9944 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -3646,7 +3646,8 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) /* 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_LEXICOGRAPHIC)) + if (operand_equal_p (newbnd, curbnd, + OEP_DECL_NAME | OEP_LEXICOGRAPHIC)) continue; if (warning_at (newloc, OPT_Wvla_parameter, diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 983d65e930c..234ee16fe4a 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5865,6 +5865,7 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs) /* Each variable VLA bound is represented by a dollar sign. */ spec += "$"; + STRIP_NOPS (nelts); vbchain = tree_cons (NULL_TREE, nelts, vbchain); } diff --git a/gcc/fold-const.c b/gcc/fold-const.c index e0cdb75fb26..7dcecc9a5c0 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3499,11 +3499,26 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1, case tcc_declaration: /* Consider __builtin_sqrt equal to sqrt. */ - return (TREE_CODE (arg0) == FUNCTION_DECL - && fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1) - && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1) - && (DECL_UNCHECKED_FUNCTION_CODE (arg0) - == DECL_UNCHECKED_FUNCTION_CODE (arg1))); + if (TREE_CODE (arg0) == FUNCTION_DECL) + return (fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1) + && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1) + && (DECL_UNCHECKED_FUNCTION_CODE (arg0) + == DECL_UNCHECKED_FUNCTION_CODE (arg1))); + + if (DECL_P (arg0) + && (flags & OEP_DECL_NAME) + && (flags & OEP_LEXICOGRAPHIC)) + { + /* Consider decls with the same name equal. The caller needs + to make sure they refer to the same entity (such as a function + formal parameter). */ + tree a0name = DECL_NAME (arg0); + tree a1name = DECL_NAME (arg1); + const char *a0ns = a0name ? IDENTIFIER_POINTER (a0name) : NULL; + const char *a1ns = a1name ? IDENTIFIER_POINTER (a1name) : NULL; + return a0ns && a1ns && strcmp (a0ns, a1ns) == 0; + } + return false; case tcc_exceptional: if (TREE_CODE (arg0) == CONSTRUCTOR) @@ -3914,14 +3929,14 @@ bool operand_compare::verify_hash_value (const_tree arg0, const_tree arg1, unsigned int flags, bool *ret) { - /* When checking, verify at the outermost operand_equal_p call that - if operand_equal_p returns non-zero then ARG0 and ARG1 has the same - hash value. */ + /* When checking and unless comparing DECL names, verify that if + the outermost operand_equal_p call returns non-zero then ARG0 + and ARG1 have the same hash value. */ if (flag_checking && !(flags & OEP_NO_HASH_CHECK)) { if (operand_equal_p (arg0, arg1, flags | OEP_NO_HASH_CHECK)) { - if (arg0 != arg1) + if (arg0 != arg1 && !(flags & OEP_DECL_NAME)) { inchash::hash hstate0 (0), hstate1 (0); hash_operand (arg0, hstate0, flags | OEP_HASH_CHECK); diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-12.c b/gcc/testsuite/gcc.dg/Wvla-parameter-12.c new file mode 100644 index 00000000000..1be5e48203b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wvla-parameter-12.c @@ -0,0 +1,36 @@ +/* PR c/101289 - bogus -Wvla-parameter warning when using const bound + { dg-do compile } + { dg-options "-Wall" } */ + +void f1ci_can (const int n, char a[n]); +void f1ci_can (const int n, char a[n]); // { dg-bogus "-Wvla-parameter" } + +void f2ci_can (const int m, char a[m]); +void f2ci_can (int n, char a[n]); // { dg-bogus "-Wvla-parameter" } + +void f3i_can (int n, char a[n]); +void f3i_can (const int n, char a[n]); // { dg-bogus "-Wvla-parameter" } + +void f4i_can (int n, char a[n]); +void f4i_can (const int n, char a[(int)n]); // { dg-bogus "-Wvla-parameter" } + +void f5i_can (int n, char a[(char)n]); +void f5i_can (const int n, char a[(char)n]); // { dg-bogus "-Wvla-parameter" } + +void f6i_can (int m, char a[(char)m]); +void f6i_can (const int n, char a[(char)n]); // { dg-bogus "-Wvla-parameter" "" { xfail *-*-* } } + + +/* PR c/97548 - bogus -Wvla-parameter on a bound expression involving + a parameter */ + +int n; + +void f7ianp1 (int, int[n + 1]); +void f7ianp1 (int, int[n + 1]); +void f7ianp1 (int, int[n + 2]); // { dg-warning "-Wvla-parameter" } + +void f8iakp1 (int k, int [k + 1]); +void f8iakp1 (int k, int [k + 1]); // { dg-bogus "-Wvla-parameter" } +void f8iakp1 (int k, int [1 + k]); // { dg-bogus "-Wvla-parameter" } +void f8iakp1 (int k, int [k + 2]); // { dg-warning "-Wvla-parameter" } diff --git a/gcc/tree-core.h b/gcc/tree-core.h index e15e6c651f0..23cd289bcc3 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -888,6 +888,7 @@ enum size_type_kind { stk_type_kind_last }; +/* Flags controlling operand_equal_p() behavior. */ enum operand_equal_flag { OEP_ONLY_CONST = 1, OEP_PURE_SAME = 2, @@ -902,7 +903,11 @@ enum operand_equal_flag { OEP_BITWISE = 128, /* For OEP_ADDRESS_OF of COMPONENT_REFs, only consider same fields as equivalent rather than also different fields with the same offset. */ - OEP_ADDRESS_OF_SAME_FIELD = 256 + OEP_ADDRESS_OF_SAME_FIELD = 256, + /* In conjunction with OEP_LEXICOGRAPHIC considers names of declarations + of the same kind. Used to compare VLA bounds involving parameters + across redeclarations of the same function. */ + OEP_DECL_NAME = 512 }; /* Enum and arrays used for tree allocation stats.