[Bug d/95120] New: [D] Incorrectly allows fqdn access to imported symbols when doing selective imports.

witold.baryluk+gcc at gmail dot com gcc-bugzilla@gcc.gnu.org
Thu May 14 00:15:15 GMT 2020


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);
}
======


More information about the Gcc-bugs mailing list