aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-11-13 16:59:31 -0500
committerJason Merrill <jason@redhat.com>2021-11-15 02:50:45 -0500
commit37326651b439bac55d96fb5a43f4daf25e401eda (patch)
treee3fb0cf171f0a7c86f00f6e6f065af106eb32fbd /gcc
parentdaa9c6b015a33fa98af0ee7cd6919120248ab5f9 (diff)
downloadgcc-37326651b439bac55d96fb5a43f4daf25e401eda.zip
gcc-37326651b439bac55d96fb5a43f4daf25e401eda.tar.gz
gcc-37326651b439bac55d96fb5a43f4daf25e401eda.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.c27
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-89285-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C2
3 files changed, 22 insertions, 9 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 82a597d..c92db5d 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 656bc9c..ea44daa 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 3809e1f..26aab9b 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 "" }