Patchwork C++ PATCH for c++/56238 (ice-checking with static_cast)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 9, 2013, 8:36 p.m.
Message ID <5116B35D.8050500@redhat.com>
Download mbox | patch
Permalink /patch/219444/
State New
Headers show

Comments

Jason Merrill - Feb. 9, 2013, 8:36 p.m.
The code in build_non_dependent_expr has caught a number of issues in 
the compiler; this is another case that fold_non_dependent_expr wasn't 
properly recognizing as dependent.  I think we want to use 
instantiation_dependent there going forward, but for 4.8 I think let's 
just check it in the ENABLE_CHECKING code.  Making this change exposed a 
couple of bugs in instantiation_dependent_r: You can't use TREE_OPERAND 
on TRAIT_EXPR, and we need to treat BIND_EXPRs as dependent because it 
contains statements.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit d00478c88d0fe712cae0955ec0b83f786e1f86f8
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Feb 7 12:48:08 2013 -0500

    	PR c++/56238
    	* pt.c (build_non_dependent_expr): Don't try to fold
    	instantiation-dependent expressions.
    	(instantiation_dependent_r) [TRAIT_EXPR]: Split out.
    	[BIND_EXPR]: Treat as dependent.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index aa127ed..29664ea 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19863,16 +19863,13 @@  instantiation_dependent_r (tree *tp, int *walk_subtrees,
     case ALIGNOF_EXPR:
     case TYPEID_EXPR:
     case AT_ENCODE_EXPR:
-    case TRAIT_EXPR:
       {
 	tree op = TREE_OPERAND (*tp, 0);
 	if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
 	  op = TREE_TYPE (op);
 	if (TYPE_P (op))
 	  {
-	    if (dependent_type_p (op)
-		|| (code == TRAIT_EXPR
-		    && dependent_type_p (TREE_OPERAND (*tp, 1))))
+	    if (dependent_type_p (op))
 	      return *tp;
 	    else
 	      {
@@ -19883,6 +19880,13 @@  instantiation_dependent_r (tree *tp, int *walk_subtrees,
 	break;
       }
 
+    case TRAIT_EXPR:
+      if (dependent_type_p (TRAIT_EXPR_TYPE1 (*tp))
+	  || dependent_type_p (TRAIT_EXPR_TYPE2 (*tp)))
+	return *tp;
+      *walk_subtrees = false;
+      return NULL_TREE;
+
     case COMPONENT_REF:
       if (TREE_CODE (TREE_OPERAND (*tp, 1)) == IDENTIFIER_NODE)
 	/* In a template, finish_class_member_access_expr creates a
@@ -19898,6 +19902,10 @@  instantiation_dependent_r (tree *tp, int *walk_subtrees,
       else
 	break;
 
+      /* Treat statement-expressions as dependent.  */
+    case BIND_EXPR:
+      return *tp;
+
     default:
       break;
     }
@@ -20341,9 +20349,10 @@  build_non_dependent_expr (tree expr)
   tree inner_expr;
 
 #ifdef ENABLE_CHECKING
-  /* Try to get a constant value for all non-type-dependent expressions in
+  /* Try to get a constant value for all non-dependent expressions in
       order to expose bugs in *_dependent_expression_p and constexpr.  */
-  if (cxx_dialect >= cxx0x)
+  if (cxx_dialect >= cxx0x
+      && !instantiation_dependent_expression_p (expr))
     maybe_constant_value (fold_non_dependent_expr_sfinae (expr, tf_none));
 #endif
 
diff --git a/gcc/testsuite/g++.dg/template/cast2.C b/gcc/testsuite/g++.dg/template/cast2.C
new file mode 100644
index 0000000..0ce55f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/cast2.C
@@ -0,0 +1,13 @@ 
+// PR c++/56238
+
+class A
+{
+  template < typename T > T& get ();
+  template < typename T > class B
+  {
+    void RemovePoint (A& value)
+    {
+      static_cast < double >(value.get < T > ());
+    }
+  };
+};