diff mbox series

[pushed] c++: check constexpr constructor body

Message ID 20211115075124.3355269-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: check constexpr constructor body | expand

Commit Message

Jason Merrill Nov. 15, 2021, 7:51 a.m. UTC
The implicit constexpr patch revealed that our checks for constexpr
constructors that could possibly produce a constant value (which
otherwise are IFNDR) was failing to look at most of the function body.
Fixing that required some library tweaks.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	* constexpr.c (maybe_save_constexpr_fundef): Also check whether the
	body of a constructor is potentially constant.

libstdc++-v3/ChangeLog:

	* src/c++17/memory_resource.cc: Add missing constexpr.
	* include/experimental/internet: Only mark copy constructor
	as constexpr with __cpp_constexpr_dynamic_alloc.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1y/constexpr-89285-2.C: Expect error.
	* g++.dg/cpp1y/constexpr-89285.C: Adjust error.
---
 gcc/cp/constexpr.c                            | 27 ++++++++++++++-----
 .../g++.dg/cpp1y/constexpr-89285-2.C          |  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C  |  2 +-
 libstdc++-v3/src/c++17/memory_resource.cc     |  2 +-
 libstdc++-v3/include/experimental/internet    |  2 ++
 5 files changed, 25 insertions(+), 10 deletions(-)


base-commit: bd95d75f3412e1a7debab7c6c602ba409f274eb5
prerequisite-patch-id: 27a5ed4ace5d1a1b46b77a7be24baec6a2d6bdf3
diff mbox series

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 82a597d7bad..c92db5d413c 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -870,7 +870,9 @@  maybe_save_constexpr_fundef (tree fun)
       || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)))
     return;
 
-  if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
+  bool complain = !DECL_GENERATED_P (fun);
+
+  if (!is_valid_constexpr_fn (fun, complain))
     return;
 
   tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
@@ -883,15 +885,26 @@  maybe_save_constexpr_fundef (tree fun)
     }
 
   bool potential = potential_rvalue_constant_expression (massaged);
-  if (!potential && !DECL_GENERATED_P (fun))
+  if (!potential && complain)
     require_potential_rvalue_constant_expression (massaged);
 
-  if (DECL_CONSTRUCTOR_P (fun)
-      && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
-				     massaged, !DECL_GENERATED_P (fun)))
-    potential = false;
+  if (DECL_CONSTRUCTOR_P (fun) && potential)
+    {
+      if (cx_check_missing_mem_inits (DECL_CONTEXT (fun),
+				      massaged, complain))
+	potential = false;
+      else if (cxx_dialect > cxx11)
+	{
+	  /* What we got from massage_constexpr_body is pretty much just the
+	     ctor-initializer, also check the body.  */
+	  massaged = DECL_SAVED_TREE (fun);
+	  potential = potential_rvalue_constant_expression (massaged);
+	  if (!potential && complain)
+	    require_potential_rvalue_constant_expression (massaged);
+	}
+    }
 
-  if (!potential && !DECL_GENERATED_P (fun))
+  if (!potential && complain)
     return;
 
   constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C
index 656bc9cb7f1..ea44daa849e 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C
@@ -10,7 +10,7 @@  struct B {
     int *c = &x->a;
     while (*c)
       c = reinterpret_cast<int *>((reinterpret_cast<char *>(c) + *c));
-    *c = reinterpret_cast<char *>(this) - reinterpret_cast<char *>(c);
+    *c = reinterpret_cast<char *>(this) - reinterpret_cast<char *>(c); // { dg-error "reinterpret_cast" }
   }
 };
 struct C : A {
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C
index 3809e1f7a9f..26aab9b6a50 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C
@@ -17,4 +17,4 @@  struct C : A {
   B bar {this};
 };
 
-constexpr C foo {};	// { dg-message "expansion of" }
+constexpr C foo {};		// { dg-message "" }
diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc
index 1ba79903f87..9fc3bb754c1 100644
--- a/libstdc++-v3/src/c++17/memory_resource.cc
+++ b/libstdc++-v3/src/c++17/memory_resource.cc
@@ -603,7 +603,7 @@  namespace pmr
     void* pointer = nullptr;
     aligned_size<min> _M_size;
 
-    size_t size() const noexcept
+    constexpr size_t size() const noexcept
     {
       if (_M_size.value == size_t(-1)) [[unlikely]]
 	return size_t(-1);
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 65c97de07d9..95b8cdc9963 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -460,7 +460,9 @@  namespace ip
     // constructors:
     constexpr address() noexcept : _M_v4(), _M_is_v4(true) { }
 
+#if __cpp_constexpr_dynamic_alloc
     constexpr
+#endif
     address(const address& __a) noexcept : _M_uninit(), _M_is_v4(__a._M_is_v4)
     {
       if (_M_is_v4)