Linker anomalies

Ali Çehreli acehreli at yahoo.com
Thu Nov 7 18:45:21 UTC 2019


On 11/07/2019 04:14 AM, Luh wrote:
 > Hey there,
 >
 > I figured out some strange behavior ;
 >
 > #1
 > It seems that the linker doesn't check for the function declared twice
 > first.

It's not the linker but the "compiler" that is concerned about these things.

 > Instead, it says:
 >
 > "Error: class app.Child use of app.Parent.foo() is hidden by Child; use
 > alias foo = Parent.foo; to introduce base class overload set"

That's an important warning where the programmer can get surprising 
results depending on whether the object is used through the Parent 
interface or the Child interface.

 > but when we call it ( p.foo() ), then it returns the correct error 
message.

It indicates to me that the compiler is performing certain checks lazily 
likely for performance reasons.

 > #2
 > The template update() compiles fine until we call it.

That's common for templates: As long as it's syntactically correct, some 
errors are delayed until instantiation time.

 > Bizarre, isn't it ?

I've seen worse. :)

 > code:
 > ---
 > void main()
 > {
 >      auto p = new Parent();
 >      // Shows the wrong error message until uncommented
 >      //p.foo();
 >      // Compiles when commented
 >      //update(p);
 > }
 >
 > class Child : Parent
 > {
 >      override void foo() { }
 > }
 >
 > class Parent
 > {
 >      void foo() { }
 >      void foo() { }

Apparently, the compiler does not check whether an overload set has 
ambiguities until actual use. I suspect the opposite would slow dow 
compilation and cause frustration in some cases.

 > }
 >
 > void update(T)(T object) if(is(T == Parent))
 > {
 >      static if (is(T == Parent))
 >      {
 >          // Shouldn't compile
 >          ObjectThatDoesntExists.bar(T);
 >      }
 > }
 > ---
 >
 > Is this a bug ?

It should compile because ObjectThatDoesntExists may actually be present 
when T==Parent depending on other conditions in the program. A simple 
example:

// Called only in some case:
   version (X) update(p);

// And that case happens to introduce ObjectThatDoesntExists:
version (X) {

class O {
   void bar() {
   }
}

O ObjectThatDoesntExists;  // <-- Now the code will compile

} // version

Remember that ObjectThatDoesntExists may even be introduced by another 
module, which may be compiled separately with e.g. different compilation 
options (e.g. --version=X). So, it's not possible for the compiler to 
detect such cases. It's an error only if the template is actually 
instantiated.

Ali



More information about the Digitalmars-d-learn mailing list