diff options
author | Jason Merrill <jason@redhat.com> | 2022-03-22 01:10:44 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-03-24 14:31:16 -0400 |
commit | 346ab5a54a831ad9c78afcbd8dfe98e0e07e3070 (patch) | |
tree | 36735be4a7405f057480072aef7ba5231740aaef /gcc/cp/method.cc | |
parent | f0530882d99abc410bb080051aa04e5cea848f18 (diff) | |
download | gcc-346ab5a54a831ad9c78afcbd8dfe98e0e07e3070.zip gcc-346ab5a54a831ad9c78afcbd8dfe98e0e07e3070.tar.gz gcc-346ab5a54a831ad9c78afcbd8dfe98e0e07e3070.tar.bz2 |
c++: delayed parse DMI [PR96645]
With the changes for PR81359 and PR88368 to make get_nsdmi errors be treated
as substitution failure, we have the problem that if we check
std::is_default_constructible for a complete class that still has unparsed
default member initializers, we get an answer (false) that will be wrong
once the DMIs have been parsed. The traits avoid this problem for regular
incomplete classes by giving an error if the operand is incomplete; we
should do the same if get_nsdmi is going to fail due to unparsed DMI.
PR c++/96645
gcc/cp/ChangeLog:
* cp-tree.h (type_has_default_ctor_to_be_synthesized): Declare.
* class.cc (type_has_default_ctor_to_be_synthesized): New.
(type_has_non_user_provided_default_constructor_1): Support it.
(type_has_non_user_provided_default_constructor): Now a wrapper.
* method.cc (complain_about_unparsed_dmi): New.
(constructible_expr): Call it.
gcc/testsuite/ChangeLog:
* g++.dg/ext/is_constructible3.C: Expect error.
* g++.dg/ext/is_constructible7.C: New test.
Diffstat (limited to 'gcc/cp/method.cc')
-rw-r--r-- | gcc/cp/method.cc | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 903ee66..e0fe217 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -2056,6 +2056,28 @@ assignable_expr (tree to, tree from) return r; } +/* An unparsed default member initializer prevents calling a defaulted default + constructor; make checking std::is_constructible ill-formed until the DMI + has been parsed, to avoid caching the wrong value. */ + +static bool +complain_about_unparsed_dmi (tree t) +{ + if (type_has_default_ctor_to_be_synthesized (t) + && TYPE_HAS_COMPLEX_DFLT (t)) + for (tree f = TYPE_FIELDS (t); f; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL + && DECL_INITIAL (f) + && TREE_CODE (DECL_INITIAL (f)) == DEFERRED_PARSE) + { + error ("default member initializer for %qD required by %qs before " + "the end of its enclosing class", f, "std::is_constructible"); + inform (location_of (f), "defined here"); + return true; + } + return false; +} + /* The predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented @@ -2070,6 +2092,8 @@ constructible_expr (tree to, tree from) cp_unevaluated cp_uneval_guard; if (CLASS_TYPE_P (to)) { + if (!from && complain_about_unparsed_dmi (to)) + return error_mark_node; tree ctype = to; vec<tree, va_gc> *args = NULL; if (!TYPE_REF_P (to)) |