This type currently has a DECL_NAME of an IDENTIFIER_DECL.  Although the
documentation indicates this is legal, this confuses modules streaming
which expects all RECORD_TYPEs to have a TYPE_DECL, which is used to
determine the context and merge key, etc.

        PR c++/120040

gcc/cp/ChangeLog:

        * constexpr.cc (cxx_eval_constant_expression): Handle TYPE_NAME
        now being a TYPE_DECL rather than just an IDENTIFIER_NODE.
        * init.cc (build_new_constexpr_heap_type): Build a TYPE_DECL for
        the returned type; mark the type as artificial.
        * module.cc (trees_out::type_node): Add some assertions.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/pr120040_a.C: New test.
        * g++.dg/modules/pr120040_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
---
 gcc/cp/constexpr.cc                       |  2 +-
 gcc/cp/init.cc                            | 10 +++++++++-
 gcc/cp/module.cc                          |  3 +++
 gcc/testsuite/g++.dg/modules/pr120040_a.C | 19 +++++++++++++++++++
 gcc/testsuite/g++.dg/modules/pr120040_b.C | 15 +++++++++++++++
 5 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/pr120040_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/pr120040_b.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa754b9a176..ceb8f04fab4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8613,7 +8613,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
            tree cookie_size = NULL_TREE;
            tree arg_size = NULL_TREE;
            if (TREE_CODE (elt_type) == RECORD_TYPE
-               && TYPE_NAME (elt_type) == heap_identifier)
+               && DECL_NAME (TYPE_NAME (elt_type)) == heap_identifier)
              {
                tree fld1 = TYPE_FIELDS (elt_type);
                tree fld2 = DECL_CHAIN (fld1);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 80a37a14a80..0a389fb6ecd 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3010,7 +3010,6 @@ build_new_constexpr_heap_type (tree elt_type, tree 
cookie_size, tree itype2)
   tree atype1 = build_cplus_array_type (sizetype, itype1);
   tree atype2 = build_cplus_array_type (elt_type, itype2);
   tree rtype = cxx_make_type (RECORD_TYPE);
-  TYPE_NAME (rtype) = heap_identifier;
   tree fld1 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype1);
   tree fld2 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype2);
   DECL_FIELD_CONTEXT (fld1) = rtype;
@@ -3019,7 +3018,16 @@ build_new_constexpr_heap_type (tree elt_type, tree 
cookie_size, tree itype2)
   DECL_ARTIFICIAL (fld2) = true;
   TYPE_FIELDS (rtype) = fld1;
   DECL_CHAIN (fld1) = fld2;
+  TYPE_ARTIFICIAL (rtype) = true;
   layout_type (rtype);
+
+  tree decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, heap_identifier, rtype);
+  TYPE_NAME (rtype) = decl;
+  TYPE_STUB_DECL (rtype) = decl;
+  DECL_CONTEXT (decl) = NULL_TREE;
+  DECL_ARTIFICIAL (decl) = true;
+  layout_decl (decl, 0);
+
   return rtype;
 }
 
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index ddb5299b244..765d17935c5 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9362,6 +9362,7 @@ trees_out::type_node (tree type)
 
   tree root = (TYPE_NAME (type)
               ? TREE_TYPE (TYPE_NAME (type)) : TYPE_MAIN_VARIANT (type));
+  gcc_checking_assert (root);
 
   if (type != root)
     {
@@ -9440,6 +9441,8 @@ trees_out::type_node (tree type)
        || TREE_CODE (type) == UNION_TYPE
        || TREE_CODE (type) == ENUMERAL_TYPE)
       {
+       gcc_checking_assert (DECL_P (name));
+
        /* We can meet template parms that we didn't meet in the
           tpl_parms walk, because we're referring to a derived type
           that was previously constructed from equivalent template
diff --git a/gcc/testsuite/g++.dg/modules/pr120040_a.C 
b/gcc/testsuite/g++.dg/modules/pr120040_a.C
new file mode 100644
index 00000000000..77e16892f4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr120040_a.C
@@ -0,0 +1,19 @@
+// PR c++/120040
+// { dg-additional-options "-fmodules -std=c++20" }
+// { dg-module-cmi M }
+
+export module M;
+
+struct S {
+  constexpr ~S() {}
+};
+
+export constexpr bool foo() {
+  S* a = new S[3];
+  delete[] a;
+  return true;
+}
+
+export constexpr S* bar() {
+  return new S[3];
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr120040_b.C 
b/gcc/testsuite/g++.dg/modules/pr120040_b.C
new file mode 100644
index 00000000000..e4610b07eaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr120040_b.C
@@ -0,0 +1,15 @@
+// PR c++/120040
+// { dg-additional-options "-fmodules -std=c++20" }
+
+import M;
+
+constexpr bool qux() {
+  auto* s = bar();
+  delete[] s;
+  return true;
+}
+
+int main() {
+  static_assert(foo());
+  static_assert(qux());
+}
-- 
2.47.0

Reply via email to