* [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).