Patchwork C++ PATCH for c++/56998 (ICE with call in C++03 mode)

login
register
mail settings
Submitter Jason Merrill
Date May 13, 2013, 7:25 p.m.
Message ID <51913E17.4050000@redhat.com>
Download mbox | patch
Permalink /patch/243505/
State New
Headers show

Comments

Jason Merrill - May 13, 2013, 7:25 p.m.
In this testcase, since one of the overloads takes a pointer, we need to 
check whether the argument is a valid null pointer constant.  In C++11 
only an integer literal can be a null pointer constant of integral type, 
but in C++03 we need to handle other integer constant expressions.  Here 
we were passing the call expression into value_dependent_expression_p, 
but in C++03 mode that function expects its argument to be a constant 
expression, and the expression wasn't filtered out by 
potential_constant_expression.  The simplest solution is to just check 
TREE_SIDE_EFFECTS since in C++03 mode an expression with side-effects 
can't be a constant expression (unlike in C++11, where constexpr 
function substitution can produce a constant expression from one with 
TREE_SIDE_EFFECTS).

Tested x86_64-pc-linux-gnu, applying to trunk and 4.8.
Jakub Jelinek - May 13, 2013, 7:36 p.m.
On Mon, May 13, 2013 at 03:25:11PM -0400, Jason Merrill wrote:
> In this testcase, since one of the overloads takes a pointer, we
> need to check whether the argument is a valid null pointer constant.
> In C++11 only an integer literal can be a null pointer constant of
> integral type, but in C++03 we need to handle other integer constant
> expressions.  Here we were passing the call expression into
> value_dependent_expression_p, but in C++03 mode that function
> expects its argument to be a constant expression, and the expression
> wasn't filtered out by potential_constant_expression.  The simplest
> solution is to just check TREE_SIDE_EFFECTS since in C++03 mode an
> expression with side-effects can't be a constant expression (unlike
> in C++11, where constexpr function substitution can produce a
> constant expression from one with TREE_SIDE_EFFECTS).

What about the 4 other
maybe_constant_value on fold_non_dependent_expr_sfinae (something, tf_none)
calls in typeck.c (two for -Wdiv-by-zero and two for shift diagnostics)?
Should that be if (cxx_dialect >= cxx0x || !TREE_SIDE_EFFECTS (t)) guarded
(or wrapped into some helper function that will do all of
tree some_good_name (tree t)
{
  if (cxx_dialect < cxx0x && TREE_SIDE_EFFECTS (t))
    return t;
  t = fold_non_dependent_expr_sfinae (t, tf_none);
  return maybe_constant_value (t);
}
Plus there is one guarded by ENABLE_CHECKING in pt.c.

	Jakub

Patch

commit bd25166552f6aa94b8da3ffea0201213e8057b17
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 13 13:34:31 2013 -0400

    	PR c++/56998
    	* call.c (null_ptr_cst_p): An expression with side-effects can't
    	be a C++03 null pointer constant.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bd8f531..9f3a50d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -554,7 +554,7 @@  null_ptr_cst_p (tree t)
   if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)))
     {
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
-      if (cxx_dialect < cxx0x)
+      if (cxx_dialect < cxx0x && !TREE_SIDE_EFFECTS (t))
 	t = maybe_constant_value (fold_non_dependent_expr_sfinae (t, tf_none));
       STRIP_NOPS (t);
       if (integer_zerop (t) && !TREE_OVERFLOW (t))
diff --git a/gcc/testsuite/g++.dg/template/overload13.C b/gcc/testsuite/g++.dg/template/overload13.C
new file mode 100644
index 0000000..d41ccd0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/overload13.C
@@ -0,0 +1,16 @@ 
+// PR c++/56998
+
+class Secret;
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];
+
+struct C
+{
+  int val() { return 42; }
+};
+
+template <typename T>
+unsigned f()
+{
+  return sizeof(IsNullLiteralHelper(C().val()));
+}