Thread overview
[Issue 21299] [LINK] undefined reference to dmd.root.stringtable.StringValue!(Type).StringValue.lstring()
Oct 09
Dlang Bot
Oct 09
Dlang Bot
Oct 13
Dlang Bot
Oct 13
Dlang Bot
3 days ago
Dlang Bot
1 day ago
Dlang Bot
October 08
https://issues.dlang.org/show_bug.cgi?id=21299

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |industry
                 CC|                            |ibuclaw@gdcproject.org

--
October 08
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
What looks to be the reason for the issue:

struct StringTable(T)
{
    StringValue!T* insert()
        fwdrefs ->
            allocValue;
            getValue;

    uint allocValue()
        instantiates ->
            StringValue!(T)

    StringValue!T* getValue()
}

1. StringTable!(Type) is having semantic ran from 'dmd.mtype' scope.
2. All members have semantic ran in order of declaration using mtype scope.
3. allocValue is a forward reference inside insert(), so functionSemantic3() is
called, which switches to using _scope member, which is the scope of the first
instantiation context (not the current) 'dmd.func'.
4. allocValue instantiates StringValue!(Type) using func scope.
5. StringValue!(Type) is appended to the non-root module 'dmd.func', and so not
emitted.

-------------

Swap the insert() and allocValue() members around though, and the execution
path becomes:

1. StringTable!(Type) is having semantic ran from 'dmd.mtype' scope.
2. All members have semantic ran in order of declaration using mtype scope.
3. allocValue instantiates StringValue!(Type) using mtype scope.
4. StringValue!(Type) is appended to the root module 'dmd.mtype', so is
emitted.

-------------

Immediately then, the problem may be one of:

- functionSemantic()/functionSemantic3() doesn't accept a Scope parameter, so
the context that they are being evaluated in is lost.   They should be fixed to
accept a Scope parameter.

- The _scope of a function is not updated if a second instantiation occurs in a root module.

--
October 09
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #2 from Iain Buclaw <ibuclaw@gdcproject.org> ---
In `templateInstanceSemantic`, there is a shortcut for merging multiple template instantiations originating from the same template decl.  It fixes up the `minst` Module of the first instantiation to point at the root module instead of a non-root module.

However, the first instantiation ran `tryExpandMembers`, which had set the `_scope.minst` of all Dsymbol members to the non-root module.  This is left intact despite their parent instance being updated.

Why is it important to note this?  In the event of handling forward references, all further template instantiations from are pushed into that non-root module that came from `_scope.minst`.  It is this that leads to undefined references in both the mtype and func modules, they should have been pushed to the root module, but `_scope.minst` is now incorrectly set.

A patch I am preparing for this adds a new Visitor to walk over all members and update their `_scope.minst` to be the root module.

--
October 09
https://issues.dlang.org/show_bug.cgi?id=21299

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED

--
October 09
https://issues.dlang.org/show_bug.cgi?id=21299

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #3 from Dlang Bot <dlang-bot@dlang.rocks> ---
@ibuclaw updated dlang/dmd pull request #11837 "Fix Issue 21299: Undefined
reference to dmd.root.stringtable.StringValue!(Type).lstring()" fixing this
issue:

- Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  In `templateInstanceSemantic`, there exists special handling of matching
  template instances for the same template declaration to ensure that only
  at most one instance gets codegen'd.

  If the primary instance `inst` originated from a non-root module, the
  `minst` field will be updated so it is now coming from a root module,
  however all Dsymbol `inst.members` of the instance still have their
  `_scope.minst` pointing at the original non-root module. We must now
  propagate `minst` to all members so that forward referenced dependencies
  that get instantiated will also be appended to the root module,
  otherwise there will be undefined references at link-time.

  This doesn't affect compilations where all modules are compiled
  together, as every module is a root module in that situation.  What this
  primarily affects are cases where there is a mix of root and non-root
  modules, and a template was first instantiated in a non-root context,
  then later instantiated again in a root context.

https://github.com/dlang/dmd/pull/11837

--
October 09
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #4 from Dlang Bot <dlang-bot@dlang.rocks> ---
@ibuclaw created dlang/dmd pull request #11838 "[stable] Fix Issue 21299:
Undefined reference to dmd.root.stringtable.StringValue!(Type).lstring()"
fixing this issue:

- Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  In `templateInstanceSemantic`, there exists special handling of matching
  template instances for the same template declaration to ensure that only
  at most one instance gets codegen'd.

  If the primary instance `inst` originated from a non-root module, the
  `minst` field will be updated so it is now coming from a root module,
  however all Dsymbol `inst.members` of the instance still have their
  `_scope.minst` pointing at the original non-root module. We must now
  propagate `minst` to all members so that forward referenced dependencies
  that get instantiated will also be appended to the root module,
  otherwise there will be undefined references at link-time.

  This doesn't affect compilations where all modules are compiled
  together, as every module is a root module in that situation.  What this
  primarily affects are cases where there is a mix of root and non-root
  modules, and a template was first instantiated in a non-root context,
  then later instantiated again in a root context.

https://github.com/dlang/dmd/pull/11838

--
October 13
https://issues.dlang.org/show_bug.cgi?id=21299

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|---                         |FIXED

--- Comment #5 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11838 "[stable] Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()" was merged into stable:

- fb78f0984632f6a9a2cef4dad5f1386115fc978a by Iain Buclaw:
  Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  In `templateInstanceSemantic`, there exists special handling of matching
  template instances for the same template declaration to ensure that only
  at most one instance gets codegen'd.

  If the primary instance `inst` originated from a non-root module, the
  `minst` field will be updated so it is now coming from a root module,
  however all Dsymbol `inst.members` of the instance still have their
  `_scope.minst` pointing at the original non-root module. We must now
  propagate `minst` to all members so that forward referenced dependencies
  that get instantiated will also be appended to the root module,
  otherwise there will be undefined references at link-time.

  This doesn't affect compilations where all modules are compiled
  together, as every module is a root module in that situation.  What this
  primarily affects are cases where there is a mix of root and non-root
  modules, and a template was first instantiated in a non-root context,
  then later instantiated again in a root context.

https://github.com/dlang/dmd/pull/11838

--
October 13
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #6 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11867 "[dmd-cxx] Fix Issue 21299: Undefined reference
to dmd.root.stringtable.StringValue!(Type).lstring()" was merged into dmd-cxx:

- 9ab13379acf226069ced667455d834acf217cc66 by Iain Buclaw:
  [dmd-cxx] Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  In `templateInstanceSemantic`, there exists special handling of matching
  template instances for the same template declaration to ensure that only
  at most one instance gets codegen'd.

  If the primary instance `inst` originated from a non-root module, the
  `minst` field will be updated so it is now coming from a root module,
  however all Dsymbol `inst.members` of the instance still have their
  `_scope.minst` pointing at the original non-root module. We must now
  propagate `minst` to all members so that forward referenced dependencies
  that get instantiated will also be appended to the root module,
  otherwise there will be undefined references at link-time.

  This doesn't affect compilations where all modules are compiled
  together, as every module is a root module in that situation.  What this
  primarily affects are cases where there is a mix of root and non-root
  modules, and a template was first instantiated in a non-root context,
  then later instantiated again in a root context.

https://github.com/dlang/dmd/pull/11867

--
3 days ago
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #7 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11874 "Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()" was merged into stable:

- 01afe9cc8f898eafb0b7bd83080ca302e4fbc74c by Iain Buclaw:
  Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  Alternative patch where instead of proactively fixing up instance
  members when a template gets changed to a root instance, rather
  propagate the `minst` as and when we run semantic on the nested
  templates that still have a non-root `minst` from its scope.

https://github.com/dlang/dmd/pull/11874

--
1 day ago
https://issues.dlang.org/show_bug.cgi?id=21299

--- Comment #8 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11886 "merge stable" was merged into master:

- 8d6c07f60edfa51e7ad0882def71ef3e6437a465 by Iain Buclaw:
  Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  In `templateInstanceSemantic`, there exists special handling of matching
  template instances for the same template declaration to ensure that only
  at most one instance gets codegen'd.

  If the primary instance `inst` originated from a non-root module, the
  `minst` field will be updated so it is now coming from a root module,
  however all Dsymbol `inst.members` of the instance still have their
  `_scope.minst` pointing at the original non-root module. We must now
  propagate `minst` to all members so that forward referenced dependencies
  that get instantiated will also be appended to the root module,
  otherwise there will be undefined references at link-time.

  This doesn't affect compilations where all modules are compiled
  together, as every module is a root module in that situation.  What this
  primarily affects are cases where there is a mix of root and non-root
  modules, and a template was first instantiated in a non-root context,
  then later instantiated again in a root context.

- cf9113d804ec7a89bb354791d66b9555bc4f3f8d by Iain Buclaw:
  Fix Issue 21299: Undefined reference to
dmd.root.stringtable.StringValue!(Type).lstring()

  Alternative patch where instead of proactively fixing up instance
  members when a template gets changed to a root instance, rather
  propagate the `minst` as and when we run semantic on the nested
  templates that still have a non-root `minst` from its scope.

https://github.com/dlang/dmd/pull/11886

--