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
Issue 21693 - Lower scoped destruction of extern(C++) class to destroy/dtor call #12265
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
e28736c
Issue 21693 - Lower scoped destruction of extern(C++) class to destroy
MoonlightSentinel 57858e4
Mimic struct destruction for stack allocated classes
MoonlightSentinel aa2147b
fixup! Issue 21693 - Lower scoped destruction of extern(C++) class to…
MoonlightSentinel File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
https://issues.dlang.org/show_bug.cgi?id=21693 | ||
|
||
RUN_OUTPUT: | ||
--- | ||
CppA: | ||
1: CppA.~this | ||
CppB: | ||
2: CppB.~this | ||
2: CppA.~this | ||
CppC: | ||
3: CppC.~this | ||
3: CppB.~this | ||
3: CppA.~this | ||
CppC: | ||
4: CppC.~this | ||
4: CppB.~this | ||
4: CppA.~this | ||
CppNoDestruct: | ||
DA: | ||
1: DA.~this | ||
DB: | ||
2: DB.~this | ||
2: DA.~this | ||
DC: | ||
3: DC.~this | ||
3: DB.~this | ||
3: DA.~this | ||
DC: | ||
4: DC.~this | ||
4: DB.~this | ||
4: DA.~this | ||
--- | ||
*/ | ||
|
||
extern (C) int printf(scope const char*, ...); | ||
|
||
extern (C++) class CppA | ||
{ | ||
int num; | ||
this(int num) | ||
{ | ||
this.num = num; | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: CppA.~this\n", num); | ||
} | ||
} | ||
|
||
extern (C++) class CppB : CppA | ||
{ | ||
this(int num) | ||
{ | ||
super(num); | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: CppB.~this\n", num); | ||
} | ||
} | ||
|
||
extern (C++) class CppC : CppB | ||
{ | ||
this(int num) | ||
{ | ||
super(num); | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: CppC.~this\n", num); | ||
} | ||
} | ||
|
||
extern (D) class DA | ||
{ | ||
int num; | ||
this(int num) | ||
{ | ||
this.num = num; | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: DA.~this\n", num); | ||
} | ||
} | ||
|
||
extern (D) class DB : DA | ||
{ | ||
this(int num) | ||
{ | ||
super(num); | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: DB.~this\n", num); | ||
} | ||
} | ||
|
||
extern (D) class DC : DB | ||
{ | ||
this(int num) | ||
{ | ||
super(num); | ||
} | ||
|
||
~this() | ||
{ | ||
printf("%d: DC.~this\n", num); | ||
} | ||
} | ||
|
||
extern (C++) class CppNoDestruct | ||
{ | ||
int num; | ||
this(int num) | ||
{ | ||
this.num = num; | ||
} | ||
} | ||
|
||
void main() | ||
{ | ||
printf("CppA:\n"); { scope a = new CppA(1); } | ||
printf("CppB:\n"); { scope CppA b = new CppB(2); } | ||
printf("CppC:\n"); { scope CppA c = new CppC(3); } | ||
printf("CppC:\n"); { scope CppB c2 = new CppC(4); } | ||
|
||
printf("CppNoDestruct:\n"); | ||
{ | ||
scope const nd = new CppNoDestruct(1); | ||
} | ||
|
||
printf("DA:\n"); { scope a = new DA(1); } | ||
printf("DB:\n"); { scope DA b = new DB(2); } | ||
printf("DC:\n"); { scope DA c = new DC(3); } | ||
printf("DC:\n"); { scope DB c2 = new DC(4); } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destroy
should be used instead ofdelete
for for D classes, too: https://issues.dlang.org/show_bug.cgi?id=21692There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destroy
doesn't work forconst
/immutable
either (unless we insert an explicit cast to mutable)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented another approach, it's now directly calling the dtor (effectively inlining the call to
destroy
).This matches the implementation for
struct
s and allows the hack to call dtors on immutable instances.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it does (tested with v2.096.0). Anyway, the direct dtor call is better. Is there a reason you don't use it for D classes too? I find it inconsistent (can use
scope const/immutable
with C++ classes, but not with D ones) and don't really like deprecated expressions in compiler-generated AST nodes. ;)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, seems like it was an issue with the lowering.
Mostly because
destroy
(anddelete
IIRC) refer tort_finalize2
which does more cleanup than just calling the dtor. Not sure if those additional steps are required for stack allocated instances...But lowering to
destroy
would still work for D classes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that'd be great.
You're right, for D classes, there's apparently the need to descend to all base classes and invoke the dtors manually (via TypeInfo... argh), and the monitor might need cleanup too. LDC has a special case for these
delete
expressions forscope
classes and tries to avoid calling druntime if the class has no finalizer and the monitor is null: https://github.com/ldc-developers/ldc/blob/937c57b8354d4821daededb35abdb77d16ce3737/gen/classes.cpp#L200-L222Doing this here in the frontend directly would obviously be much nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the best way forward is to replace the
TypeInfo
based dtor-loop in DRuntime with a real dtor chain as done for C++ classes and to move the cleanup into `Object.~this()). That would cause less (magic) code scattered across dmd/druntime/ldc/... .Anyway, lowering to
destroy
doesn't work yet.@nogc
destroy
(it needs some special casing as done fordelete
)