diff mbox

[C++] PR 51225

Message ID 4F10750E.2070606@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Jan. 13, 2012, 6:16 p.m. UTC
Hi,

in C++11 mode after erroring out for an undeclared name we can easily 
end up calling cxx_eval_constant_expression on a CAST_EXPR etc, which 
has error_mark_node as argument.

The latter trees are currently completely unhandled by 
cxx_eval_constant_expression, thus in order to avoid such ICEs on 
invalid it seems safe setting *non_constant_p = true and returning back 
t, as we do when t itself is error_mark_node, and asserting errorcount. 
The resulting diagnostics is pretty terse.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////
/cp
2012-01-13  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51225
	* semantics.c (cxx_eval_constant_expression): Handle CAST_EXPR,
	CONST_CAST_EXPR, STATIC_CAST_EXPR, REINTERPRET_CAST_EXPR,
	IMPLICIT_CONV_EXPR.

/testsuite
2012-01-13  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51225
	* g++.dg/cpp0x/pr51225.C: New.

Comments

Jason Merrill Jan. 13, 2012, 8 p.m. UTC | #1
On 01/13/2012 01:16 PM, Paolo Carlini wrote:
> in C++11 mode after erroring out for an undeclared name we can easily
> end up calling cxx_eval_constant_expression on a CAST_EXPR etc, which
> has error_mark_node as argument.

We should never pass uninstantiated trees to 
cxx_eval_constant_expression; they need to go through tsubst first.

Jason
Paolo Carlini Jan. 13, 2012, 8:57 p.m. UTC | #2
Hi,
> On 01/13/2012 01:16 PM, Paolo Carlini wrote:
>> in C++11 mode after erroring out for an undeclared name we can easily
>> end up calling cxx_eval_constant_expression on a CAST_EXPR etc, which
>> has error_mark_node as argument.
>
> We should never pass uninstantiated trees to 
> cxx_eval_constant_expression; they need to go through tsubst first.
Actually, I'm pretty sure you explained that already in the past, and I 
have more generally a deja-vu...

Anyway, the reason we are not tsubst-ing such trees  - eg, a CAST_EXPR 
on a single element TREE_LIST as argument, with error_mark_node as value 
- is that potential_constant_expression is false in 
fold_non_dependent_expr_sfinae, thus tsubst_copy_and_build is not called 
at all. The reason why potential_constant_expression is false is that 
recursion leads to the argument as a TREE_LIST and then the next call to 
the error_mark_node itself, which eventually leads to false.

Back to my deja-vu feeling, I'm pretty sure that a few weeks ago I 
experimented with changing potential_constant_expression to actually 
return *true* for error_mark_node, and that worked for a similar problem.

But maybe my few lines of analysis already inspire you something?

Thanks,
Paolo.
Jason Merrill Jan. 14, 2012, 2:15 a.m. UTC | #3
On 01/13/2012 03:57 PM, Paolo Carlini wrote:
> Anyway, the reason we are not tsubst-ing such trees - eg, a CAST_EXPR on
> a single element TREE_LIST as argument, with error_mark_node as value -
> is that potential_constant_expression is false in
> fold_non_dependent_expr_sfinae, thus tsubst_copy_and_build is not called
> at all.

We also shouldn't call cxx_eval_constant_expression if 
potential_constant_expression is false.

Jason
diff mbox

Patch

Index: testsuite/g++.dg/cpp0x/pr51225.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr51225.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr51225.C	(revision 0)
@@ -0,0 +1,14 @@ 
+// PR c++/51225
+// { dg-options "-std=c++0x" }
+
+template<int> struct A {};
+
+template<typename> void foo()
+{
+  A<int(x)> a; // { dg-error "not declared|invalid type" }
+}
+
+template<typename> struct bar
+{
+  static constexpr A<1> a = A<1>(x); // { dg-error "not declared" }
+};
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 183153)
+++ cp/semantics.c	(working copy)
@@ -7769,6 +7769,15 @@  cxx_eval_constant_expression (const constexpr_call
 	 used, and they can't do anything with it, so just return it.  */
       return t;
 
+    case CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
+      gcc_assert (errorcount);
+      *non_constant_p = true;
+      return t;
+
     case LAMBDA_EXPR:
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR: