From: Martin Sebor Date: Wed, 20 Dec 2017 16:56:20 +0000 (+0000) Subject: PR testsuite/83131 - c-c++/common/attr-nonstring-3 failure for strcmp tests on PowerPC X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=16155777a6069d69a078fee979d9ad05456256a7;p=gcc.git PR testsuite/83131 - c-c++/common/attr-nonstring-3 failure for strcmp tests on PowerPC gcc/ChangeLog: PR testsuite/83131 * builtins.c (expand_builtin_strlen): Use get_callee_fndecl. (expand_builtin_strcmp): Call maybe_warn_nonstring_arg. (expand_builtin_strncmp): Same. gcc/testsuite/ChangeLog: PR testsuite/83131 * c-c++-common/attr-nonstring-4.c: New test. From-SVN: r255898 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6e98187f016..2f23a2b8860 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-12-20 Martin Sebor + + PR testsuite/83131 + * builtins.c (expand_builtin_strlen): Use get_callee_fndecl. + (expand_builtin_strcmp): Call maybe_warn_nonstring_arg. + (expand_builtin_strncmp): Same. + 2017-12-20 Alexandre Oliva PR bootstrap/83396 diff --git a/gcc/builtins.c b/gcc/builtins.c index 277bbe8db26..f8b853c6ecd 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2829,102 +2829,100 @@ expand_builtin_strlen (tree exp, rtx target, { if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; - else - { - struct expand_operand ops[4]; - rtx pat; - tree len; - tree src = CALL_EXPR_ARG (exp, 0); - rtx src_reg; - rtx_insn *before_strlen; - machine_mode insn_mode; - enum insn_code icode = CODE_FOR_nothing; - unsigned int align; - /* If the length can be computed at compile-time, return it. */ - len = c_strlen (src, 0); - if (len) - return expand_expr (len, target, target_mode, EXPAND_NORMAL); - - /* If the length can be computed at compile-time and is constant - integer, but there are side-effects in src, evaluate - src for side-effects, then return len. - E.g. x = strlen (i++ ? "xfoo" + 1 : "bar"); - can be optimized into: i++; x = 3; */ - len = c_strlen (src, 1); - if (len && TREE_CODE (len) == INTEGER_CST) - { - expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); - return expand_expr (len, target, target_mode, EXPAND_NORMAL); - } + struct expand_operand ops[4]; + rtx pat; + tree len; + tree src = CALL_EXPR_ARG (exp, 0); + rtx src_reg; + rtx_insn *before_strlen; + machine_mode insn_mode; + enum insn_code icode = CODE_FOR_nothing; + unsigned int align; - align = get_pointer_alignment (src) / BITS_PER_UNIT; + /* If the length can be computed at compile-time, return it. */ + len = c_strlen (src, 0); + if (len) + return expand_expr (len, target, target_mode, EXPAND_NORMAL); - /* If SRC is not a pointer type, don't do this operation inline. */ - if (align == 0) - return NULL_RTX; + /* If the length can be computed at compile-time and is constant + integer, but there are side-effects in src, evaluate + src for side-effects, then return len. + E.g. x = strlen (i++ ? "xfoo" + 1 : "bar"); + can be optimized into: i++; x = 3; */ + len = c_strlen (src, 1); + if (len && TREE_CODE (len) == INTEGER_CST) + { + expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); + return expand_expr (len, target, target_mode, EXPAND_NORMAL); + } - /* Bail out if we can't compute strlen in the right mode. */ - FOR_EACH_MODE_FROM (insn_mode, target_mode) - { - icode = optab_handler (strlen_optab, insn_mode); - if (icode != CODE_FOR_nothing) - break; - } - if (insn_mode == VOIDmode) - return NULL_RTX; + align = get_pointer_alignment (src) / BITS_PER_UNIT; + + /* If SRC is not a pointer type, don't do this operation inline. */ + if (align == 0) + return NULL_RTX; - /* Make a place to hold the source address. We will not expand - the actual source until we are sure that the expansion will - not fail -- there are trees that cannot be expanded twice. */ - src_reg = gen_reg_rtx (Pmode); + /* Bail out if we can't compute strlen in the right mode. */ + FOR_EACH_MODE_FROM (insn_mode, target_mode) + { + icode = optab_handler (strlen_optab, insn_mode); + if (icode != CODE_FOR_nothing) + break; + } + if (insn_mode == VOIDmode) + return NULL_RTX; - /* Mark the beginning of the strlen sequence so we can emit the - source operand later. */ - before_strlen = get_last_insn (); + /* Make a place to hold the source address. We will not expand + the actual source until we are sure that the expansion will + not fail -- there are trees that cannot be expanded twice. */ + src_reg = gen_reg_rtx (Pmode); - create_output_operand (&ops[0], target, insn_mode); - create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg)); - create_integer_operand (&ops[2], 0); - create_integer_operand (&ops[3], align); - if (!maybe_expand_insn (icode, 4, ops)) - return NULL_RTX; + /* Mark the beginning of the strlen sequence so we can emit the + source operand later. */ + before_strlen = get_last_insn (); - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ - maybe_warn_nonstring_arg (TREE_OPERAND (CALL_EXPR_FN (exp), 0), exp); + create_output_operand (&ops[0], target, insn_mode); + create_fixed_operand (&ops[1], gen_rtx_MEM (BLKmode, src_reg)); + create_integer_operand (&ops[2], 0); + create_integer_operand (&ops[3], align); + if (!maybe_expand_insn (icode, 4, ops)) + return NULL_RTX; - /* Now that we are assured of success, expand the source. */ - start_sequence (); - pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL); - if (pat != src_reg) - { + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + maybe_warn_nonstring_arg (get_callee_fndecl (exp), exp); + + /* Now that we are assured of success, expand the source. */ + start_sequence (); + pat = expand_expr (src, src_reg, Pmode, EXPAND_NORMAL); + if (pat != src_reg) + { #ifdef POINTERS_EXTEND_UNSIGNED - if (GET_MODE (pat) != Pmode) - pat = convert_to_mode (Pmode, pat, - POINTERS_EXTEND_UNSIGNED); + if (GET_MODE (pat) != Pmode) + pat = convert_to_mode (Pmode, pat, + POINTERS_EXTEND_UNSIGNED); #endif - emit_move_insn (src_reg, pat); - } - pat = get_insns (); - end_sequence (); + emit_move_insn (src_reg, pat); + } + pat = get_insns (); + end_sequence (); - if (before_strlen) - emit_insn_after (pat, before_strlen); - else - emit_insn_before (pat, get_insns ()); + if (before_strlen) + emit_insn_after (pat, before_strlen); + else + emit_insn_before (pat, get_insns ()); - /* Return the value in the proper mode for this function. */ - if (GET_MODE (ops[0].value) == target_mode) - target = ops[0].value; - else if (target != 0) - convert_move (target, ops[0].value, 0); - else - target = convert_to_mode (target_mode, ops[0].value, 0); + /* Return the value in the proper mode for this function. */ + if (GET_MODE (ops[0].value) == target_mode) + target = ops[0].value; + else if (target != 0) + convert_move (target, ops[0].value, 0); + else + target = convert_to_mode (target_mode, ops[0].value, 0); - return target; - } + return target; } /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) @@ -4485,102 +4483,104 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode); insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode); - if (cmpstr_icode != CODE_FOR_nothing || cmpstrn_icode != CODE_FOR_nothing) - { - rtx arg1_rtx, arg2_rtx; - tree fndecl, fn; - tree arg1 = CALL_EXPR_ARG (exp, 0); - tree arg2 = CALL_EXPR_ARG (exp, 1); - rtx result = NULL_RTX; + if (cmpstr_icode == CODE_FOR_nothing && cmpstrn_icode == CODE_FOR_nothing) + return NULL_RTX; - unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; - unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); - /* If we don't have POINTER_TYPE, call the function. */ - if (arg1_align == 0 || arg2_align == 0) - return NULL_RTX; + unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; + unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; - /* Stabilize the arguments in case gen_cmpstr(n)si fail. */ - arg1 = builtin_save_expr (arg1); - arg2 = builtin_save_expr (arg2); + /* If we don't have POINTER_TYPE, call the function. */ + if (arg1_align == 0 || arg2_align == 0) + return NULL_RTX; - arg1_rtx = get_memory_rtx (arg1, NULL); - arg2_rtx = get_memory_rtx (arg2, NULL); + /* Stabilize the arguments in case gen_cmpstr(n)si fail. */ + arg1 = builtin_save_expr (arg1); + arg2 = builtin_save_expr (arg2); - /* Try to call cmpstrsi. */ - if (cmpstr_icode != CODE_FOR_nothing) - result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx, - MIN (arg1_align, arg2_align)); + rtx arg1_rtx = get_memory_rtx (arg1, NULL); + rtx arg2_rtx = get_memory_rtx (arg2, NULL); - /* Try to determine at least one length and call cmpstrnsi. */ - if (!result && cmpstrn_icode != CODE_FOR_nothing) - { - tree len; - rtx arg3_rtx; - - tree len1 = c_strlen (arg1, 1); - tree len2 = c_strlen (arg2, 1); - - if (len1) - len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); - if (len2) - len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); - - /* If we don't have a constant length for the first, use the length - of the second, if we know it. We don't require a constant for - this case; some cost analysis could be done if both are available - but neither is constant. For now, assume they're equally cheap, - unless one has side effects. If both strings have constant lengths, - use the smaller. */ - - if (!len1) - len = len2; - else if (!len2) - len = len1; - else if (TREE_SIDE_EFFECTS (len1)) - len = len2; - else if (TREE_SIDE_EFFECTS (len2)) - len = len1; - else if (TREE_CODE (len1) != INTEGER_CST) - len = len2; - else if (TREE_CODE (len2) != INTEGER_CST) - len = len1; - else if (tree_int_cst_lt (len1, len2)) - len = len1; - else - len = len2; + rtx result = NULL_RTX; + /* Try to call cmpstrsi. */ + if (cmpstr_icode != CODE_FOR_nothing) + result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx, + MIN (arg1_align, arg2_align)); - /* If both arguments have side effects, we cannot optimize. */ - if (len && !TREE_SIDE_EFFECTS (len)) - { - arg3_rtx = expand_normal (len); - result = expand_cmpstrn_or_cmpmem - (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len), - arg3_rtx, MIN (arg1_align, arg2_align)); - } - } + /* Try to determine at least one length and call cmpstrnsi. */ + if (!result && cmpstrn_icode != CODE_FOR_nothing) + { + tree len; + rtx arg3_rtx; + + tree len1 = c_strlen (arg1, 1); + tree len2 = c_strlen (arg2, 1); + + if (len1) + len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); + if (len2) + len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); + + /* If we don't have a constant length for the first, use the length + of the second, if we know it. We don't require a constant for + this case; some cost analysis could be done if both are available + but neither is constant. For now, assume they're equally cheap, + unless one has side effects. If both strings have constant lengths, + use the smaller. */ + + if (!len1) + len = len2; + else if (!len2) + len = len1; + else if (TREE_SIDE_EFFECTS (len1)) + len = len2; + else if (TREE_SIDE_EFFECTS (len2)) + len = len1; + else if (TREE_CODE (len1) != INTEGER_CST) + len = len2; + else if (TREE_CODE (len2) != INTEGER_CST) + len = len1; + else if (tree_int_cst_lt (len1, len2)) + len = len1; + else + len = len2; - if (result) + /* If both arguments have side effects, we cannot optimize. */ + if (len && !TREE_SIDE_EFFECTS (len)) { - /* Return the value in the proper mode for this function. */ - machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); - if (GET_MODE (result) == mode) - return result; - if (target == 0) - return convert_to_mode (mode, result, 0); - convert_move (target, result, 0); - return target; + arg3_rtx = expand_normal (len); + result = expand_cmpstrn_or_cmpmem + (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len), + arg3_rtx, MIN (arg1_align, arg2_align)); } + } - /* Expand the library call ourselves using a stabilized argument - list to avoid re-evaluating the function's arguments twice. */ - fndecl = get_callee_fndecl (exp); - fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2); - gcc_assert (TREE_CODE (fn) == CALL_EXPR); - CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); - return expand_call (fn, target, target == const0_rtx); + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + tree fndecl = get_callee_fndecl (exp); + maybe_warn_nonstring_arg (fndecl, exp); + + if (result) + { + /* Return the value in the proper mode for this function. */ + machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); + if (GET_MODE (result) == mode) + return result; + if (target == 0) + return convert_to_mode (mode, result, 0); + convert_move (target, result, 0); + return target; } - return NULL_RTX; + + /* Expand the library call ourselves using a stabilized argument + list to avoid re-evaluating the function's arguments twice. */ + tree fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2); + gcc_assert (TREE_CODE (fn) == CALL_EXPR); + CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); + return expand_call (fn, target, target == const0_rtx); } /* Expand expression EXP, which is a call to the strncmp builtin. Return @@ -4591,8 +4591,6 @@ static rtx expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, ATTRIBUTE_UNUSED machine_mode mode) { - location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp); - if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return NULL_RTX; @@ -4601,88 +4599,92 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, lengths, and it doesn't have side effects, then emit cmpstrnsi using length MIN(strlen(string)+1, arg3). */ insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode); - if (cmpstrn_icode != CODE_FOR_nothing) - { - tree len, len1, len2, len3; - rtx arg1_rtx, arg2_rtx, arg3_rtx; - rtx result; - tree fndecl, fn; - tree arg1 = CALL_EXPR_ARG (exp, 0); - tree arg2 = CALL_EXPR_ARG (exp, 1); - tree arg3 = CALL_EXPR_ARG (exp, 2); - - unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; - unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; - - len1 = c_strlen (arg1, 1); - len2 = c_strlen (arg2, 1); - - if (len1) - len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1); - if (len2) - len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2); - - len3 = fold_convert_loc (loc, sizetype, arg3); - - /* If we don't have a constant length for the first, use the length - of the second, if we know it. If neither string is constant length, - use the given length argument. We don't require a constant for - this case; some cost analysis could be done if both are available - but neither is constant. For now, assume they're equally cheap, - unless one has side effects. If both strings have constant lengths, - use the smaller. */ - - if (!len1 && !len2) - len = len3; - else if (!len1) - len = len2; - else if (!len2) - len = len1; - else if (TREE_SIDE_EFFECTS (len1)) - len = len2; - else if (TREE_SIDE_EFFECTS (len2)) - len = len1; - else if (TREE_CODE (len1) != INTEGER_CST) - len = len2; - else if (TREE_CODE (len2) != INTEGER_CST) - len = len1; - else if (tree_int_cst_lt (len1, len2)) - len = len1; - else - len = len2; - - /* If we are not using the given length, we must incorporate it here. - The actual new length parameter will be MIN(len,arg3) in this case. */ - if (len != len3) - len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3); - arg1_rtx = get_memory_rtx (arg1, len); - arg2_rtx = get_memory_rtx (arg2, len); - arg3_rtx = expand_normal (len); - result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx, - arg2_rtx, TREE_TYPE (len), arg3_rtx, - MIN (arg1_align, arg2_align)); - if (result) - { - /* Return the value in the proper mode for this function. */ - mode = TYPE_MODE (TREE_TYPE (exp)); - if (GET_MODE (result) == mode) - return result; - if (target == 0) - return convert_to_mode (mode, result, 0); - convert_move (target, result, 0); - return target; - } + if (cmpstrn_icode == CODE_FOR_nothing) + return NULL_RTX; - /* Expand the library call ourselves using a stabilized argument - list to avoid re-evaluating the function's arguments twice. */ - fndecl = get_callee_fndecl (exp); - fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 3, - arg1, arg2, len); - gcc_assert (TREE_CODE (fn) == CALL_EXPR); - CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); - return expand_call (fn, target, target == const0_rtx); - } - return NULL_RTX; + tree len; + + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); + tree arg3 = CALL_EXPR_ARG (exp, 2); + + unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; + unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; + + tree len1 = c_strlen (arg1, 1); + tree len2 = c_strlen (arg2, 1); + + location_t loc = EXPR_LOCATION (exp); + + if (len1) + len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1); + if (len2) + len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2); + + tree len3 = fold_convert_loc (loc, sizetype, arg3); + + /* If we don't have a constant length for the first, use the length + of the second, if we know it. If neither string is constant length, + use the given length argument. We don't require a constant for + this case; some cost analysis could be done if both are available + but neither is constant. For now, assume they're equally cheap, + unless one has side effects. If both strings have constant lengths, + use the smaller. */ + + if (!len1 && !len2) + len = len3; + else if (!len1) + len = len2; + else if (!len2) + len = len1; + else if (TREE_SIDE_EFFECTS (len1)) + len = len2; + else if (TREE_SIDE_EFFECTS (len2)) + len = len1; + else if (TREE_CODE (len1) != INTEGER_CST) + len = len2; + else if (TREE_CODE (len2) != INTEGER_CST) + len = len1; + else if (tree_int_cst_lt (len1, len2)) + len = len1; + else + len = len2; + + /* If we are not using the given length, we must incorporate it here. + The actual new length parameter will be MIN(len,arg3) in this case. */ + if (len != len3) + len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3); + rtx arg1_rtx = get_memory_rtx (arg1, len); + rtx arg2_rtx = get_memory_rtx (arg2, len); + rtx arg3_rtx = expand_normal (len); + rtx result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx, + arg2_rtx, TREE_TYPE (len), arg3_rtx, + MIN (arg1_align, arg2_align)); + + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. */ + tree fndecl = get_callee_fndecl (exp); + maybe_warn_nonstring_arg (fndecl, exp); + + if (result) + { + /* Return the value in the proper mode for this function. */ + mode = TYPE_MODE (TREE_TYPE (exp)); + if (GET_MODE (result) == mode) + return result; + if (target == 0) + return convert_to_mode (mode, result, 0); + convert_move (target, result, 0); + return target; + } + + /* Expand the library call ourselves using a stabilized argument + list to avoid re-evaluating the function's arguments twice. */ + tree fn = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len); + gcc_assert (TREE_CODE (fn) == CALL_EXPR); + CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); + return expand_call (fn, target, target == const0_rtx); } /* Expand a call to __builtin_saveregs, generating the result in TARGET, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 76f1b795c63..3eb1f534cf3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-12-20 Martin Sebor + + PR testsuite/83131 + * c-c++-common/attr-nonstring-4.c: New test. + 2017-12-20 Richard Sandiford * gcc.dg/plugin/poly-int-tests.h (test_nonpoly_multiple_p): New diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-4.c b/gcc/testsuite/c-c++-common/attr-nonstring-4.c new file mode 100644 index 00000000000..0571e46fc4d --- /dev/null +++ b/gcc/testsuite/c-c++-common/attr-nonstring-4.c @@ -0,0 +1,79 @@ +/* PR middle-end/83131 - c-c++/common/attr-nonstring-3 failure for strcmp + tests on PowerPC + { dg-do compile } + { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */ + +#if __cplusplus +extern "C" { +#endif + +typedef __SIZE_TYPE__ size_t; + +extern int strcmp (const char*, const char*); +extern int strncmp (const char*, const char*, size_t); + +#if __cplusplus +} /* extern "C" */ +#endif + +extern char arx[] __attribute__ ((nonstring)); +extern char ar5[5] __attribute__ ((nonstring)); +extern char str[]; + +enum { N = sizeof ar5 }; +enum { X = sizeof ar5 + 1 }; + + +int warn_strcmp_cst_1 (void) +{ + return strcmp ("bar", arx); /* { dg-warning "argument 2 declared attribute .nonstring." } */ +} + +int warn_strcmp_cst_2 (void) +{ + return strcmp (arx, "foo"); /* { dg-warning "argument 1 declared attribute .nonstring." } */ +} + + +int warn_strncmp_cst_1 (void) +{ + return strncmp ("bar", ar5, X); /* { dg-warning "argument 2 declared attribute .nonstring." } */ +} + +int warn_strncmp_cst_2 (void) +{ + return strncmp (ar5, "foo", X); /* { dg-warning "argument 1 declared attribute .nonstring." } */ +} + + +int nowarn_strncmp_cst_1 (void) +{ + return strncmp ("bar", ar5, N); +} + +int nowarn_strncmp_cst_2 (void) +{ + return strncmp (ar5, "foo", N); +} + + +int warn_strncmp_var_1 (void) +{ + return strncmp (str, ar5, X); /* { dg-warning "argument 2 declared attribute .nonstring." } */ +} + +int warn_strncmp_var_2 (void) +{ + return strncmp (ar5, str, X); /* { dg-warning "argument 1 declared attribute .nonstring." } */ +} + + +int nowarn_strncmp_var_1 (void) +{ + return strncmp (str, ar5, N); +} + +int nowarn_strncmp_var_2 (void) +{ + return strncmp (ar5, str, N); +}