2016-04-26 Nathan Sidwell <nathan@acm.org>
cp/
* constexpr.c (get_fundef_copy): Use the original function for
non-recursive evaluations.
(save_fundef_copy): Always expect a slot to be available.
testsuite/
* g++.dg/cpp0x/constexpr-recursion3.C: New.
* g++.dg/ubsan/pr63956.C: Adjust error location.
===================================================================
@@ -989,7 +989,8 @@ maybe_initialize_fundef_copies_table ()
}
/* Reuse a copy or create a new unshared copy of the function FUN.
- Return this copy. */
+ Return this copy. We use a TREE_LIST whose PURPOSE is body, VALUE
+ is parms, TYPE is result. */
static tree
get_fundef_copy (tree fun)
@@ -997,15 +998,26 @@ get_fundef_copy (tree fun)
maybe_initialize_fundef_copies_table ();
tree copy;
- tree *slot = fundef_copies_table->get (fun);
- if (slot == NULL || *slot == NULL_TREE)
+ bool existed;
+ tree *slot = &fundef_copies_table->get_or_insert (fun, &existed);
+
+ if (!existed)
+ {
+ /* There is no cached function available, or in use. We can use
+ the function directly. That the slot is now created records
+ that this function is now in use. */
+ copy = build_tree_list (DECL_SAVED_TREE (fun), DECL_ARGUMENTS (fun));
+ TREE_TYPE (copy) = DECL_RESULT (fun);
+ }
+ else if (*slot == NULL_TREE)
{
+ /* We've already used the function itself, so make a copy. */
copy = build_tree_list (NULL, NULL);
- /* PURPOSE is body, VALUE is parms, TYPE is result. */
TREE_PURPOSE (copy) = copy_fn (fun, TREE_VALUE (copy), TREE_TYPE (copy));
}
else
{
+ /* We have a cached function available. */
copy = *slot;
*slot = TREE_CHAIN (copy);
}
@@ -1013,12 +1025,14 @@ get_fundef_copy (tree fun)
return copy;
}
-/* Save the copy COPY of function FUN for later reuse by get_fundef_copy(). */
+/* Save the copy COPY of function FUN for later reuse by
+ get_fundef_copy(). By construction, there will always be an entry
+ to find. */
static void
save_fundef_copy (tree fun, tree copy)
{
- tree *slot = &fundef_copies_table->get_or_insert (fun, NULL);
+ tree *slot = fundef_copies_table->get (fun);
TREE_CHAIN (copy) = *slot;
*slot = copy;
}
===================================================================
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int Foo (int i)
+{
+ return (i ? Foo (i - 1): 0) + i;
+}
+
+static int a = Foo (0);
+static int b = Foo (1);
+static int d = Foo (3);
+static int c = Foo (2);
+static int e = Foo (4);
+static int g = Foo (6);
+static int f = Foo (5);
===================================================================
@@ -92,7 +92,7 @@ constexpr int
fn6 (const int &a, int b)
{
if (b != 2)
- b = a;
+ b = a; // { dg-error "is not a constant expression" }
return b;
}
@@ -106,7 +106,7 @@ fn7 (const int *a, int b)
constexpr int n1 = 7;
constexpr int n2 = fn7 (&n1, 5);
-constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "is not a constant expression" }
+constexpr int n3 = fn7 ((const int *) 0, 8);
constexpr int
fn8 (int i)