[Issue 14541] New: "duplicate COMDAT" linker error with the template forward reference in Tuple.opAssign
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Sun May 3 08:40:18 PDT 2015
https://issues.dlang.org/show_bug.cgi?id=14541
Issue ID: 14541
Summary: "duplicate COMDAT" linker error with the template
forward reference in Tuple.opAssign
Product: D
Version: D2
Hardware: x86_64
OS: Windows
Status: NEW
Keywords: link-failure, rejects-valid
Severity: normal
Priority: P1
Component: DMD
Assignee: nobody at puremagic.com
Reporter: k.hara.pg at gmail.com
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[];
}
}
}
}
--
More information about the Digitalmars-d-bugs
mailing list