Hi,
This patch fixes PR123407.
Issue an error if two symbols with the same assembler name have a
mismatched TREE_CODE.
Regstrapped on x86_64-linux-gnu, committed to mainline, and backported
to releases/gcc-13, gcc-14, and gcc-15.
Regards,
Iain.
---
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.
---
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(-)
create mode 100644 gcc/testsuite/gdc.dg/pr123407a.d
create mode 100644 gcc/testsuite/gdc.dg/pr123407b.d
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index b1f232616fc..5535ff47088 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1213,8 +1213,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;
@@ -1225,8 +1224,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;
@@ -1261,8 +1259,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 (!dmd::functionSemantic (fd))
@@ -1354,29 +1351,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
@@ -1418,6 +1424,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,
@@ -1571,6 +1580,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 00000000000..112b7d3f63e
--- /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 00000000000..78960dbc941
--- /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" }
--
2.43.0