[gcc r12-5256] c++: check constexpr constructor body

Jason Merrill jason@gcc.gnu.org
Mon Nov 15 07:52:41 GMT 2021


https://gcc.gnu.org/g:37326651b439bac55d96fb5a43f4daf25e401eda

commit r12-5256-g37326651b439bac55d96fb5a43f4daf25e401eda
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Nov 13 16:59:31 2021 -0500

    c++: check constexpr constructor body
    
    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.
    
    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.

Diff:
---
 gcc/cp/constexpr.c                             | 27 +++++++++++++++++++-------
 gcc/testsuite/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(-)

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)


More information about the Libstdc++-cvs mailing list