[RFC] Add UNARY_PLUS_EXPR to C++ front-end
Roger Sayle
roger@eyesopen.com
Thu May 26 05:43:00 GMT 2005
The following is a request for comment, or more accurately a request
for help, from the C++ folks for a patch to introduce a new front-end
tree code for C++'s unary plus operator.
Currently the g++ front-end abuses the semantics of the middle-end's
CONVERT_EXPR tree code to represent unary plus. This isn't an issue
for the C front-end, which also temporarily misuses CONVERT_EXPR for
the same reason, but the use of default conversions followed by a
call to fold_build1 means that we never actually allocate a node to
represent it. In C++, however, the deferral of folding until after
template instantiation, means that in numerous places the front-end
must preserve and interpret CONVERT_EXPR as a unary plus instead of
as a conversion operator.
In an attempt to clean this up, and more accurately represent the
user source code in the front-end's trees, the following patch introduces
a new UNARY_PLUS_EXPR tree code identical to the one used by the Java
front-end.
Now for the catch. There's always a catch! The following patch
passes a full top-level "make -k check", but with a single new
regression in the g++ testsuite...
FAIL: g++.dg/template/nontype11.C (test for excess errors)
which fails due to the error message:
nontype11.C:14: error: '+1' is not a valid template argument for type
'int' because it is a non-constant expression
The problem is that at template instantiation time, we're not folding
UNARY_PLUS_EXPR of an INTEGER_CST to just an INTEGER_CST soon enough.
Unfortunately, my "g++ fu" isn't strong enough to work out which one
or two line change to the template instantiation code required to replace
UNARY_PLUS_EXPR with it's TREE_OPERAND (t, 0) at the appropriate point.
There are several places this could be done, but I thought I'd ask the
list and solicit help for this final piece.
As mentioned above, the following patch has been bootstrapped and
regression tested on an x86_64-unknown-linux-gnu, all default
languages, and regression tested with a top-level "make -k check"
with only a single new failure, as described above. Although better
representation of C++ semantics in the front-end is already a g++
goal, this change is also part of/blocking a much larger middle-end
clean-up I've been working on.
Any advice? Co-authors wanted. Pretty please.
2005-05-25 Roger Sayle <roger@eyesopen.com>
* cp-tree.def (UNARY_PLUS_EXPR): New C++ unary tree code.
* parser.c (cp_parser_unary_expression): Use UNARY_PLUS_EXPR instead
of CONVERT_EXPR.
(cp_parser_unary_expression): Likewise.
* typeck.c (build_unary_op): Likewise.
* call.c (add_builtin_candidate, build_new_op): Likewise.
* error.c (dump_expr): Likewise.
* pt.c (tsubst_copy, tsubst_copy_and_build): Likewise.
* cp-gimplify.c (cp_gimplify_expr): Handle UNARY_PLUS_EXPR like a
conversion, if the result and argument types differ.
Index: cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.101
diff -c -3 -p -r1.101 cp-tree.def
*** cp-tree.def 25 Apr 2005 19:03:36 -0000 1.101
--- cp-tree.def 24 May 2005 23:23:54 -0000
*************** DEFTREECODE (ALIGNOF_EXPR, "alignof_expr
*** 340,345 ****
--- 340,349 ----
STMT_EXPR_STMT is the statement given by the expression. */
DEFTREECODE (STMT_EXPR, "stmt_expr", tcc_expression, 1)
+ /* Unary plus. Operand 0 is the expression to which the unary plus
+ is applied. */
+ DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1)
+
/*
Local variables:
mode:c
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.331
diff -c -3 -p -r1.331 parser.c
*** parser.c 19 May 2005 03:05:46 -0000 1.331
--- parser.c 24 May 2005 23:23:57 -0000
*************** cp_parser_unary_expression (cp_parser *p
*** 4873,4879 ****
non_constant_p = (unary_operator == PREINCREMENT_EXPR
? "`++'" : "`--'");
/* Fall through. */
! case CONVERT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
expression = finish_unary_op_expr (unary_operator, cast_expression);
--- 4873,4879 ----
non_constant_p = (unary_operator == PREINCREMENT_EXPR
? "`++'" : "`--'");
/* Fall through. */
! case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
expression = finish_unary_op_expr (unary_operator, cast_expression);
*************** cp_parser_unary_operator (cp_token* toke
*** 4909,4915 ****
return ADDR_EXPR;
case CPP_PLUS:
! return CONVERT_EXPR;
case CPP_MINUS:
return NEGATE_EXPR;
--- 4909,4915 ----
return ADDR_EXPR;
case CPP_PLUS:
! return UNARY_PLUS_EXPR;
case CPP_MINUS:
return NEGATE_EXPR;
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.628
diff -c -3 -p -r1.628 typeck.c
*** typeck.c 17 May 2005 20:05:24 -0000 1.628
--- typeck.c 24 May 2005 23:23:59 -0000
*************** build_unary_op (enum tree_code code, tre
*** 3692,3704 ****
switch (code)
{
! /* CONVERT_EXPR stands for unary plus in this context. */
! case CONVERT_EXPR:
case NEGATE_EXPR:
{
int flags = WANT_ARITH | WANT_ENUM;
/* Unary plus (but not unary minus) is allowed on pointers. */
! if (code == CONVERT_EXPR)
flags |= WANT_POINTER;
arg = build_expr_type_conversion (flags, arg, true);
if (!arg)
--- 3692,3703 ----
switch (code)
{
! case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
{
int flags = WANT_ARITH | WANT_ENUM;
/* Unary plus (but not unary minus) is allowed on pointers. */
! if (code == UNARY_PLUS_EXPR)
flags |= WANT_POINTER;
arg = build_expr_type_conversion (flags, arg, true);
if (!arg)
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.535
diff -c -3 -p -r1.535 call.c
*** call.c 23 Apr 2005 21:28:47 -0000 1.535
--- call.c 24 May 2005 23:24:00 -0000
*************** add_builtin_candidate (struct z_candidat
*** 1652,1658 ****
T operator+(T);
T operator-(T); */
! case CONVERT_EXPR: /* unary + */
if (TREE_CODE (type1) == POINTER_TYPE)
break;
case NEGATE_EXPR:
--- 1652,1658 ----
T operator+(T);
T operator-(T); */
! case UNARY_PLUS_EXPR: /* unary + */
if (TREE_CODE (type1) == POINTER_TYPE)
break;
case NEGATE_EXPR:
*************** build_new_op (enum tree_code code, int f
*** 3848,3854 ****
case TRUTH_ORIF_EXPR:
return cp_build_binary_op (code, arg1, arg2);
! case CONVERT_EXPR:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
--- 3848,3854 ----
case TRUTH_ORIF_EXPR:
return cp_build_binary_op (code, arg1, arg2);
! case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
Index: error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.280
diff -c -3 -p -r1.280 error.c
*** error.c 24 Mar 2005 07:20:33 -0000 1.280
--- error.c 24 May 2005 23:24:00 -0000
*************** dump_expr (tree t, int flags)
*** 1511,1517 ****
pp_cxx_right_bracket (cxx_pp);
break;
! case CONVERT_EXPR:
if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
{
pp_cxx_left_paren (cxx_pp);
--- 1511,1517 ----
pp_cxx_right_bracket (cxx_pp);
break;
! case UNARY_PLUS_EXPR:
if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
{
pp_cxx_left_paren (cxx_pp);
Index: pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.997
diff -c -3 -p -r1.997 pt.c
*** pt.c 17 May 2005 20:05:18 -0000 1.997
--- pt.c 24 May 2005 23:24:03 -0000
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 7802,7808 ****
case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
case ADDR_EXPR:
! case CONVERT_EXPR: /* Unary + */
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
case ARROW_EXPR:
--- 7802,7808 ----
case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
case ADDR_EXPR:
! case UNARY_PLUS_EXPR: /* Unary + */
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
case ARROW_EXPR:
*************** tsubst_copy_and_build (tree t,
*** 8483,8489 ****
case BIT_NOT_EXPR:
case ABS_EXPR:
case TRUTH_NOT_EXPR:
! case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
--- 8483,8489 ----
case BIT_NOT_EXPR:
case ABS_EXPR:
case TRUTH_NOT_EXPR:
! case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
Index: cp-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-gimplify.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 cp-gimplify.c
*** cp-gimplify.c 25 Apr 2005 19:03:36 -0000 1.19
--- cp-gimplify.c 24 May 2005 23:24:03 -0000
*************** cp_gimplify_expr (tree *expr_p, tree *pr
*** 557,562 ****
--- 557,572 ----
ret = GS_OK;
break;
+ case UNARY_PLUS_EXPR:
+ {
+ tree arg = TREE_OPERAND (*expr_p, 0);
+ tree type = TREE_TYPE (*expr_p);
+ *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
+ : arg;
+ ret = GS_OK;
+ }
+ break;
+
default:
ret = c_gimplify_expr (expr_p, pre_p, post_p);
break;
Roger
--
More information about the Gcc-patches
mailing list