Bug 14541 – "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2015-05-03T15:40:18Z
Last change time
2020-12-03T23:07:40Z
Keywords
link-failure, pull, rejects-valid
Assigned to
No Owner
Creator
Kenji Hara

Comments

Comment #0 by k.hara.pg — 2015-05-03T15:40:18Z
Command line and error message: $ dmd -m64 test test.obj : fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '_D6traits14__T5TupleTiTiZ5Tuple44__T8opAssignTS6traits14__T5TupleTiTiZ5TupleZ8opAssignMFNaNbNiNfS6traits14__T5TupleTiTiZ5TupleZv' --- errorlevel 1179 Source files with explanation comments: ==== test.d import traits; void main() { Tuple!(int, int) result; alias T = typeof(result); static assert(hasElaborateAssign!T); // hasElablrateAssign!(Tuple(int, int)): // 1. instantiates Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = Rvalue] // 2. instantiates swap!(Tuple!(int, int)) // 3. instantiates hasElablrateAssign!(Tuple!(int, int)) // --> forward reference error // --> swap!(Tuple!(int, int)) fails to instantiate // --> Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = rvalue] fails to instantiate // 4. instantiates Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = Lvalue] // --> succeeds // hasElablrateAssign!(Tuple(int, int)) succeeds to instantiate (result is 'true') // Instantiates Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = Rvalue], but // it's already done in gagged context, so this is made an error reproduction instantiation. // --> 1st error reproduction instantiation // But, the forward reference of hasElablrateAssign!(Tuple(int, int)) is alredy resolved, so // the instantiation will succeeds. result = Tuple!(int, int)(0, 0); // Instantiates Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = Rvalue], but // it's already done in gagged context, so this is made an error reproduction instantiation. // --> 2nd error reproduction instantiation // But, the forward reference of hasElablrateAssign!(Tuple(int, int)) is alredy resolved, so // the instantiation will succeeds. result = Tuple!(int, int)(0, 0); // The two error reproduction instantiations generate the function: // Tuple!(int, int).opAssign!(Tuple!(int, int)) [auto ref = Rvalue] // twice, then it will cause duplicate COMDAT error in Win64 platform. } ==== traits.d template hasElaborateAssign(S) { static if (is(S == struct)) { extern __gshared S lvalue; enum hasElaborateAssign = is(typeof(S.init.opAssign(S.init))) || is(typeof(S.init.opAssign(lvalue))); } else { enum bool hasElaborateAssign = false; } } void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow @nogc { static if (hasElaborateAssign!T) { } else { } } template Tuple(Types...) { struct Tuple { Types field; alias field this; this(Types values) { field[] = values[]; } void opAssign(R)(auto ref R rhs) { static if (is(R : Tuple!Types) && !__traits(isRef, rhs)) { // Use swap-and-destroy to optimize rvalue assignment swap!(Tuple!Types)(this, rhs); } else { // Do not swap; opAssign should be called on the fields. field[] = rhs.field[]; } } } }
Comment #1 by k.hara.pg — 2015-05-03T16:31:11Z
Comment #2 by k.hara.pg — 2015-07-14T13:02:30Z
(In reply to Kenji Hara from comment #1) > https://github.com/D-Programming-Language/dmd/pull/4626#issuecomment-98389722 I closed pull 4626, so separate to a new PR: https://github.com/D-Programming-Language/dmd/pull/4814
Comment #3 by github-bugzilla — 2015-07-19T08:52:04Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/1112eec29eef531663de289f17800ad4a10fee50 fix Issue 14541 - "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign The "error reproduction instantiation" might succeed to finish semantic analysis by the forward reference resolution. When it happens, the cached error instance needs to be overridden by the succeeded instance. https://github.com/D-Programming-Language/dmd/commit/0b0d37363727385299c76a52c8ddb5c9db47afd8 Merge pull request #4814 from 9rnsr/fix14541 Issue 14541 - "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign
Comment #4 by github-bugzilla — 2015-08-30T19:18:38Z
Commit pushed to stable at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/cd29d5f34cbacebd83ecdb9727ab1b93f7fa6af1 Merge pull request #4814 from 9rnsr/fix14541 Issue 14541 - "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign
Comment #5 by github-bugzilla — 2015-09-02T04:10:16Z
Comment #6 by github-bugzilla — 2017-07-22T12:36:04Z
Commits pushed to dmd-cxx at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/1112eec29eef531663de289f17800ad4a10fee50 fix Issue 14541 - "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign https://github.com/dlang/dmd/commit/0b0d37363727385299c76a52c8ddb5c9db47afd8 Merge pull request #4814 from 9rnsr/fix14541 Issue 14541 - "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign
Comment #7 by bugzilla — 2020-12-03T23:07:40Z
I found the test case link14541.d completely baffling. The comment says "If instantiated contexts are different" but the whole idea is that templates in different contexts have different instantiations. This makes no sense. It should give an appropriate forward reference error. Likely the whole PR #4814 should be reverted as it makes no sense.