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 > ());
+ }
+ };
+};