Issue 19937 - object._d_assert_fail linker error if compiling with -checkaction=context
Summary: object._d_assert_fail linker error if compiling with -checkaction=context
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-06-03 18:08 UTC by JR
Modified: 2022-12-17 10:38 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description JR 2019-06-03 18:08:56 UTC
import std.stdio;
import std.json;

void main()
{
    auto j = parseJSON(`[ "abc", "def", "ghi" ]`);
}


$ dmd -checkaction=context checkaction.d
/usr/bin/ld: c.o: in function `_D3std3uni__T4TrieTSQsQq__T9BitPackedTbVmi1ZQrTwVmi1114112TSQCgQCf__T9sliceBitsVmi13Vmi21ZQvTSQDoQDn__TQBiVmi8Vmi13ZQBvTSQEpQEo__TQCjVmi0Vmi8ZQCvZQFd__T7opIndexZQjMxFNaNbNiNewZb':
checkaction.d:(.text._D3std3uni__T4TrieTSQsQq__T9BitPackedTbVmi1ZQrTwVmi1114112TSQCgQCf__T9sliceBitsVmi13Vmi21ZQvTSQDoQDn__TQBiVmi8Vmi13ZQBvTSQEpQEo__TQCjVmi0Vmi8ZQCvZQFd__T7opIndexZQjMxFNaNbNiNewZb[_D3std3uni__T4TrieTSQsQq__T9BitPackedTbVmi1ZQrTwVmi1114112TSQCgQCf__T9sliceBitsVmi13Vmi21ZQvTSQDoQDn__TQBiVmi8Vmi13ZQBvTSQEpQEo__TQCjVmi0Vmi8ZQCvZQFd__T7opIndexZQjMxFNaNbNiNewZb]+0x52): undefined reference to `_D6object__T14_d_assert_failVAyaa1_3cTmTmZQBeFNaNbNiNfmmZQBc'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1

demangles to pure nothrow @nogc @safe immutable(char)[] object._d_assert_fail!("<", ulong, ulong)._d_assert_fail(ulong, ulong)
Comment 1 JR 2019-06-03 18:13:36 UTC
Apologies, I should mention Manjaro/Arch x86_64, dmd v2.086.0 from official repositories.
Comment 2 Seb 2019-08-03 20:08:59 UTC
Demangled:

---
checkaction.o:checkaction.d:function const pure nothrow @nogc @trusted bool std.uni.Trie!(std.uni.BitPacked!(bool, 1uL).BitPacked, dchar, 1114112uL, std.uni.sliceBits!(13uL, 21uL).sliceBits, std.uni.sliceBits!(8uL, 13uL).sliceBits, std.uni.sliceBits!(0uL, 8uL).sliceBits).Trie.opIndex!().opIndex(dchar): error: undefined reference to 'pure nothrow @nogc @safe immutable(char)[] object._d_assert_fail!("<", ulong, ulong)._d_assert_fail(ulong, ulong)'
---


Code generated from DMD looks like this:

```
inout pure nothrow @nogc @system BitPacked!(bool, 1LU) opIndex(ulong idx)
			in
			{
				assert(idx < this.limit, _d_assert_fail(idx, this.limit));
			}
			do
			{
				{
					{
						assert(idx < this.limit, _d_assert_fail(idx, this.limit));
					}
				}
				return this.ptr.opIndex(this.ofs + idx);
			}
```


...


```
_d_assert_fail!("<", ulong, ulong)
{
	pure nothrow @nogc @safe string _d_assert_fail(ulong a, ulong b)
	{
		import core.internal.dassert : invertCompToken, miniFormatFakeAttributes, pureAlloc;
		string valA = miniFormatFakeAttributes(a);
		string valB = miniFormatFakeAttributes(b);
		enum string token = ">=";
		const const(ulong) totalLen = valA.length + 2LU + valB.length + 2LU;
		char[] buffer = cast(char[])pureAlloc(totalLen)[0..totalLen];
		ulong n = valA.length;
		buffer[0..n] = cast(const(char[]))valA;
		buffer[n++] = ' ';
		buffer[n..n + 2LU] = ">=";
		n += 2LU;
		buffer[n++] = ' ';
		buffer[n..n + valB.length] = cast(const(char[]))valB;
		return delegate () => cast(string)buffer();
	}

}
```

but it doesn't appear in the object file:

```
$ nm bar.o | grep assert_fail | ddemangle
0000000000000000 W pure nothrow @nogc @trusted immutable(char)[] object._d_assert_fail!("<", uint, uint)._d_assert_fail(uint, uint).__lambda3()
0000000000000000 W pure nothrow @nogc @safe immutable(char)[] object._d_assert_fail!("<", uint, uint)._d_assert_fail(uint, uint)
                 U pure nothrow @nogc @safe immutable(char)[] object._d_assert_fail!("<", ulong, ulong)._d_assert_fail(ulong, ulong)
0000000000000000 W pure nothrow @nogc @trusted immutable(char)[] object._d_assert_fail!(">=", uint, uint)._d_assert_fail(uint, uint).__lambda3()
0000000000000000 W pure nothrow @nogc @safe immutable(char)[] object._d_assert_fail!(">=", uint, uint)._d_assert_fail(uint, uint)
```

DMD probably thinks that this assertion was already instantiated in Phobos (and thus should be part of the object file), but it is not as Phobos was build without -checkaction=context.
Comment 3 Seb 2019-08-03 21:00:44 UTC
BTW a workaround is to do force the instantiation e.g. with the following hack:

```
cat << EOF > workaround.d
void test(ulong x, ulong y){
    assert(x < y);
}
EOF
```

```
dmd -checkaction=context -c workaround.d
dmd -checkaction=context workaround.o checkaction.d 
```
Comment 4 Mathias LANG 2020-02-24 02:13:44 UTC
I'm seeing this with anything that involves Vibe.d as well, with DMD v2.090.1.
Comment 5 Mathias LANG 2020-02-24 02:23:12 UTC
@Seb: Thanks for the pointer. Unfortunately in the Vibe.d case it is nastier, because the symbol takes a `ref` and a non-ref. Turns out `assert(x > y)` and `assert(x > 0)` will generate different symbol (the former's second argument is `ref` while the later is not, being a rvalue).
Comment 6 Bastiaan Veelo 2020-04-10 11:32:45 UTC
Assuming Seb's assessment of phobos being compiled without `-checkaction=context` is the root cause, here is another test case:

```
import std;
void main()
{
  wchar[] c;
  c.toUTF8;
}
```

Compiling this with `-checkaction=context` produces
```
Error 42: Symbol Undefined __D4core8internal7dassert__T24miniFormatFakeAttributesTkZQBdFNaNbNiNfKxkZAya
```

The link error vanishes if the argument `-debug` or `-release` is added, or if the import is changed into `import std.utf;`. This happens for DMD64 D Compiler v2.091.0-dirty on Windows, couldn't reproduce this on run.dlang.io.

Bastiaan.