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 19185 - [ICE] Nested struct segfaults when using variable from outer scope #8597

Merged
merged 1 commit into from
Sep 6, 2018

Conversation

RazvanN7
Copy link
Contributor

The context pointer was not initialized when when the nested struct was constructed implicitly.

@dlang-bot
Copy link
Contributor

dlang-bot commented Aug 22, 2018

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 verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the annotated coverage diff directly on GitHub with CodeCov's browser extension
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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

Auto-close Bugzilla Severity Description
19185 normal [ICE] Nested struct segfaults when using variable from outer scope

Testing this PR locally

If 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"

* Returns:
* The expression initializer
*/
private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
Copy link
Contributor

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.

Copy link
Contributor Author

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)

*
* Returns:
* The expression initializer
*/
Copy link
Contributor

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.

Copy link
Member

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.

@jacob-carlborg
Copy link
Contributor

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())
Copy link
Contributor Author

@RazvanN7 RazvanN7 Aug 23, 2018

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.

* 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
Copy link
Member

Choose a reason for hiding this comment

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

t1 => t

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);
Copy link
Member

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().

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

* t = the type of the expression
*
* Returns:
* The expression initializer
Copy link
Contributor

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.

Copy link
Contributor

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));
Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Member

@MartinNowak MartinNowak left a 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.

@RazvanN7
Copy link
Contributor Author

RazvanN7 commented Sep 3, 2018

@MartinNowak is this better?

return setError();
Expression einit = getInitExp(sd, exp.loc, sc, t1);
if (einit.op == TOK.error)
return setError();
Copy link
Contributor

@JinShil JinShil Sep 4, 2018

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 setError to take an ErrorExp
  • instead of return setError() do result = einit; return;

Maybe there is another solution, but those are the two that come to mind for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@RazvanN7 RazvanN7 dismissed MartinNowak’s stale review September 5, 2018 08:54

Required changes were implemented

@PetarKirov PetarKirov closed this Sep 6, 2018
@PetarKirov PetarKirov reopened this Sep 6, 2018
@jacob-carlborg
Copy link
Contributor

160 commits!! This does't look correct 😃.

@RazvanN7
Copy link
Contributor Author

RazvanN7 commented Sep 6, 2018

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.

@dlang-bot dlang-bot merged commit 88de313 into dlang:master Sep 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants