re PR c++/18354 (expression "+1" not considered constant (as template parameter).)
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 22 Nov 2004 12:15:53 +0000 (12:15 +0000)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Mon, 22 Nov 2004 12:15:53 +0000 (12:15 +0000)
PR c++/18354
* typeck.c (build_unary_op) <CONVERT_EXPR, NEGATE_EXPR>: Unify code.
Make sure the result is always a rvalue.

PR c++/18354
* g++.dg/template/nontype11.C: New test.

From-SVN: r91008

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/nontype11.C [new file with mode: 0644]

index ddb1e99..bcb9d21 100644 (file)
@@ -1,3 +1,9 @@
+2004-11-22  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/18354
+       * typeck.c (build_unary_op) <CONVERT_EXPR, NEGATE_EXPR>: Unify code.
+       Make sure the result is always a rvalue.
+
 2004-11-16  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
        * decl.c (start_preparsed_function): Call check_function_type even
index b1a85d5..4caf051 100644 (file)
@@ -3741,26 +3741,30 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
 
   switch (code)
     {
+    /* CONVERT_EXPR stands for unary plus in this context.  */
     case CONVERT_EXPR:
-      /* This is used for unary plus, because a CONVERT_EXPR
-        is enough to prevent anybody from looking inside for
-        associativity, but won't generate any code.  */
-      if (!(arg = build_expr_type_conversion
-           (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, true)))
-       errstring = "wrong type argument to unary plus";
-      else
-       {
-         if (!noconvert)
-           arg = default_conversion (arg);
-         arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
-       }
-      break;
-
     case NEGATE_EXPR:
-      if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
-       errstring = "wrong type argument to unary minus";
-      else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
-       arg = perform_integral_promotions (arg);
+      {\r
+       int flags = WANT_ARITH | WANT_ENUM;\r
+       /* Unary plus (but not unary minus) is allowed on pointers.  */\r
+       if (code == CONVERT_EXPR)\r
+         flags |= WANT_POINTER;\r
+       arg = build_expr_type_conversion (flags, arg, true);\r
+       if (!arg)
+         errstring = (code == NEGATE_EXPR
+                      ? "wrong type argument to unary minus"
+                      : "wrong type argument to unary plus");
+       else
+         {
+           if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
+             arg = perform_integral_promotions (arg);
+
+           /* Make sure the result is not a lvalue: a unary plus or minus
+              expression is always a rvalue.  */
+           if (real_lvalue_p (arg))
+             arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
+         }
+      }
       break;
 
     case BIT_NOT_EXPR:
index b9ec394..3601740 100644 (file)
@@ -1,3 +1,8 @@
+2004-11-22  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/18354
+       * g++.dg/template/nontype11.C: New test.
+
 2004-11-21  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/18520
diff --git a/gcc/testsuite/g++.dg/template/nontype11.C b/gcc/testsuite/g++.dg/template/nontype11.C
new file mode 100644 (file)
index 0000000..d52eb9a
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// Origin: <fsm at robots dot ox dot ac dot uk>
+// PR c++/18354: Unary plus should not be wrapped in NON_LVALUE_EXPR
+
+template <int N>
+struct X { };
+
+const int n = 1;
+
+void f()
+{
+  X< 1> a;
+  X<-1> b;
+  X<+1> c;
+}
+
+void g()
+{
+  X< n> a;
+  X<-n> b;
+  X<+n> c;
+}