diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 75297ed7c9e..879dbcc1e52 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -4511,6 +4511,9 @@ pass_waccess::check_dangling_stores (basic_block bb, if (!stmt) break; + if (warning_suppressed_p (stmt, OPT_Wdangling_pointer_)) + continue; + if (is_gimple_call (stmt) && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))) /* Avoid looking before nonconst, nonpure calls since those might @@ -4536,10 +4539,16 @@ pass_waccess::check_dangling_stores (basic_block bb, } else if (TREE_CODE (lhs_ref.ref) == SSA_NAME) { - /* Avoid looking at or before stores into unknown objects. */ gimple *def_stmt = SSA_NAME_DEF_STMT (lhs_ref.ref); if (!gimple_nop_p (def_stmt)) + /* Avoid looking at or before stores into unknown objects. */ return; + + tree var = SSA_NAME_VAR (lhs_ref.ref); + if (TREE_CODE (var) == PARM_DECL && DECL_BY_REFERENCE (var)) + /* Avoid by-value arguments transformed into by-reference. */ + continue; + } else if (TREE_CODE (lhs_ref.ref) == MEM_REF) { @@ -4572,6 +4581,8 @@ pass_waccess::check_dangling_stores (basic_block bb, "storing the address of local variable %qD in %qE", rhs_ref.ref, lhs)) { + suppress_warning (stmt, OPT_Wdangling_pointer_); + location_t loc = DECL_SOURCE_LOCATION (rhs_ref.ref); inform (loc, "%qD declared here", rhs_ref.ref); diff --git a/gcc/testsuite/c-c++-common/Wdangling-pointer-8.c b/gcc/testsuite/c-c++-common/Wdangling-pointer-8.c new file mode 100644 index 00000000000..433727dd845 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wdangling-pointer-8.c @@ -0,0 +1,20 @@ +/* Verify -Wdangling-pointer is issued only once. + { dg-do compile } + { dg-options "-O -Wall" } */ + +void *p; + +void escape_global_warn_once (void) +{ + int x[5]; + + p = &x[3]; // { dg-regexp "\[^\n\r\]+: warning: \[^\n\r\]+ \\\[-Wdangling-pointer.?\\\]" "message" } +} + + +void escape_param_warn_once (void **p) +{ + int x[5]; + + *p = &x[3]; // { dg-regexp "\[^\n\r\]+: warning: \[^\n\r\]+ \\\[-Wdangling-pointer.?\\\]" "message" } +} diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-pointer-5.C b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-5.C new file mode 100644 index 00000000000..b3d144a9e6d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-5.C @@ -0,0 +1,34 @@ +/* PR middle-end/104436 - spurious -Wdangling-pointer assigning local + address to a class passed by value + { dg-do compile } + { dg-options "-O1 -Wall" } */ + +struct S +{ + S (void *p): p (p) { } + S (const S &s): p (s.p) { } + + void *p; +}; + + +void nowarn_assign_by_value (S s) +{ + int i; + S t (&i); + s = t; // { dg-bogus "-Wdangling-pointer" } +} + +void nowarn_assign_by_value_arg (S s) +{ + S t (&s); + s = t; // { dg-bogus "-Wdangling-pointer" } +} + + +void warn_assign_local_by_reference (S &s) +{ + int i; + S t (&i); + s = t; // { dg-warning "-Wdangling-pointer" } +}