Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 18020 - [Reg 2.078] no property opCmp for anon class #7378

Merged
merged 1 commit into from Nov 30, 2017
Merged

Fix Issue 18020 - [Reg 2.078] no property opCmp for anon class #7378

merged 1 commit into from Nov 30, 2017

Conversation

JinShil
Copy link
Contributor

@JinShil JinShil commented Nov 30, 2017

ClassKind.anonymous is not a linkage type.

In this case, this should be targeting "master", right?

cc @RazvanN7

@dlang-bot
Copy link
Contributor

dlang-bot commented Nov 30, 2017

Thanks for your pull request, @JinShil!

Bugzilla references

Auto-close Bugzilla Description
18020 [Reg 2.078] no property opCmp for anon class

⚠️⚠️⚠️ Warnings ⚠️⚠️⚠️

Copy link
Member

@WalterBright WalterBright left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind the Jenkins failures

@jacob-carlborg
Copy link
Contributor

ClassKind.anonymous is not a linkage type.

Technically classes don't have linkage a type, only functions do. In the previous PR #7315, a couple of mutually exclusive booleans were converted to a single enum to actually enforce the exclusiveness. For example, a class cannot be anonymous and C++ or Objective-C at the same time.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

a class cannot be anonymous and C++ or Objective-C at the same time.

... but it can be ClassKind.d and anonymous at the same time, right? Hence the regression. I think the previous PR had too much refactoring in it and navigated away from the issue at hand.

Copy link
Contributor

@RazvanN7 RazvanN7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be the right way, but please also fix the issue stated in #7315

@jacob-carlborg
Copy link
Contributor

but it can be ClassKind.d and anonymous at the same time, right?

Yes.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

but please also fix the issue stated in #7315

Done.

