Core 898
authorJason Merrill <jason@redhat.com>
Mon, 28 Mar 2011 16:13:50 +0000 (12:13 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 28 Mar 2011 16:13:50 +0000 (12:13 -0400)
Core 898
* semantics.c (constexpr_fn_retval): New.  Allow using-declaration
and using-definition.
(register_constexpr_fundef): Call it.

From-SVN: r171611

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-using.C [new file with mode: 0644]

index 3bbeddf..baaf94e 100644 (file)
@@ -1,5 +1,10 @@
 2011-03-28  Jason Merrill  <jason@redhat.com>
 
+       Core 898
+       * semantics.c (constexpr_fn_retval): New.  Allow using-declaration
+       and using-definition.
+       (register_constexpr_fundef): Call it.
+
        * except.c (build_noexcept_spec): Call cxx_constant_value after
        converting to bool.
 
index 41ab858..6906c1b 100644 (file)
@@ -5585,6 +5585,52 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
     return error_mark_node;
 }
 
+/* Subroutine of register_constexpr_fundef.  BODY is the body of a function
+   declared to be constexpr, or a sub-statement thereof.  Returns the
+   return value if suitable, error_mark_node for a statement not allowed in
+   a constexpr function, or NULL_TREE if no return value was found.  */
+
+static tree
+constexpr_fn_retval (tree body)
+{
+  switch (TREE_CODE (body))
+    {
+    case STATEMENT_LIST:
+      {
+       tree_stmt_iterator i;
+       tree expr = NULL_TREE;
+       for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
+         {
+           tree s = constexpr_fn_retval (tsi_stmt (i));
+           if (s == error_mark_node)
+             return error_mark_node;
+           else if (s == NULL_TREE)
+             /* Keep iterating.  */;
+           else if (expr)
+             /* Multiple return statements.  */
+             return error_mark_node;
+           else
+             expr = s;
+         }
+       return expr;
+      }
+
+    case RETURN_EXPR:
+      return unshare_expr (TREE_OPERAND (body, 0));
+
+    case DECL_EXPR:
+      if (TREE_CODE (DECL_EXPR_DECL (body)) == USING_DECL)
+       return NULL_TREE;
+      return error_mark_node;
+
+    case USING_STMT:
+      return NULL_TREE;
+
+    default:
+      return error_mark_node;
+    }
+}
+
 /* We are processing the definition of the constexpr function FUN.
    Check that its BODY fulfills the propriate requirements and
    enter it in the constexpr function definition table.
@@ -5610,13 +5656,13 @@ register_constexpr_fundef (tree fun, tree body)
        body = TREE_OPERAND (body, 0);
       if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
         body = TREE_OPERAND (body, 0);
-      if (TREE_CODE (body) != RETURN_EXPR)
+      body = constexpr_fn_retval (body);
+      if (body == NULL_TREE || body == error_mark_node)
         {
           error ("body of constexpr function %qD not a return-statement", fun);
           DECL_DECLARED_CONSTEXPR_P (fun) = false;
           return NULL;
         }
-      body = unshare_expr (TREE_OPERAND (body, 0));
     }
 
   if (!potential_rvalue_constant_expression (body))
index 863f599..35b8c53 100644 (file)
@@ -1,5 +1,7 @@
 2011-03-28  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/constexpr-using.C: New.
+
        * g++.dg/cpp0x/constexpr-noexcept.C: New.
 
 2011-03-28  H.J. Lu  <hongjiu.lu@intel.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C
new file mode 100644 (file)
index 0000000..fc794e9
--- /dev/null
@@ -0,0 +1,27 @@
+// Core issue 898
+// { dg-options -std=c++0x }
+
+namespace N { const int i = 42; }
+namespace M { const int j = 42; }
+
+constexpr int g() {
+  using namespace N;
+  using M::j;
+  static_assert (i == 42, "i == 42");
+  return i + j;
+}
+
+template <class T>
+constexpr int h() {
+  using namespace N;
+  using M::j;
+  static_assert (i == 42, "i == 42");
+  return i + j;
+}
+
+constexpr int i = g();
+constexpr int i2 = h<int>();
+
+static_assert (i == 84, "i == 84");
+static_assert (i2 == 84, "i2 == 84");
+