-
-
Notifications
You must be signed in to change notification settings - Fork 610
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 19185 - [ICE] Nested struct segfaults when using variable from outer scope #8597
Conversation
|
Thanks for your pull request and interest in making D better, @RazvanN7! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + dmd#8597" |
src/dmd/expressionsem.d
Outdated
| * Returns: | ||
| * The expression initializer | ||
| */ | ||
| private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t) |
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.
I wonder if functions like this should actually be member functions of the class.
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.
It could be made a nested function inside visit(AssignExp)
src/dmd/expressionsem.d
Outdated
| * | ||
| * Returns: | ||
| * The expression initializer | ||
| */ |
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.
If we want to be strict about the style (https://dlang.org/dstyle.html#phobos_documentation) we should not prepend * characters on each line. But I don't think it should hold up this PR.
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.
The remark about not using leading * in documentation was added to the style guide in January of this year and reflects Phobos but doesn't reflect the style of the existing DMD codebase. IMO the most important thing is maintaining consistency within a document.
|
Perhaps because I’m reading this on my phone but I don’t see what actually fixed the issue. |
| return new IntegerExp(loc, 0, Type.tint32); | ||
| } | ||
|
|
||
| if (sd.isNested()) |
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.
Perhaps because I’m reading this on my phone but I don’t see what actually fixed the issue.
@jacob-carlborg This block of code is executed. Before this patch, it would have not.
src/dmd/expressionsem.d
Outdated
| * sd = the struct for which the expression initializer is needed | ||
| * loc = the location of the initializer | ||
| * sc = the scope where the expression is located | ||
| * t1 = the type of the expression |
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.
t1 => t
src/dmd/expressionsem.d
Outdated
| Expression einit; | ||
| einit = new BlitExp(exp.loc, e1x, e1x.type.defaultInit(exp.loc)); | ||
| Expression einit = getInitExp(sd, exp.loc, sc, t1); | ||
| einit = new BlitExp(exp.loc, e1x, einit); |
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.
Note to other reviewers: it's fine that this PR replaces e1x.type with t1 because here e1x is exp.e1 and t1 is exp.e1.type.toBasetype().
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.
Note that einit is assigned twice. A better method is to assign it only once.
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.
Fixed.
src/dmd/expressionsem.d
Outdated
| * t = the type of the expression | ||
| * | ||
| * Returns: | ||
| * The expression initializer |
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.
I think this should mention that it might return null and why.
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.
Or, better yet, shouldn't this return an ErrorExp and then check for TOK.error in the caller?
| @@ -6833,8 +6851,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor | |||
| } | |||
| } | |||
|
|
|||
| Expression einit; | |||
| einit = new BlitExp(exp.loc, e1x, e1x.type.defaultInit(exp.loc)); | |||
| Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1)); | |||
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.
getInitExp might return null, but there's no check for null in the BlitExp class hierarchy. It seems like a segfault waiting to happen. Should there be an if (!einit) return setError(); here also?
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.
Better yet, getInitExp should just return an ErrorExp and thus turn any use of such expressions into an error as well.
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.
I agree with @JinShil here, getInitExp should return an ErrorExp instead of null.
da54cd0 to
512c2b1
Compare
|
@MartinNowak is this better? |
src/dmd/expressionsem.d
Outdated
| return setError(); | ||
| Expression einit = getInitExp(sd, exp.loc, sc, t1); | ||
| if (einit.op == TOK.error) | ||
| return setError(); |
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.
This is redundant. getInitExp returned an ErrorExp and then setError immediately creates a new ErrorExp and assigns it to result. I see few options:
- create an overload of
setErrorto take anErrorExp - instead of
return setError()doresult = einit; return;
Maybe there is another solution, but those are the two that come to mind for me.
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.
Done
512c2b1 to
609db94
Compare
Required changes were implemented
609db94 to
9b5a295
Compare
|
160 commits!! This does't look correct 😃. |
|
I wanted to fix the semaphore issue by rebasing master, but I forgot I was targeting stable :(. I'm just gonna target master for now. |
The context pointer was not initialized when when the nested struct was constructed implicitly.