https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95120
Bug ID: 95120 Summary: [D] Incorrectly allows fqdn access to imported symbols when doing selective imports. Product: gcc Version: 10.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: d Assignee: ibuclaw at gdcproject dot org Reporter: witold.baryluk+gcc at gmail dot com Target Milestone: --- Created attachment 48529 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48529&action=edit Example of incorrectly accepted d source by gdc-10 gdc does violatate D language spec: https://dlang.org/spec/module.html#selective_imports ==== 4.7 Selective Imports Specific symbols can be exclusively imported from a module and bound into the current namespace: import std.stdio : writeln, foo = write; void main() { std.stdio.writeln("hello!"); // error, std is undefined writeln("hello!"); // ok, writeln bound into current namespace write("world"); // error, write is undefined foo("world"); // ok, calls std.stdio.write() fwritefln(stdout, "abc"); // error, fwritefln undefined } ===== I found that in some weird situations the gdc-10 does behave differently than dmd and ldc2. Here are the versions I used: $ dmd --version DMD64 D Compiler v2.092.0 Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved written by Walter Bright $ ldc2 --version LDC - the LLVM D compiler (1.20.1): based on DMD v2.090.1 and LLVM 9.0.1 built with LDC - the LLVM D compiler (1.20.1) Default target: x86_64-pc-linux-gnu Host CPU: znver1 $ gdc-10 --version gdc-10 (Debian 10.1.0-1) 10.1.0 $ All on Debian testing/unstable, amd64. ==== badimport.d ===== void main() { import std.stdio; import std.algorithm.comparison : min; static struct S { int min_; // int min() { return min_; } void opOpAssign(string op)(const S other) if (op == "+") { min_ = std.algorithm.comparison.min(min_, other.min_); } } S x = {3}; x += x; } ============= (the intention was to use fqdn here, to not reference struct member function min; using `.min(min_, other.min_)`, is another option, but it actually shouldn't work either, due to other reasons). Anyway: $ gdc-10 badimport.d # Compiles. $ $ ldc2 badimport.d # Correct error. badimport.d(11): Error: undefined identifier algorithm in package std, perhaps add static import std.algorithm; badimport.d(16): Error: template instance badimport.main.S.opOpAssign!"+" error instantiating $ $ dmd badimport.d # Correct error. badimport.d(11): Error: undefined identifier algorithm in package std, perhaps add static import std.algorithm; badimport.d(16): Error: template instance badimport.main.S.opOpAssign!"+" error instantiating $ Produced code by gdc-10 does work correctly. However, it shouldn't compile at all. >From what I can see, it is some kind of interaction with preceding imports, that is the `import std.stdio;`. Removing `import std.stdio;` makes gdc-10 correctly report the error and stop compilation. The test case can be further minimizes, and it attached to the bug. Same behaviour: ====== import std.stdio; import std.algorithm.comparison : min; struct S { int min_; void add(const S other) { min_ = std.algorithm.comparison.min(min_, other.min_); } } void main() { S x = {3}; x.add(x); } ======