diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 2e83d24dfda0473643125b8e992b8d689d5c4814..8078b31544d13e92bb14c72b64a6810585cfb5a5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1872,13 +1872,18 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
 	  x = build_address (x);
 	}
       if (TREE_ADDRESSABLE (type))
-	/* Undo convert_for_arg_passing work here.  */
-	x = convert_from_reference (x);
-      /* Normally we would strip a TARGET_EXPR in an initialization context
-	 such as this, but here we do the elision differently: we keep the
-	 TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm.  */
-      arg = cxx_eval_constant_expression (ctx, x, vc_prvalue,
-					  non_constant_p, overflow_p);
+	{
+	  /* Undo convert_for_arg_passing work here.  */
+	  x = convert_from_reference (x);
+	  arg = cxx_eval_constant_expression (ctx, x, vc_glvalue,
+					      non_constant_p, overflow_p);
+	}
+      else
+	/* Normally we would strip a TARGET_EXPR in an initialization context
+	   such as this, but here we do the elision differently: we keep the
+	   TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm.  */
+	arg = cxx_eval_constant_expression (ctx, x, vc_prvalue,
+					    non_constant_p, overflow_p);
       /* Check we aren't dereferencing a null pointer when calling a non-static
 	 member function, which is undefined behaviour.  */
       if (i == 0 && DECL_OBJECT_MEMBER_FUNCTION_P (fun)
@@ -1904,7 +1909,16 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
 	{
 	  /* Make sure the binding has the same type as the parm.  But
 	     only for constant args.  */
-	  if (!TYPE_REF_P (type))
+	  if (TREE_ADDRESSABLE (type))
+	    {
+	      if (!same_type_p (type, TREE_TYPE (arg)))
+		{
+		  arg = build_fold_addr_expr (arg);
+		  arg = cp_fold_convert (build_reference_type (type), arg);
+		  arg = convert_from_reference (arg);
+		}
+	    }
+	  else if (!TYPE_REF_P (type))
 	    arg = adjust_temp_type (type, arg);
 	  if (!TREE_CONSTANT (arg))
 	    *non_constant_args = true;
@@ -7499,9 +7513,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 
     case PARM_DECL:
       if (lval && !TYPE_REF_P (TREE_TYPE (t)))
-	/* glvalue use.  */;
+	{
+	  /* glvalue use.  */
+	  if (TREE_ADDRESSABLE (TREE_TYPE (t)))
+	    if (tree v = ctx->global->get_value (t))
+	      r = v;
+	}
       else if (tree v = ctx->global->get_value (t))
-	r = v;
+	{
+	  r = v;
+	  if (TREE_ADDRESSABLE (TREE_TYPE (t)))
+	    r = cxx_eval_constant_expression (ctx, r, vc_prvalue,
+					      non_constant_p, overflow_p);
+	}
       else if (lval)
 	/* Defer in case this is only used for its type.  */;
       else if (ctx->global->is_outside_lifetime (t))
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime7.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime7.C
index 4148f42f7be8498b188485c64f7d4c287e04ff00..a1da4f81201885b9c54ee98d1b53b43152c82902 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime7.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-lifetime7.C
@@ -87,7 +87,7 @@ constexpr bool n1 = test_access<NonTrivial>();        // { dg-message "in .const
 constexpr bool n2 = test_modification<NonTrivial>();  // { dg-message "in .constexpr." "" { target c++20 } }
 constexpr bool n3 = test_scope<NonTrivial>();         // { dg-message "in .constexpr." "" { target c++20 } }
 constexpr bool n4 = test_destroy_temp<NonTrivial>();  // { dg-message "in .constexpr." "" { target c++20 } }
-constexpr bool n5 = test_parameter(NonTrivial{});     // { dg-error "destroying" "" { target c++20 } }
+constexpr bool n5 = test_parameter(NonTrivial{});     // { dg-message "in .constexpr." "" { target c++20 } }
 constexpr bool n6 = test_bindings<NonTrivial>();
 #endif
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-111284.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-111284.C
new file mode 100644
index 0000000000000000000000000000000000000000..eb31fd843e6612b42776b120aacef8183f0a7a27
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-111284.C
@@ -0,0 +1,19 @@
+// PR c++/111284
+// { dg-do compile { target c++17 } }
+
+struct S {
+  S () = default;
+  constexpr S (const S &) noexcept : s{this} {}
+  constexpr S & operator= (const S &) noexcept { return *this; }
+  constexpr bool foo () const noexcept { return s == this; }
+  S *s = this;
+};
+
+constexpr bool
+bar (S x) noexcept
+{
+  return x.foo ();
+}
+
+static_assert (bar (S {}), "");
+static_assert ([] (S x) { return x.foo (); } (S {}), "");