diff mbox series

[2/2] c++: -Wdangling-reference diagnostic

Message ID 20240917211948.72205-2-jason@redhat.com
State New
Headers show
Series [1/2] c++: -Wdangling-reference and empty class [PR115361] | expand

Commit Message

Jason Merrill Sept. 17, 2024, 9:16 p.m. UTC
Tested x86_64-pc-linux-gnu.  Marek, thoughts?

-- 8< --

The -Wdangling-reference diagnostic talks about the full-expression, but
prints one call, while the full-expression in a declaration is the entire
initialization.  It seems more useful to point out the temporary that the
compiler thinks we might be getting a dangling reference to.

gcc/cp/ChangeLog:

	* call.cc (do_warn_dangling_reference): Return temporary
	instead of the call it's passed to.
	(maybe_warn_dangling_reference): Adjust diagnostic.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/Wdangling-reference1.C: Adjust diagnostic.
---
 gcc/cp/call.cc                                | 23 +++++++++----------
 .../g++.dg/warn/Wdangling-reference1.C        |  2 +-
 2 files changed, 12 insertions(+), 13 deletions(-)

Comments

Marek Polacek Sept. 17, 2024, 9:53 p.m. UTC | #1
On Tue, Sep 17, 2024 at 05:16:48PM -0400, Jason Merrill wrote:
> Tested x86_64-pc-linux-gnu.  Marek, thoughts?

Makes sense.  OK, thanks.
 
