[gcc r13-10066] d: Fix Segmentation fault with redeclared symbols [PR123407]

Iain Buclaw ibuclaw@gcc.gnu.org
Thu Jan 29 16:18:29 GMT 2026


https://gcc.gnu.org/g:c67142f19574e94a45ef91710e777ec17b4d5e4d

commit r13-10066-gc67142f19574e94a45ef91710e777ec17b4d5e4d
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Thu Jan 29 16:26:21 2026 +0100

    d: Fix Segmentation fault with redeclared symbols [PR123407]
    
    Issue an error if two symbols with the same assembler name have a
    mismatched TREE_CODE.
    
            PR d/123407
    
    gcc/d/ChangeLog:
    
            * decl.cc (get_symbol_decl): Handle declarations with matching
            assembler names, but different TREE_CODE.
    
    gcc/testsuite/ChangeLog:
    
            * gdc.dg/pr123407a.d: New test.
            * gdc.dg/pr123407b.d: New test.
    
    (cherry picked from commit 172634608a49603d10b471b0379c71cf53d3e2c0)

Diff:
---
 gcc/d/decl.cc                    | 62 +++++++++++++++++++++++-----------------
 gcc/testsuite/gdc.dg/pr123407a.d |  4 +++
 gcc/testsuite/gdc.dg/pr123407b.d |  4 +++
 3 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 5308357aa371..03e2e3d8570c 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1202,8 +1202,7 @@ get_symbol_decl (Declaration *decl)
 
   /* Deal with placeholder symbols immediately:
      SymbolDeclaration is used as a shell around an initializer symbol.  */
-  SymbolDeclaration *sd = decl->isSymbolDeclaration ();
-  if (sd)
+  if (SymbolDeclaration *sd = decl->isSymbolDeclaration ())
     {
       decl->csym = aggregate_initializer_decl (sd->dsym);
       return decl->csym;
@@ -1214,8 +1213,7 @@ get_symbol_decl (Declaration *decl)
     return get_typeinfo_decl ((TypeInfoDeclaration *) decl);
 
   /* FuncAliasDeclaration is used to import functions from another scope.  */
-  FuncAliasDeclaration *fad = decl->isFuncAliasDeclaration ();
-  if (fad)
+  if (FuncAliasDeclaration *fad = decl->isFuncAliasDeclaration ())
     {
       decl->csym = get_symbol_decl (fad->funcalias);
       return decl->csym;
@@ -1250,8 +1248,7 @@ get_symbol_decl (Declaration *decl)
     }
 
   /* Build the tree for the symbol.  */
-  FuncDeclaration *fd = decl->isFuncDeclaration ();
-  if (fd)
+  if (FuncDeclaration *fd = decl->isFuncDeclaration ())
     {
       /* Run full semantic on functions we need to know about.  */
       if (!fd->functionSemantic ())
@@ -1343,29 +1340,38 @@ get_symbol_decl (Declaration *decl)
       if (IDENTIFIER_DSYMBOL (mangled_name))
 	{
 	  Declaration *other = IDENTIFIER_DSYMBOL (mangled_name);
-	  tree olddecl = decl->csym;
-	  decl->csym = get_symbol_decl (other);
-
-	  /* Update the symbol location to the current definition.  */
-	  if (DECL_EXTERNAL (decl->csym) && !DECL_INITIAL (decl->csym))
-	    DECL_SOURCE_LOCATION (decl->csym) = DECL_SOURCE_LOCATION (olddecl);
+	  tree newdecl = decl->csym;
+	  tree olddecl = get_symbol_decl (other);
 
-	  /* The current declaration is a prototype or marked extern, merge
-	     applied user attributes and return.  */
-	  if (DECL_EXTERNAL (olddecl) && !DECL_INITIAL (olddecl))
-	    {
-	      apply_user_attributes (decl, decl->csym);
-	      return decl->csym;
-	    }
-	  /* The previous declaration is a prototype or marked extern, set the
-	     current declaration as the main reference of the symbol.  */
-	  else if (DECL_EXTERNAL (decl->csym) && !DECL_INITIAL (decl->csym))
+	  if (TREE_CODE (olddecl) == TREE_CODE (newdecl))
 	    {
-	      IDENTIFIER_DSYMBOL (mangled_name) = decl;
-	      DECL_EXTERNAL (decl->csym) = 0;
+	      /* Update the symbol location to the current definition.  */
+	      if (DECL_EXTERNAL (olddecl) && !DECL_INITIAL (olddecl))
+		DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (newdecl);
+
+	      /* The current declaration is a prototype or marked extern, merge
+		 applied user attributes and return.  */
+	      if (DECL_EXTERNAL (newdecl) && !DECL_INITIAL (newdecl))
+		{
+		  apply_user_attributes (decl, olddecl);
+		  decl->csym = olddecl;
+		  return decl->csym;
+		}
+	      /* The previous declaration is a prototype or marked extern, set
+		 the current declaration as the main reference of the symbol.
+	       */
+	      else if (DECL_EXTERNAL (olddecl) && !DECL_INITIAL (olddecl))
+		{
+		  IDENTIFIER_DSYMBOL (mangled_name) = decl;
+		  decl->csym = olddecl;
+		  DECL_EXTERNAL (decl->csym) = 0;
+		}
+	      /* Non-extern, non-templated decls shouldn't be defined twice.  */
+	      else if (!decl->isInstantiated ())
+		ScopeDsymbol::multiplyDefined (decl->loc, decl, other);
 	    }
-	  /* Non-extern, non-templated decls shouldn't be defined twice.  */
-	  else if (!decl->isInstantiated ())
+	  /* Declarations are for conflicting kinds of symbol.  */
+	  else
 	    ScopeDsymbol::multiplyDefined (decl->loc, decl, other);
 	}
       else
@@ -1407,6 +1413,9 @@ get_symbol_decl (Declaration *decl)
     }
   else if (TREE_CODE (decl->csym) == FUNCTION_DECL)
     {
+      FuncDeclaration *fd = decl->isFuncDeclaration ();
+      gcc_assert (fd != NULL);
+
       /* Dual-context functions require the code generation to build an array
 	 for the context pointer of the function, making the delicate task of
 	 tracking which context to follow when encountering a non-local symbol,
@@ -1560,6 +1569,7 @@ get_symbol_decl (Declaration *decl)
   if (decl->isDataseg () || decl->isCodeseg () || decl->isThreadlocal ())
     {
       /* Set TREE_PUBLIC by default, but allow private template to override.  */
+      FuncDeclaration *fd = decl->isFuncDeclaration ();
       if (!fd || !fd->isNested ())
 	TREE_PUBLIC (decl->csym) = 1;
 
diff --git a/gcc/testsuite/gdc.dg/pr123407a.d b/gcc/testsuite/gdc.dg/pr123407a.d
new file mode 100644
index 000000000000..112b7d3f63e9
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr123407a.d
@@ -0,0 +1,4 @@
+// { dg-do compile }
+module pr123407;
+pragma(mangle, "ice") int fun();
+pragma(mangle, "ice") int var; // { dg-error "matches conflicting symbols" }
diff --git a/gcc/testsuite/gdc.dg/pr123407b.d b/gcc/testsuite/gdc.dg/pr123407b.d
new file mode 100644
index 000000000000..78960dbc941b
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr123407b.d
@@ -0,0 +1,4 @@
+// { dg-do compile }
+module pr123407;
+int fun();
+extern(C) int _D8pr1234073funFZi; // { dg-error "matches conflicting symbols" }


More information about the Gcc-cvs mailing list