aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-03-28 12:13:50 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-03-28 12:13:50 -0400
commit62add5e145ffe3f87f93bb40e0d9ccbf20044420 (patch)
tree00c7516b10cc587b3cba7257e430c1e64a83a2e7
parent0309d28824f040972a212183b34c45d59449b529 (diff)
downloadgcc-62add5e145ffe3f87f93bb40e0d9ccbf20044420.zip
gcc-62add5e145ffe3f87f93bb40e0d9ccbf20044420.tar.gz
gcc-62add5e145ffe3f87f93bb40e0d9ccbf20044420.tar.bz2
Core 898
Core 898 * semantics.c (constexpr_fn_retval): New. Allow using-declaration and using-definition. (register_constexpr_fundef): Call it. From-SVN: r171611
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/semantics.c50
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-using.C27
4 files changed, 82 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3bbeddf..baaf94e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 41ab858..6906c1b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 863f599..35b8c53 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..fc794e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C
@@ -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");
+