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.
commit d00478c88d0fe712cae0955ec0b83f786e1f86f8
Author: Jason Merrill <ja...@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 > ());
+    }
+  };
+};

Reply via email to