SILNode versus C++

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
    int i;
    union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
    int a() { return X::i; } // works
    int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

Thanks,
Dave

This is expected. The inheritance chain ultimately ends up a B in both cases, so the reference to j is ambiguous, and the compiler can’t resolve which B is meant.

This works.

class B
{
  protected:
    int i;
    union { int j; };
};

class C
{
  protected:
    int i;
    union { int j; };
};

class X : public B { };
class Y : public C { };

class Z : public X, public Y
{
  int a() { return X::i; }
  int b() { return Y::i; }
  int c() { return X::j; }
  int d() { return Y::j; }
};

If “B” is a metaphor for a common base class in the “real” case, you are going to run into one of the pitfalls of C++ multiple inheritance, the “diamond” inheritance problem (Z inherits from X and Y, which both inherit from B, forms an inheritance “diamond” if you graph it out). That is why C++ has virtual inheritance. However, with anonymous unions, there is still an ambiguity as to which union member to access (as far as clang++ is concerned). Giving it a name or encasing it in another class instance resolves that ambigiuity.

Jonathan

···

On Dec 16, 2017, at 9:08 AM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
   int i;
   union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
   int a() { return X::i; } // works
   int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

Thanks,
Dave
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

This seems like a bug; anonymous unions are just supposed to inject their member names into the containing scope as if there was an ordinary member there, and the explicit scope-qualification should resolve which subobject is meant for such injected names the same it resolves them for ordinary fields. But if it's a bug in all existing clangs, it's a bug we're going to have to work around.

John.

···

On Dec 16, 2017, at 9:08 AM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
   int i;
   union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
   int a() { return X::i; } // works
   int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

Which should not prevent Dave from still reporting it on https://bugs.llvm.org/enter_bug.cgi?product=clang :slight_smile:

-- adrian

···

On Dec 16, 2017, at 10:31 AM, John McCall via swift-dev <swift-dev@swift.org> wrote:

On Dec 16, 2017, at 9:08 AM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
  int i;
  union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
  int a() { return X::i; } // works
  int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

This seems like a bug; anonymous unions are just supposed to inject their member names into the containing scope as if there was an ordinary member there, and the explicit scope-qualification should resolve which subobject is meant for such injected names the same it resolves them for ordinary fields. But if it's a bug in all existing clangs, it's a bug we're going to have to work around.

Hi Adrian,

Feel free to file a bug if you’re motivated. Personally speaking, I don’t expect this bug to be on anybody’s priority list. The workaround of using named structs/unions has no downside for most projects, and Swift is no exception.

Dave

···

--
Sent from my iPad

On Jan 4, 2018, at 20:11, Adrian Prantl <aprantl@apple.com> wrote:

On Dec 16, 2017, at 10:31 AM, John McCall via swift-dev <swift-dev@swift.org> wrote:

On Dec 16, 2017, at 9:08 AM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
int i;
union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
int a() { return X::i; } // works
int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

This seems like a bug; anonymous unions are just supposed to inject their member names into the containing scope as if there was an ordinary member there, and the explicit scope-qualification should resolve which subobject is meant for such injected names the same it resolves them for ordinary fields. But if it's a bug in all existing clangs, it's a bug we're going to have to work around.

Which should not prevent Dave from still reporting it on https://bugs.llvm.org/enter_bug.cgi?product=clang :slight_smile:

-- adrian

Hi Adrian,

Feel free to file a bug if you’re motivated. Personally speaking, I don’t expect this bug to be on anybody’s priority list. The workaround of using named structs/unions has no downside for most projects, and Swift is no exception.

Filed as https://bugs.llvm.org/show_bug.cgi?id=35832 <https://bugs.llvm.org/show_bug.cgi?id=35832>

John.

···

On Jan 4, 2018, at 8:29 PM, David Zarzycki <dave@znu.io> wrote:

Dave

--
Sent from my iPad

On Jan 4, 2018, at 20:11, Adrian Prantl <aprantl@apple.com> wrote:

On Dec 16, 2017, at 10:31 AM, John McCall via swift-dev <swift-dev@swift.org> wrote:

On Dec 16, 2017, at 9:08 AM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:

Hello,

I’m trying to improve SILNode memory layout density by adopting the AST bitfield macros. Unfortunately, multiple inheritance doesn’t seem to get along with anonymous/unnamed unions. Here is a distillation of the problem:

class B {
protected:
int i;
union { int j; };
};

class X : public B { };
class Y : public B { };

class Z : public X, public Y {
int a() { return X::i; } // works
int b() { return X::j; } // fails
};

Is this expected C++ behavior? I can certainly workaround this by naming the unnamed union, but before I do, I thought that I should check here first.

This seems like a bug; anonymous unions are just supposed to inject their member names into the containing scope as if there was an ordinary member there, and the explicit scope-qualification should resolve which subobject is meant for such injected names the same it resolves them for ordinary fields. But if it's a bug in all existing clangs, it's a bug we're going to have to work around.

Which should not prevent Dave from still reporting it on https://bugs.llvm.org/enter_bug.cgi?product=clang :slight_smile:

-- adrian