public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Disallow reinterpret_cast in potential_constant_expression_1 (PR c++/89599)
@ 2019-03-07 19:32 Jakub Jelinek
  2019-03-08  4:44 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2019-03-07 19:32 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

The last testcase in the patch diagnoses invalid constexpr in the
ptr case, but doesn't for arr.
The array is constexpr, so we do:
      value = fold_non_dependent_expr (value);
      if (DECL_DECLARED_CONSTEXPR_P (decl)
          || (DECL_IN_AGGR_P (decl)
              && DECL_INITIALIZED_IN_CLASS_P (decl)))
        {
          /* Diagnose a non-constant initializer for constexpr variable or
             non-inline in-class-initialized static data member.  */
          if (!require_constant_expression (value))
            value = error_mark_node;
          else if (processing_template_decl)
            /* In a template we might not have done the necessary
               transformations to make value actually constant,
               e.g. extend_ref_init_temps.  */
            value = maybe_constant_init (value, decl, true);
          else
            value = cxx_constant_init (value, decl);
        }
but require_constant_expression returned true even when there are
REINTERPRET_CAST_Ps in the CONSTRUCTOR, and then cxx_constant_init
doesn't reject it, because:
    case CONSTRUCTOR:
      if (TREE_CONSTANT (t) && reduced_constant_expression_p (t))
        {
          /* Don't re-process a constant CONSTRUCTOR, but do fold it to
             VECTOR_CST if applicable.  */
          verify_constructor_flags (t);
          if (TREE_CONSTANT (t))
            return fold (t);
        }
      r = cxx_eval_bare_aggregate (ctx, t, lval,
                                   non_constant_p, overflow_p);
      break;
and reduced_constant_expression_p is true on it, so we never try to evaluate
it.

The following patch changes potential_constant_expression_1 to reject the
REINTERPRET_CAST_P, not really sure if that is the best way though.

In any case, bootstrapped/regtested on x86_64-linux and i686-linux.

2019-03-07  Jakub Jelinek  <jakub@redhat.com>

	PR c++/89599
	* constexpr.c (potential_constant_expression_1): Reject
	REINTERPRET_CAST_P NOP_EXPRs.

	* g++.dg/ubsan/vptr-4.C: Adjust expected diagnostics.
	* g++.dg/parse/array-size2.C: Likewise.
	* g++.dg/cpp0x/constexpr-89599.C: New test.

--- gcc/cp/constexpr.c.jj	2019-03-07 14:03:00.040329107 +0100
+++ gcc/cp/constexpr.c	2019-03-07 15:36:30.831721422 +0100
@@ -5997,6 +5997,13 @@ potential_constant_expression_1 (tree t,
       return true;
 
     case NOP_EXPR:
+      if (REINTERPRET_CAST_P (t))
+	{
+	  if (flags & tf_error)
+	    error_at (loc, "a reinterpret_cast is not a constant expression");
+	  return false;
+	}
+      /* FALLTHRU */
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
       /* -- a reinterpret_cast.  FIXME not implemented, and this rule
--- gcc/testsuite/g++.dg/ubsan/vptr-4.C.jj	2019-02-21 22:20:24.886099340 +0100
+++ gcc/testsuite/g++.dg/ubsan/vptr-4.C	2019-03-07 15:59:34.853143085 +0100
@@ -19,7 +19,7 @@ struct T : S {
 };
 
 constexpr T t;
-constexpr const T *p = t.foo ();	// { dg-message "expansion of" }
+constexpr const T *p = t.foo ();	// { dg-error "called in a constant expression" }
 
 template <typename U>
 struct V {
@@ -39,17 +39,16 @@ struct W : V<U> {
 };
 
 constexpr W<int> w;
-constexpr const W<int> *s = w.foo ();	// { dg-error "is not a constant expression" }
-// { dg-message "expansion of" "" { target *-*-* } .-1 }
+constexpr const W<int> *s = w.foo ();	// { dg-error "called in a constant expression" }
 
 template <typename U>
 int foo (void)
 {
   static constexpr T t;
-  static constexpr const T *p = t.foo ();	// { dg-message "expansion of" }
+  static constexpr const T *p = t.foo ();	// { dg-error "called in a constant expression" }
   static constexpr W<U> w;
-  static constexpr const W<U> *s = w.foo ();	// { dg-error "is not a constant expression" }
-  return t.b + w.b;				// { dg-message "expansion of" "" { target *-*-* } .-1 }
+  static constexpr const W<U> *s = w.foo ();	// { dg-error "called in a constant expression" }
+  return t.b + w.b;
 }
 
 int x = foo <char> ();
--- gcc/testsuite/g++.dg/parse/array-size2.C.jj	2018-11-29 23:11:40.225616846 +0100
+++ gcc/testsuite/g++.dg/parse/array-size2.C	2019-03-07 15:51:12.998330254 +0100
@@ -15,6 +15,8 @@ void
 foo (void)
 {
   char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "40:size of array .g. is not an integral constant-expression" }
+						      // { dg-error "narrowing conversion" "" { target c++11 } .-1 }
+						      // { dg-message "expression has a constant value but is not a C.. constant-expression" "" { target c++11 } .-2 }
   char h[(__SIZE_TYPE__) &((struct S *) 8)->b];	      // { dg-error "10:size of array .h. is not an integral constant-expression" }
   bar (g, h);
 }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C.jj	2019-03-07 16:04:43.526107447 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C	2019-03-07 16:04:14.519580648 +0100
@@ -0,0 +1,6 @@
+// PR c++/89599
+// { dg-do compile { target c++11 } }
+
+void foo (int x) {}
+constexpr void *arr[2] = { (void*) &foo, (void *) foo };// { dg-error "a reinterpret_cast is not a constant expression" }
+constexpr void *ptr = (void *) &foo;			// { dg-error "a reinterpret_cast is not a constant expression" }

	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [C++ PATCH] Disallow reinterpret_cast in potential_constant_expression_1 (PR c++/89599)
  2019-03-07 19:32 [C++ PATCH] Disallow reinterpret_cast in potential_constant_expression_1 (PR c++/89599) Jakub Jelinek
@ 2019-03-08  4:44 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2019-03-08  4:44 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 3/7/19 2:29 PM, Jakub Jelinek wrote:
> Hi!
> 
> The last testcase in the patch diagnoses invalid constexpr in the
> ptr case, but doesn't for arr.
> The array is constexpr, so we do:
>        value = fold_non_dependent_expr (value);
>        if (DECL_DECLARED_CONSTEXPR_P (decl)
>            || (DECL_IN_AGGR_P (decl)
>                && DECL_INITIALIZED_IN_CLASS_P (decl)))
>          {
>            /* Diagnose a non-constant initializer for constexpr variable or
>               non-inline in-class-initialized static data member.  */
>            if (!require_constant_expression (value))
>              value = error_mark_node;
>            else if (processing_template_decl)
>              /* In a template we might not have done the necessary
>                 transformations to make value actually constant,
>                 e.g. extend_ref_init_temps.  */
>              value = maybe_constant_init (value, decl, true);
>            else
>              value = cxx_constant_init (value, decl);
>          }
> but require_constant_expression returned true even when there are
> REINTERPRET_CAST_Ps in the CONSTRUCTOR, and then cxx_constant_init
> doesn't reject it, because:
>      case CONSTRUCTOR:
>        if (TREE_CONSTANT (t) && reduced_constant_expression_p (t))
>          {
>            /* Don't re-process a constant CONSTRUCTOR, but do fold it to
>               VECTOR_CST if applicable.  */
>            verify_constructor_flags (t);
>            if (TREE_CONSTANT (t))
>              return fold (t);
>          }
>        r = cxx_eval_bare_aggregate (ctx, t, lval,
>                                     non_constant_p, overflow_p);
>        break;
> and reduced_constant_expression_p is true on it, so we never try to evaluate
> it.
> 
> The following patch changes potential_constant_expression_1 to reject the
> REINTERPRET_CAST_P, not really sure if that is the best way though.

That seems right to me.  The patch is OK.

Jason

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-03-08  4:43 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-07 19:32 [C++ PATCH] Disallow reinterpret_cast in potential_constant_expression_1 (PR c++/89599) Jakub Jelinek
2019-03-08  4:44 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).