Bug 19496 – Wrong D and C++ ABI caused by scope qualifier in other method
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
Linux
Creation time
2018-12-16T17:15:24Z
Last change time
2020-02-19T05:16:58Z
Keywords
C++, industry, wrong-code
Assigned to
No Owner
Creator
Илья Ярошенко
Comments
Comment #0 by ilyayaroshenko — 2018-12-16T17:15:24Z
t1.d:
struct S
{
void* _payload;
~this();
typeof(this) merge() { return this; }
bool foo(ref typeof(this) rhs);
}
t2.d:
struct S
{
void* _payload;
~this();
typeof(this) merge() { return this; }
bool foo(scope ref typeof(this) rhs);
}
As you can see the difference between this two tests is that t2.S.foo's argument has scope qualifier.
The issue is that t1.S.merge and t2.S.merge have different ABI. Fantastic issue, ha!
The correct ABI is in t1. The same ABI is in C++ for objects with destructors. Note, that ABI depends on if destructor presents, both in D and C++.
The issue is represented both in DMD and LDC, both for extern(D) and extern(C++).
LLVM output (DMD's assembler is less informative):
t.ll.S.merge:
// ABI signature returns void (as for objects with destructors)
define void @_D22t11S5mergeMFZSQBkQp(%t1.S* noalias nocapture sret align 8 %.sret_arg, %t1.S* nocapture nonnull readonly %.this_arg) local_unnamed_addr #1 comdat {
%1 = bitcast %t1.S* %.this_arg to i64* ; [#uses = 1]
%2 = bitcast %t1.S* %.sret_arg to i64* ; [#uses = 1]
%3 = load i64, i64* %1, align 1 ; [#uses = 1]
store i64 %3, i64* %2, align 8
ret void
}
t2.ll.S.merge:
// ABI signature returns S (as for objects without destructors)
define %t2.S @_D22t21S5mergeMFZSQBkQp(%t2.S* nocapture nonnull readonly %.this_arg) local_unnamed_addr #1 comdat {
%1 = getelementptr inbounds %t2.S, %t2.S* %.this_arg, i64 0, i32 0 ; [#uses =
1, type = i8**]
%.unpack = load i8*, i8** %1, align 8 ; [#uses = 1]
%2 = insertvalue %t2.S undef, i8* %.unpack, 0 ; [#uses = 1]
ret %t2.S %2
}
Comment #1 by ilyayaroshenko — 2018-12-16T17:17:15Z
Both 32 and 64 bit code affected
Comment #2 by kinke — 2018-12-16T17:40:50Z
Wow, that's a curious major issue indeed. Somehow that little `scope` seems to affect `StructDeclaration.isPOD()`.
Comment #3 by ilyayaroshenko — 2019-03-01T12:14:04Z
Fixed since DMD 2.084 / LDC 1.14
Comment #4 by pro.mathias.lang — 2020-02-19T05:16:58Z