diff mbox series

[committed] d: Fix PR 108842: Cannot use enum array with -fno-druntime

Message ID 20230707192923.465324-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Fix PR 108842: Cannot use enum array with -fno-druntime | expand

Commit Message

Iain Buclaw July 7, 2023, 7:29 p.m. UTC
Hi,

This patch restricts generating of CONST_DECLs for D manifest constants
to just scalars without pointers.  It shouldn't happen that a reference
to a manifest constant has not been expanded within a function body
during codegen, but it has been found to occur in older versions of the
D front-end (PR98277), so if the decl of a non-scalar constant is
requested, just return its initializer as an expression.

Bootstrapped and regresson tested on x86_64-linux-gnu/-m32, committed to
mainline, and backported to the gcc-11, gcc-12, and gcc-13 release
branches.

Regards,
Iain.

---
	PR d/108842

gcc/d/ChangeLog:

	* decl.cc (DeclVisitor::visit (VarDeclaration *)): Only emit scalar
	manifest constants.
	(get_symbol_decl): Don't generate CONST_DECL for non-scalar manifest
	constants.
	* imports.cc (ImportVisitor::visit (VarDeclaration *)): New method.

gcc/testsuite/ChangeLog:

	* gdc.dg/pr98277.d: Add more tests.
	* gdc.dg/pr108842.d: New test.
---
 gcc/d/decl.cc                   | 36 +++++++++++++++++++--------------
 gcc/d/imports.cc                |  9 +++++++++
 gcc/testsuite/gdc.dg/pr108842.d |  4 ++++
 gcc/testsuite/gdc.dg/pr98277.d  | 11 ++++++++++
 4 files changed, 45 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr108842.d
diff mbox series

Patch

diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 3f980851259..0375ede082b 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -782,7 +782,7 @@  public:
       {
 	/* Do not store variables we cannot take the address of,
 	   but keep the values for purposes of debugging.  */
-	if (!d->type->isscalar ())
+	if (d->type->isscalar () && !d->type->hasPointers ())
 	  {
 	    tree decl = get_symbol_decl (d);
 	    d_pushdecl (decl);
@@ -1212,6 +1212,20 @@  get_symbol_decl (Declaration *decl)
       return decl->csym;
     }
 
+  if (VarDeclaration *vd = decl->isVarDeclaration ())
+    {
+      /* CONST_DECL was initially intended for enumerals and may be used for
+	 scalars in general, but not for aggregates.  Here a non-constant
+	 value is generated anyway so as its value can be used.  */
+      if (!vd->canTakeAddressOf () && !vd->type->isscalar ())
+	{
+	  gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
+	  Expression *ie = initializerToExpression (vd->_init);
+	  decl->csym = build_expr (ie, false);
+	  return decl->csym;
+	}
+    }
+
   /* Build the tree for the symbol.  */
   FuncDeclaration *fd = decl->isFuncDeclaration ();
   if (fd)
@@ -1259,23 +1273,15 @@  get_symbol_decl (Declaration *decl)
       if (vd->storage_class & STCextern)
 	DECL_EXTERNAL (decl->csym) = 1;
 
-      /* CONST_DECL was initially intended for enumerals and may be used for
-	 scalars in general, but not for aggregates.  Here a non-constant
-	 value is generated anyway so as the CONST_DECL only serves as a
-	 placeholder for the value, however the DECL itself should never be
-	 referenced in any generated code, or passed to the back-end.  */
-      if (vd->storage_class & STCmanifest)
+      if (!vd->canTakeAddressOf ())
 	{
 	  /* Cannot make an expression out of a void initializer.  */
-	  if (vd->_init && !vd->_init->isVoidInitializer ())
-	    {
-	      Expression *ie = initializerToExpression (vd->_init);
+	  gcc_assert (vd->_init && !vd->_init->isVoidInitializer ());
+	  /* Non-scalar manifest constants have already been dealt with.  */
+	  gcc_assert (vd->type->isscalar ());
 
-	      if (!vd->type->isscalar ())
-		DECL_INITIAL (decl->csym) = build_expr (ie, false);
-	      else
-		DECL_INITIAL (decl->csym) = build_expr (ie, true);
-	    }
+	  Expression *ie = initializerToExpression (vd->_init);
+	  DECL_INITIAL (decl->csym) = build_expr (ie, true);
 	}
 
       /* [type-qualifiers/const-and-immutable]
diff --git a/gcc/d/imports.cc b/gcc/d/imports.cc
index 2efef4ed54f..3172b799cb0 100644
--- a/gcc/d/imports.cc
+++ b/gcc/d/imports.cc
@@ -127,6 +127,15 @@  public:
     this->result_ = this->make_import (TYPE_STUB_DECL (type));
   }
 
+  void visit (VarDeclaration *d) final override
+  {
+    /* Not all kinds of manifest constants create a CONST_DECL.  */
+    if (!d->canTakeAddressOf () && !d->type->isscalar ())
+      return;
+
+    visit ((Declaration *) d);
+  }
+
   /* For now, ignore importing other kinds of dsymbols.  */
   void visit (ScopeDsymbol *) final override
   {
diff --git a/gcc/testsuite/gdc.dg/pr108842.d b/gcc/testsuite/gdc.dg/pr108842.d
new file mode 100644
index 00000000000..5aae9e5000d
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr108842.d
@@ -0,0 +1,4 @@ 
+// { dg-do compile }
+// { dg-options "-fno-rtti" }
+module object;
+enum int[] x = [0, 1, 2];
diff --git a/gcc/testsuite/gdc.dg/pr98277.d b/gcc/testsuite/gdc.dg/pr98277.d
index 0dff142a6ef..c88c735dec8 100644
--- a/gcc/testsuite/gdc.dg/pr98277.d
+++ b/gcc/testsuite/gdc.dg/pr98277.d
@@ -11,3 +11,14 @@  ref int getSide(Side side, return ref int left, return ref int right)
 {
     return side == Side.left ? left : right;
 }
+
+enum SideA : int[]
+{
+    left = [0],
+    right = [1],
+}
+
+int getSideA(SideA side, ref int left, ref int right)
+{
+    return side == SideA.left ? left : right;
+}