[pushed] c++: check constexpr constructor body
Commit Message
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
@@ -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};
@@ -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 {
@@ -17,4 +17,4 @@ struct C : A {
B bar {this};
};
-constexpr C foo {}; // { dg-message "expansion of" }
+constexpr C foo {}; // { dg-message "" }
@@ -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);
@@ -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)