Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Ticket #354 (reopened defect)

Opened 2 years ago

Last modified 2 years ago

undefined reference to package function called from an interface

Reported by: Cyborg16 Assigned to: ChristianK
Priority: major Milestone:
Component: unspecified Version: release 0.9.1
Keywords: link-failure Cc:

Description

LDC seems to have the same issue as dmd: (see http://d.puremagic.com/issues/show_bug.cgi?id=3252)

Trying to compile this:

/** Compiler error - calling a package interface function.
 */
module packageFunc;

// Same error whether it's an interface or abstract class; although OK if the method is not abstract:
//interface I {
abstract class I {
    package void iPack();
}
class A : I {
    package void iPack() {}
}

void main () {
    A a = new A;
    I i = a;
    i.iPack;	// causes an undefined reference
    (cast(A) i).iPack;	// a workaround
}

results in the following linker error message (same error dmd has):

# ldc packageFunc.d
packageFunc.o: In function `_Dmain':
packageFunc:(.text+0x49): undefined reference to `_D11packageFunc1I5iPackMFZv'
collect2: ld returned 1 exit status
Error: linking failed:
status: 1

Change History

08/17/09 05:58:57 changed by lindquist

  • status changed from new to closed.
  • resolution set to invalid.

Member functions in an abstract class that do not have a body are not actually abstract methods. This is pretty much by design in LDC, you should add "abstract" in front of I.iPack.

08/17/09 13:18:49 changed by Cyborg16

Making I.iPack abstract produces the following error (when I is an interface or abstract class, in both ldc and dmd):

packageFunc.d(7): Error: function packageFunc.I.iPack non-virtual functions cannot be abstract

Which is probably a separate issue (since abstract members need to be virtual anyway; and virtual/non-virtual is automatic rather than explicit in D).

In reply to your comment:

  1. I see why abstract classes can have non-abstract methods, but what's the use of non-abstract methods with no body?
  2. this is only an issue with package protection; public/protected/private methods work fine
    • (although explicitly declaring such methods abstract still gives the above error)

Hence I don't think it's invalid?

08/17/09 14:34:42 changed by ChristianK

About 1., supposedly bodyless non-abstract methods could be defined elsewhere. This is essentially http://d.puremagic.com/issues/show_bug.cgi?id=2894 .

08/18/09 02:35:32 changed by Cyborg16

Then shouldn't the following code work? It doesn't, as commented:

abstract class A {
    private abstract void iPriv ();	// Error: function methodProtection.A.iPriv non-virtual functions cannot be abstract
    protected abstract void iProt ();
    package abstract void iPack ();	// Error: function methodProtection.A.iPack non-virtual functions cannot be abstract
    public abstract void iPub ();
}

class B : A {
    private void iPriv() {}
    protected void iProt() {}
    package void iPack() {}
    public void iPub() {}
}

void main() {
    A a = new B;
    a.iPriv;
    a.iProt;
    a.iPack;
    a.iPub;
}

Secondly, shouldn't this code compile (presumably interface methods shouldn't be declared abstract)? This time dmd gives undefined reference errors and ldc much less readable errors if either of the two marked lines are present.

interface I {
    private void iPriv ();
    protected void iProt ();
    package void iPack ();
    public void iPub ();
}

class B : I {
    private void iPriv() {}
    protected void iProt() {}
    package void iPack() {}
    public void iPub() {}
}

void main() {
    I a = new B;
    a.iPriv;	// error
    a.iProt;
    a.iPack;	// error
    a.iPub;
}

In both cases it's only with package or private protection. Thinking about it, I'm not sure if deriving a method with private protection is valid (although the compiler doesn't specifically complain about it), but with package protection it should be. Shouldn't all types of protection work the same, with the following exceptions?

  1. The obvious: limits on where the function can be called from
  2. That invariants are only called with public functions
  3. Possibly that private functions never need to be virtual?

08/18/09 11:44:33 changed by ChristianK

I'm not sure if deriving a method with private protection is valid

I haven't looked at the code, but private methods are never virtual. You cannot override them.

08/19/09 02:27:37 changed by Cyborg16

  • status changed from closed to reopened.
  • resolution deleted.

True. From the spec: "Private means that only members of the enclosing class can access the member, or members and functions in the same module as the enclosing class. Private members cannot be overridden." But that wasn't the main issue.

Reopening; hopefully you agree it is a bug. Together with #355, it makes virtual package functions kindof impossible to use.

Btw, thank you for the work you (plural) have put into producing another great compiler for D (especially with 64bit support)!

Copyright © 2008, LDC Development Team.