@@ -719,7 +719,7 @@ private void membersToDt(AggregateDeclaration ad, DtBuilder dtb,
{
dtb.xoff(toVtblSymbol(concreteType), 0); // __vptr
offset = Target.ptrsize;
if (!cd.classKind == ClassKind.cpp)
if (cd.classKind != ClassKind.cpp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we look for more of these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did. I didn't find any. Feel free to check yourself.

@@ -242,6 +240,10 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
/// to prevent recursive attempts
private bool inuse;

/// true if this class has an identifier, but was originally declared anonymous
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to mention the second part, after the comma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, yes.

@@ -242,6 +240,10 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
/// to prevent recursive attempts
private bool inuse;

/// true if this class has an identifier, but was originally declared anonymous
/// used in support of https://issues.dlang.org/show_bug.cgi?id=17371
private bool isActuallyAnonymous;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the D convention is, as far as I know, to use the same name as the getter but prefix it with an underscore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen that. Show me where the precedent is established.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know where/if it's written down somewhere. But I think the name is a bit strange anyway, having Actually as part of the name doesn't add anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Actually" documents the fact that we are lying, because the class has a __anonclass identifier. And remember I had to overload a method called isAnonymous, so that name is off limits.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And remember I had to overload a method called isAnonymous, so that name is off limits.

That's why it's common to name the field either _isAnonymous or isAnonymous_. I prefer the latter but I think the former is more common in Phobos.

Copy link
Contributor Author

@JinShil JinShil Nov 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why it's common to name the field either _isAnonymous or isAnonymous_

I would prefer something like that as well, but that doesn't seem to be the convention in DMD.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but in the rest of the D community, at least in the core projects, the ones in the dlang GitHub organization. Keep in mind that DMD is quite an old code base written in a very old style, C with classes. We're trying to improve that and in my opinion any new code should follow the standard D conventions. We don't want to make it worse by adding new code that is written in the old style 😃.

@jacob-carlborg
Copy link
Contributor

The C++ header need to be updated as well.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

The C++ header need to be updated as well.

aggregate.h was updated. Are you referring to something else?

@jacob-carlborg
Copy link
Contributor

aggregate.h was updated. Are you referring to something else?

No, but the new field was not added.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

No, but the new field was not added.

Which new field?

@RazvanN7
Copy link
Contributor

@jacob-carlborg It shouldn't, since it is private.

@jacob-carlborg
Copy link
Contributor

isActuallyAnonymous.

@jacob-carlborg
Copy link
Contributor

The sizes of the D and the C++ classes need to match, as far as I know.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

The sizes of the D and the C++ classes need to match, as far as I know.

None of the private fields are declared in aggregate.h::ClassDeclaration. Please be more specific, I'm getting confused. What precisely needs to be done?

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Nov 30, 2017

None of the private fields are declared in aggregate.h::ClassDeclaration

It was only one, inuse, before this new field, which was recently added. Which I think needs to be added as well. Currently, if the C++ code tries to access the isabstract field it will actually get the inuse field, if I understand how this works.

Please be more specific, I'm getting confused. What precisely needs to be done?

Please add the inuse and the isActuallyAnonymous fields to the C++ header aggregate.h::ClassDeclaration.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

Please add the inuse and the isActuallyAnonymous fields to the C++ header aggregate.h::ClassDeclaration.

Done. Thank you!

@jacob-carlborg
Copy link
Contributor

Example:

$ cat foo.d
module foo;

struct Foo
{
    private int a;
    int b;
}

extern (C) Foo* getFoo()
{
    import core.stdc.stdlib;

    auto foo = cast(Foo*) malloc(Foo.sizeof);
    foo.a = 3;
    foo.b = 4;

    return foo;
}
$ dmd -c -betterC foo.d
$ cat main.c
#include <stdio.h>

struct Foo
{
    int b;
};

struct Foo *getFoo();

int main (int i, char** c)
{
    struct Foo *foo = getFoo();
    printf("%d\n", foo->b);
}
$ clang main.c -o main foo.o
$ ./main
3

The above prints 3 and not 4 because the sizes of the structs on the D side and the C side doesn't match. It's the same idea with the D class and the C++ class.

@jacob-carlborg
Copy link
Contributor

Done. Thank you!

The C++ header file looks good now.

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Nov 30, 2017

BTW, if you want to, the fields can be private on the C++ side as well. Although I'm not sure if the inuse field is used by LDC/GDC.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

BTW, if you want to, the fields can be private on the C++ side as well.

I'm don't want to refactor anything; I just want to fix the regression. The others fields are public so the new fields are public. If we need to be specific with access modifiers for the C++ interface, I think it should be done in a different PR.

@jacob-carlborg
Copy link
Contributor

I'm don't want to refactor anything; I just want to fix the regression

Fair enough.

@jacob-carlborg
Copy link
Contributor

LGTM 👌.

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

The only thing preventing me from pulling this is I'm not sure if it should target master or stable. The PR that introduced this regression was only merged yesterday, so I'm guessing it needs to go to master. Please advise.

@jacob-carlborg
Copy link
Contributor

The only thing preventing me from pulling this is I'm not sure if it should target master or stable. The PR that introduced this regression was only merged yesterday, so I'm guessing it needs to go to master. Please advise.

@MartinNowak ^

@JinShil
Copy link
Contributor Author

JinShil commented Nov 30, 2017

It must be master. I don't see the changes in stable yet. auto-merge toggling on.

@dlang-bot dlang-bot merged commit 39981da into dlang:master Nov 30, 2017
@JinShil JinShil deleted the fix_18020 branch November 30, 2017 11:59
@MartinNowak
Copy link
Member

... but it can be ClassKind.d and anonymous at the same time, right?

In fact anonymous classes always seem to be ClassKind.d, at least I didn't manage to produce a non-D anon class. But it's better to make this explicit, instead of relying on the fact that sth. cannot be expressed in the language's grammar.

@MartinNowak
Copy link
Member

The PR that introduced this regression was only merged yesterday, so I'm guessing it needs to go to master.

Hence [Reg 2.078] which is the next upcoming release, it means the fix needs to go into 2.078.0, which will be branched off master on Dec 15 2017, and gets released on Jan 1 2018.
Also see https://calendar.google.com/calendar/embed?src=ut29n9vq9vu3ad4kbaabeed1d8%40group.calendar.google.com.

@jacob-carlborg
Copy link
Contributor

In fact anonymous classes always seem to be ClassKind.d, at least I didn't manage to produce a non-D anon class.

Yes, that's correct. It was originally put in the enum to enforce that a class in the AST should not be anonymous and Objective-C/C++ at the same time. Which was possible before and is now possible again.

@MartinNowak
Copy link
Member

Which was possible before and is now possible again.

Well it's still not possible in the language and the code the more self-explaining now.

@jacob-carlborg
Copy link
Contributor

the code the more self-explaining now

I disagree. Ideally the API should force you do to the correct things as much as possible. In this case none of the solutions are prefect.

@MartinNowak
Copy link
Member

Could easily add an assertion that anonymous implies extern(D) atm.

@@ -269,7 +269,7 @@ extern (C++) class Dsymbol : RootObject
return false;
}

final bool isAnonymous()
bool isAnonymous()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you made this function virtual, but didn't reflect it in c++ headers?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I had the C++ headers covered but apparently not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #7385

WalterBright added a commit that referenced this pull request Dec 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants