diff mbox

PR c++/77539

Message ID 8ffdc7e6-bd7c-0bbd-7b75-c8c44402459a@acm.org
State New
Headers show

Commit Message

Nathan Sidwell Sept. 14, 2016, 2:30 p.m. UTC
I've committed this backport to the gcc-6 branch.  I'll commit the new testcase 
to trunk, so we don't regress in future.

nathan
diff mbox

Patch

2016-09-14  Nathan Sidwell  <nathan@acm.org>

	cp/
	PR c++/77539
	* constexpr.c (get_fundef_copy): Use the original function for
	non-recursive evaluations.
	(save_fundef_copy): Always expect a slot to be available.

	testsuite/
	PR c++/77539
	* g++.dg/cpp0x/constexpr-recursion3.C: New.
	* g++.dg/ubsan/pr63956.C: Adjust error location.
	* g++.dg/cpp1y/pr77539.C: New.

Index: cp/constexpr.c
===================================================================
--- cp/constexpr.c	(revision 240079)
+++ cp/constexpr.c	(working copy)
@@ -994,7 +994,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)
@@ -1002,15 +1003,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);
     }
@@ -1018,12 +1030,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;
 }
Index: testsuite/g++.dg/cpp0x/constexpr-recursion3.C
===================================================================
--- testsuite/g++.dg/cpp0x/constexpr-recursion3.C	(nonexistent)
+++ testsuite/g++.dg/cpp0x/constexpr-recursion3.C	(working 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);
Index: testsuite/g++.dg/cpp1y/pr77539.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr77539.C	(nonexistent)
+++ testsuite/g++.dg/cpp1y/pr77539.C	(working copy)
@@ -0,0 +1,14 @@ 
+// PR c++/77539
+// { dg-do compile { target c++14 } }
+
+constexpr int foobar()
+{
+  int array[100] = {};
+  int *ar = array;
+  if (ar == nullptr) // Error...
+  {
+    return 0;
+  }
+  return 1;
+}
+static_assert(foobar(),"");
Index: testsuite/g++.dg/ubsan/pr63956.C
===================================================================
--- testsuite/g++.dg/ubsan/pr63956.C	(revision 240079)
+++ testsuite/g++.dg/ubsan/pr63956.C	(working copy)
@@ -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)