Issue 22427 - betterC: casting an array causes linker error in string comparison.
Summary: betterC: casting an array causes linker error in string comparison.
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 regression
Assignee: No Owner
URL:
Keywords: betterC, link-failure, pull
Depends on:
Blocks:
 
Reported: 2021-10-19 03:49 UTC by dave287091
Modified: 2023-07-14 16:02 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description dave287091 2021-10-19 03:49:12 UTC
This reduced code fails to link. 
// foo.d
extern(C)
int main(){
    if("a" == "a")
        return 1;
    char[] p;
    auto a = cast(int[])p;
    return 0;
}

A linker error results:

Undefined symbols for architecture x86_64:
  "__D4core8internal5array8equality__T8__equalsTaTaZQoFNaNbNiNeMxAaMxQeZb", referenced from:
      _main in foo.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: /usr/bin/cc failed with status: 1

The undefined symbol demangles to:
pure nothrow @nogc @trusted bool core.internal.array.equality.__equals!(char, char).__equals(scope const(char[]), scope const(char[]))

I have verified this problem happens both with dmd and ldc2. ldc2 1.24 - 1.28 has the error. Older ldc do not. Current dmd has the error, I don’t know how far back.
Comment 1 dave287091 2021-10-19 03:52:33 UTC
(In reply to dave287091 from comment #0)
> This reduced code fails to link. 

I forgot to mention, compile with -betterC. Without -betterC it links fine.
Comment 2 dave287091 2021-10-19 03:53:12 UTC
(In reply to dave287091 from comment #1)
> (In reply to dave287091 from comment #0)
> > This reduced code fails to link. 
> 
> I forgot to mention, compile with -betterC. Without -betterC it links fine.

Also, without the array cast there it also links fine.
Comment 3 dave287091 2022-05-13 04:46:03 UTC
This worked with dmd 2.093 and stopped working with dmd 2.094.
Comment 4 dave287091 2022-05-25 01:26:39 UTC
The -allinst/--allinst flag will resolve the link error, but that is a counter-intuitive requirement as there is no explicit template in the program - just one injected by the compiler. The fact that array equality is implemented as a template is an implementation detail and shouldn’t require the user to work around it.

It’s also weird that the cast somehow changes whether the template is emitted.
Comment 5 RazvanN 2023-07-11 14:29:28 UTC
It seems that the cast is lowered to __ArrayCast which in turn ends up instantiating __equals with the same template parameters, but in a speculative context (static if). Somehow, the template emission strategy decides that the instance does not require codegen (from what I can tell, the compiler decides that it's better to put the instance in the imported module - core.memory in this case), hence the linker errors.

I think that this strategy should be disabled in the case of betterC as it currently is with -allinst.
Comment 6 Dlang Bot 2023-07-11 14:52:21 UTC
@RazvanN7 created dlang/dmd pull request #15404 "Fix Issue 22427 - betterC: casting an array causes linker error in string comparison" fixing this issue:

- Fix Issue 22427 - betterC: casting an array causes linker error in string comparison

https://github.com/dlang/dmd/pull/15404
Comment 7 Dlang Bot 2023-07-14 16:02:23 UTC
dlang/dmd pull request #15404 "Fix Issue 22427 - betterC: casting an array causes linker error in string comparison" was merged into master:

- bab58df92fa67c4702bf001c8258ff2eeb4643bc by RazvanN7:
  Fix Issue 22427 - betterC: casting an array causes linker error in string comparison

- 9e1ba7b233a73941ec094d60b226af92618301d8 by RazvanN7:
  Fix Issue 22427 - betterC: casting an array causes linker error in string comparison

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