diff mbox series

C++ PATCH for build_throw

Message ID 20180904230155.GL12638@redhat.com
State New
Headers show
Series C++ PATCH for build_throw | expand

Commit Message

Marek Polacek Sept. 4, 2018, 11:01 p.m. UTC
It occurred to me that we should be able to use treat_lvalue_as_rvalue_p in the
second context where we're supposed to use a move operation as well.  Except
that for a throw-expression, the operand may not be a function parameter.
While at it, also make use of CP_TYPE_VOLATILE_P.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-09-04  Marek Polacek  <polacek@redhat.com>

	* cp-tree.h (treat_lvalue_as_rvalue_p): Declare.
	* except.c (build_throw): Use it.  Use CP_TYPE_VOLATILE_P.
	* typeck.c (treat_lvalue_as_rvalue_p): No longer static.  Add PARM_OK
	parameter.
	(maybe_warn_pessimizing_move): Adjust treat_lvalue_as_rvalue_p call.
	(check_return_expr): Likewise.

Comments

Jason Merrill Sept. 5, 2018, 1:39 a.m. UTC | #1
OK.

On Tue, Sep 4, 2018 at 7:01 PM, Marek Polacek <polacek@redhat.com> wrote:
> It occurred to me that we should be able to use treat_lvalue_as_rvalue_p in the
> second context where we're supposed to use a move operation as well.  Except
> that for a throw-expression, the operand may not be a function parameter.
> While at it, also make use of CP_TYPE_VOLATILE_P.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2018-09-04  Marek Polacek  <polacek@redhat.com>
>
>         * cp-tree.h (treat_lvalue_as_rvalue_p): Declare.
>         * except.c (build_throw): Use it.  Use CP_TYPE_VOLATILE_P.
>         * typeck.c (treat_lvalue_as_rvalue_p): No longer static.  Add PARM_OK
>         parameter.
>         (maybe_warn_pessimizing_move): Adjust treat_lvalue_as_rvalue_p call.
>         (check_return_expr): Likewise.
>
> diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
> index 43e452cc1a3..df441fca304 100644
> --- gcc/cp/cp-tree.h
> +++ gcc/cp/cp-tree.h
> @@ -7354,6 +7354,7 @@ extern tree cp_perform_integral_promotions      (tree, tsubst_flags_t);
>  extern tree finish_left_unary_fold_expr      (tree, int);
>  extern tree finish_right_unary_fold_expr     (tree, int);
>  extern tree finish_binary_fold_expr          (tree, tree, int);
> +extern bool treat_lvalue_as_rvalue_p        (tree, bool);
>
>  /* in typeck2.c */
>  extern void require_complete_eh_spec_types     (tree, tree);
> diff --git gcc/cp/except.c gcc/cp/except.c
> index f85ae047cfc..2db90eedcf7 100644
> --- gcc/cp/except.c
> +++ gcc/cp/except.c
> @@ -676,12 +676,9 @@ build_throw (tree exp)
>           /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
>              treated as an rvalue for the purposes of overload resolution
>              to favor move constructors over copy constructors.  */
> -         if (/* Must be a local, automatic variable.  */
> -             VAR_P (exp)
> -             && DECL_CONTEXT (exp) == current_function_decl
> -             && ! TREE_STATIC (exp)
> +         if (treat_lvalue_as_rvalue_p (exp, /*parm_ok*/false)
>               /* The variable must not have the `volatile' qualifier.  */
> -             && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
> +             && !CP_TYPE_VOLATILE_P (TREE_TYPE (exp)))
>             {
>               tree moved = move (exp);
>               exp_vec = make_tree_vector_single (moved);
> diff --git gcc/cp/typeck.c gcc/cp/typeck.c
> index ab088a946b3..84cf4c478aa 100644
> --- gcc/cp/typeck.c
> +++ gcc/cp/typeck.c
> @@ -9180,14 +9180,15 @@ can_do_nrvo_p (tree retval, tree functype)
>  }
>
>  /* Returns true if we should treat RETVAL, an expression being returned,
> -   as if it were designated by an rvalue.  See [class.copy.elision].  */
> +   as if it were designated by an rvalue.  See [class.copy.elision].
> +   PARM_P is true if a function parameter is OK in this context.  */
>
> -static bool
> -treat_lvalue_as_rvalue_p (tree retval)
> +bool
> +treat_lvalue_as_rvalue_p (tree retval, bool parm_ok)
>  {
>    return ((cxx_dialect != cxx98)
>           && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
> -             || TREE_CODE (retval) == PARM_DECL)
> +             || (parm_ok && TREE_CODE (retval) == PARM_DECL))
>           && DECL_CONTEXT (retval) == current_function_decl
>           && !TREE_STATIC (retval));
>  }
> @@ -9240,7 +9241,7 @@ maybe_warn_pessimizing_move (tree retval, tree functype)
>             }
>           /* Warn if the move is redundant.  It is redundant when we would
>              do maybe-rvalue overload resolution even without std::move.  */
> -         else if (treat_lvalue_as_rvalue_p (arg))
> +         else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true))
>             {
>               auto_diagnostic_group d;
>               if (warning_at (loc, OPT_Wredundant_move,
> @@ -9525,7 +9526,7 @@ check_return_expr (tree retval, bool *no_warning)
>           Note that these conditions are similar to, but not as strict as,
>          the conditions for the named return value optimization.  */
>        bool converted = false;
> -      if (treat_lvalue_as_rvalue_p (retval)
> +      if (treat_lvalue_as_rvalue_p (retval, /*parm_ok*/true)
>           /* This is only interesting for class type.  */
>           && CLASS_TYPE_P (functype))
>         {
diff mbox series

Patch

diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index 43e452cc1a3..df441fca304 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -7354,6 +7354,7 @@  extern tree cp_perform_integral_promotions      (tree, tsubst_flags_t);
 extern tree finish_left_unary_fold_expr      (tree, int);
 extern tree finish_right_unary_fold_expr     (tree, int);
 extern tree finish_binary_fold_expr          (tree, tree, int);
+extern bool treat_lvalue_as_rvalue_p	     (tree, bool);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types	(tree, tree);
diff --git gcc/cp/except.c gcc/cp/except.c
index f85ae047cfc..2db90eedcf7 100644
--- gcc/cp/except.c
+++ gcc/cp/except.c
@@ -676,12 +676,9 @@  build_throw (tree exp)
 	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
 	     treated as an rvalue for the purposes of overload resolution
 	     to favor move constructors over copy constructors.  */
-	  if (/* Must be a local, automatic variable.  */
-	      VAR_P (exp)
-	      && DECL_CONTEXT (exp) == current_function_decl
-	      && ! TREE_STATIC (exp)
+	  if (treat_lvalue_as_rvalue_p (exp, /*parm_ok*/false)
 	      /* The variable must not have the `volatile' qualifier.  */
-	      && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
+	      && !CP_TYPE_VOLATILE_P (TREE_TYPE (exp)))
 	    {
 	      tree moved = move (exp);
 	      exp_vec = make_tree_vector_single (moved);
diff --git gcc/cp/typeck.c gcc/cp/typeck.c
index ab088a946b3..84cf4c478aa 100644
--- gcc/cp/typeck.c
+++ gcc/cp/typeck.c
@@ -9180,14 +9180,15 @@  can_do_nrvo_p (tree retval, tree functype)
 }
 
 /* Returns true if we should treat RETVAL, an expression being returned,
-   as if it were designated by an rvalue.  See [class.copy.elision].  */
+   as if it were designated by an rvalue.  See [class.copy.elision].
+   PARM_P is true if a function parameter is OK in this context.  */
 
-static bool
-treat_lvalue_as_rvalue_p (tree retval)
+bool
+treat_lvalue_as_rvalue_p (tree retval, bool parm_ok)
 {
   return ((cxx_dialect != cxx98)
 	  && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
-	      || TREE_CODE (retval) == PARM_DECL)
+	      || (parm_ok && TREE_CODE (retval) == PARM_DECL))
 	  && DECL_CONTEXT (retval) == current_function_decl
 	  && !TREE_STATIC (retval));
 }
@@ -9240,7 +9241,7 @@  maybe_warn_pessimizing_move (tree retval, tree functype)
 	    }
 	  /* Warn if the move is redundant.  It is redundant when we would
 	     do maybe-rvalue overload resolution even without std::move.  */
-	  else if (treat_lvalue_as_rvalue_p (arg))
+	  else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true))
 	    {
 	      auto_diagnostic_group d;
 	      if (warning_at (loc, OPT_Wredundant_move,
@@ -9525,7 +9526,7 @@  check_return_expr (tree retval, bool *no_warning)
          Note that these conditions are similar to, but not as strict as,
 	 the conditions for the named return value optimization.  */
       bool converted = false;
-      if (treat_lvalue_as_rvalue_p (retval)
+      if (treat_lvalue_as_rvalue_p (retval, /*parm_ok*/true)
 	  /* This is only interesting for class type.  */
 	  && CLASS_TYPE_P (functype))
 	{