> -- 8< --
> 
> The -Wdangling-reference diagnostic talks about the full-expression, but
> prints one call, while the full-expression in a declaration is the entire
> initialization.  It seems more useful to point out the temporary that the
> compiler thinks we might be getting a dangling reference to.
> 
> gcc/cp/ChangeLog:
> 
> 	* call.cc (do_warn_dangling_reference): Return temporary
> 	instead of the call it's passed to.
> 	(maybe_warn_dangling_reference): Adjust diagnostic.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/warn/Wdangling-reference1.C: Adjust diagnostic.
> ---
>  gcc/cp/call.cc                                | 23 +++++++++----------
>  .../g++.dg/warn/Wdangling-reference1.C        |  2 +-
>  2 files changed, 12 insertions(+), 13 deletions(-)
> 
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 1ecf3aac705..3f753e2d2f9 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -14253,19 +14253,18 @@ reference_like_class_p (tree ctype)
>    return false;
>  }
>  
> -/* Helper for maybe_warn_dangling_reference to find a problematic CALL_EXPR
> -   that initializes the LHS (and at least one of its arguments represents
> -   a temporary, as outlined in maybe_warn_dangling_reference), or NULL_TREE
> +/* Helper for maybe_warn_dangling_reference to find a problematic temporary
> +   in EXPR (as outlined in maybe_warn_dangling_reference), or NULL_TREE
>     if none found.  For instance:
>  
> -     const S& s = S().self(); // S::self (&TARGET_EXPR <...>)
> -     const int& r = (42, f(1)); // f(1)
> -     const int& t = b ? f(1) : f(2); // f(1)
> -     const int& u = b ? f(1) : f(g); // f(1)
> -     const int& v = b ? f(g) : f(2); // f(2)
> +     const S& s = S().self(); // S()
> +     const int& r = (42, f(1)); // temporary for passing 1 to f
> +     const int& t = b ? f(1) : f(2); // temporary for 1
> +     const int& u = b ? f(1) : f(g); // temporary for 1
> +     const int& v = b ? f(g) : f(2); // temporary for 2
>       const int& w = b ? f(g) : f(g); // NULL_TREE
>       const int& y = (f(1), 42); // NULL_TREE
> -     const int& z = f(f(1)); // f(f(1))
> +     const int& z = f(f(1)); // temporary for 1
>  
>     EXPR is the initializer.  If ARG_P is true, we're processing an argument
>     to a function; the point is to distinguish between, for example,
> @@ -14365,7 +14364,7 @@ do_warn_dangling_reference (tree expr, bool arg_p)
>  		    && !reference_related_p (TREE_TYPE (rettype),
>  					     TREE_TYPE (arg)))
>  		  continue;
> -		return expr;
> +		return arg;
>  	      }
>  	  /* Don't warn about member functions like:
>  	      std::any a(...);
> @@ -14438,8 +14437,8 @@ maybe_warn_dangling_reference (const_tree decl, tree init)
>        auto_diagnostic_group d;
>        if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wdangling_reference,
>  		      "possibly dangling reference to a temporary"))
> -	inform (EXPR_LOCATION (call), "the temporary was destroyed at "
> -		"the end of the full expression %qE", call);
> +	inform (EXPR_LOCATION (call), "%qT temporary created here",
> +		TREE_TYPE (call));
>      }
>  }
>  
> diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
> index a184317dd5c..5e60a415836 100644
> --- a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
> +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
> @@ -117,7 +117,7 @@ const B& b10 = lox (H{}); // { dg-warning "dangling reference" }
>  
>  struct S {
>    const int &r; // { dg-warning "dangling reference" }
> -  S() : r(f(10)) { } // { dg-message "destroyed" }
> +  S() : r(f(10)) { } // { dg-message "created" }
>  };
>  
>  // From cppreference.
> -- 
> 2.46.0
> 

Marek
diff mbox series

Patch

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 1ecf3aac705..3f753e2d2f9 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14253,19 +14253,18 @@  reference_like_class_p (tree ctype)
   return false;
 }
 
-/* Helper for maybe_warn_dangling_reference to find a problematic CALL_EXPR
-   that initializes the LHS (and at least one of its arguments represents
-   a temporary, as outlined in maybe_warn_dangling_reference), or NULL_TREE
+/* Helper for maybe_warn_dangling_reference to find a problematic temporary
+   in EXPR (as outlined in maybe_warn_dangling_reference), or NULL_TREE
    if none found.  For instance:
 
-     const S& s = S().self(); // S::self (&TARGET_EXPR <...>)
-     const int& r = (42, f(1)); // f(1)
-     const int& t = b ? f(1) : f(2); // f(1)
-     const int& u = b ? f(1) : f(g); // f(1)
-     const int& v = b ? f(g) : f(2); // f(2)
+     const S& s = S().self(); // S()
+     const int& r = (42, f(1)); // temporary for passing 1 to f
+     const int& t = b ? f(1) : f(2); // temporary for 1
+     const int& u = b ? f(1) : f(g); // temporary for 1
+     const int& v = b ? f(g) : f(2); // temporary for 2
      const int& w = b ? f(g) : f(g); // NULL_TREE
      const int& y = (f(1), 42); // NULL_TREE
-     const int& z = f(f(1)); // f(f(1))
+     const int& z = f(f(1)); // temporary for 1
 
    EXPR is the initializer.  If ARG_P is true, we're processing an argument
    to a function; the point is to distinguish between, for example,
@@ -14365,7 +14364,7 @@  do_warn_dangling_reference (tree expr, bool arg_p)
 		    && !reference_related_p (TREE_TYPE (rettype),
 					     TREE_TYPE (arg)))
 		  continue;
-		return expr;
+		return arg;
 	      }
 	  /* Don't warn about member functions like:
 	      std::any a(...);
@@ -14438,8 +14437,8 @@  maybe_warn_dangling_reference (const_tree decl, tree init)
       auto_diagnostic_group d;
       if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wdangling_reference,
 		      "possibly dangling reference to a temporary"))
-	inform (EXPR_LOCATION (call), "the temporary was destroyed at "
-		"the end of the full expression %qE", call);
+	inform (EXPR_LOCATION (call), "%qT temporary created here",
+		TREE_TYPE (call));
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
index a184317dd5c..5e60a415836 100644
--- a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
@@ -117,7 +117,7 @@  const B& b10 = lox (H{}); // { dg-warning "dangling reference" }
 
 struct S {
   const int &r; // { dg-warning "dangling reference" }
-  S() : r(f(10)) { } // { dg-message "destroyed" }
+  S() : r(f(10)) { } // { dg-message "created" }
 };
 
 // From cppreference.