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 issues 19655, 19656, 19657, 19746 & 19750 #9471

Merged
merged 4 commits into from Mar 21, 2019
Merged

Conversation

puneet
Copy link
Contributor

@puneet puneet commented Mar 20, 2019

The Semantic (pass 1) analysis for classes is handled by visit(ClassDeclaration ) method of DsymbolSemanticVisitor class. For a given class, this method may be run multiple times in order to resolve forward references. The method incrementally tries to resolve the types referred to by the members of the class.

The subsequent calls to this method are short-circuited if the class members have been fully analyzed. For this the code tests that it is not the first/main call to the method (semanticRun == PASS.init else branch), scx is not set, and that the cldec.symtab is already set. If all these conditions are met, the method returns. But before returning, the method was setting cldec.semanticRun to PASS.semanticdone. It should not set semanticRun since the class has not been fully analyzed yet. The base class analysis for this class could be pending and as a result vtable may not have been fully created.

This fake setting of semanticRun results in the semantic analyzer to believe that the class has been fully analyzed. As exposed by the issues 19656, 19657, 19746 and 19750, it may result in compile time errors when a derived type class is getting analyzed and because of this fake semanticdone on the base class, the semantic analysis construes that an overridden method is not defined in the base class. Issue 19655 exposes a scenario where a buggy vtable may be created and a call to class method may result in execution of some adhoc code.

The Semantic (pass 1) analysis for classes is handled by visit(ClassDeclaration ) method of DsymbolSemanticVisitor class. For a given class, this method may be run multiple times in order to resolve forward references. The method incrementally tries to resolve the types referred to by the members of the class.

The subsequent calls to this method are short-circuited if the class members have been fully analyzed. For this the code tests that it is not the first/main call to the method (semanticRun == PASS.init else branch), scx is not set, and that the cldec.symtab is already set. If all these conditions are met, the method returns. But before returning, the method was setting cldec.semanticRun to PASS.semanticdone. It should not set semanticRun since the class has not been fully analyzed yet. The base class analysis for this class could be pending and as a result vtable may not have been fully created.

This fake setting of semanticRun results in the semantic analyzer to believe that the class has been fully analyzed. As exposed by the issues 19656, 19657, 19746 and 19750, it may result in compile time errors when a derived type class is getting analyzed and because of this fake semanticdone on the base class, the semantic analysis construes that an overridden method is not defined in the base class. Issue 19655 exposes a scenario where a buggy vtable may be created and a call to class method may result in execution of some adhoc code.
@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @puneet! 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
19655 regression DMD generates wrong code for some circular dependencies
19656 regression D compiler fails to resolve circular module dependency when modules are compiled separately
19657 regression D compiler fails to resolve circular module dependency when modules are compiled together
19746 regression DMD fails to compile some circular dependencies spiced with is (T == super) condition
19750 regression [Reg v2.070.2] DMD fails with some circular module refs with Template/Mixin instances

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 "stable + dmd#9471"

@puneet puneet mentioned this pull request Mar 20, 2019
@puneet
Copy link
Contributor Author

puneet commented Mar 20, 2019

The tests fail because it is not able to create test_results/runnable/test19655.sh.out. The same happened with my local run. But a subsequent run was successful. Am I missing something?

@thewilsonator
Copy link
Contributor

I think generally we have either shell script tests or source tests but not both. If the related files need to be compiled all together the they should go in extra_files. @ZombineDev @jacob-carlborg ?

@UplinkCoder
Copy link
Member

@puneet can you consolidate your tests please?

@puneet
Copy link
Contributor Author

puneet commented Mar 20, 2019

@puneet can you consolidate your tests please?

I need multiple files because the import sequence is important to recreate the test scenario.

@puneet
Copy link
Contributor Author

puneet commented Mar 20, 2019

@puneet can you consolidate your tests please?

Alright, I get what you are saying. I now have created shell script wrappers that write out D files and then compiles. I will update the PR.

But I am still getting this error when I run the tests locally. But if I run make again, the error goes. As I understand the compile is happening too quickly and the makefile misses the output file. I can not make out why it happens for my sh files and not for the other sh tests that already exist.

Any clues?

Test compilable/test19656.sh failed. The logged output:
cat: test_results/compilable/test19656.sh.out: No such file or directory
Makefile:144: recipe for target 'test_results/compilable/test19656.sh.out' failed
make: *** [test_results/compilable/test19656.sh.out] Error 1

Copy link
Contributor

@thewilsonator thewilsonator left a comment

Choose a reason for hiding this comment

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

The tests are a bit hacky, but then so it the whole test suite. Lets get this merged.

@dlang-bot dlang-bot merged commit 58878ae into dlang:stable Mar 21, 2019
@wilzbach
Copy link
Member

The tests are a bit hacky,

That doesn't even cut it. Let's please please please only use shell tests when absolutely necessary as they slow down the testsuite, are harder to debug and port to other runtimes.

Also, creating files in the shell scripts is an absolute anti-pattern.

@puneet thanks a lot for your PR, but could you please convert these test to proper test files?
It's not that hard:

  • you add your main entry point in either compilable or runnable
  • you add all imports into the respective imports directory (shell scripts typically use extra-files btw)
  • Add these files as EXTRA_SOURCES like this:
// EXTRA_SOURCES: imports/abc.d imports/abc2.d

Copy link
Member

@wilzbach wilzbach left a comment

Choose a reason for hiding this comment

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

Just a few comments regarding the tests. Can you please give someone who's experienced with the testsuite a reasonable timeframe for reviewing?

void func (Thud ) { }
void thunk () { }
}
EOF
Copy link
Member

Choose a reason for hiding this comment

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

This should have been in extra-files instead of creating on-the-fly.

@@ -0,0 +1,57 @@
#! /usr/bin/env bash

TEST_DIR=${OUTPUT_BASE}
Copy link
Member

Choose a reason for hiding this comment

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

TEST_DIR is an existing exported variable.

export TEST_DIR=$1 # TEST_DIR should be one of compilable, fail_compilation or runnable

While possible, probably not a good idea to overwrite it.

${TEST_DIR}${SEP}test19657e.d ${TEST_DIR}${SEP}test19657f.d \
${TEST_DIR}${SEP}test19657g.d

rm -f ${TEST_DIR}${SEP}${TEST_NAME}${OBJ} ${TEST_DIR}${SEP}${TEST_NAME}*.d
Copy link
Member

Choose a reason for hiding this comment

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

Wasn't the entire point of creating a directory that you can remove it in one command?


TEST_DIR=${OUTPUT_BASE}

mkdir -p ${TEST_DIR}
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

  • (1) the files should have been not generated on the fly and placed e.g. in EXTRA_FILES
  • (2) ${OUTPUT_BASE}a would have worked too

export OUTPUT_BASE=${RESULTS_TEST_DIR}/${TEST_NAME} # reference to the resulting files without a suffix, e.g. test_results/runnable/test123


cat >${TEST_DIR}${SEP}test19657d.d <<EOF
import test19657a;
class Trump: Foo {}
Copy link
Member

Choose a reason for hiding this comment

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

Let's not be political here.

@@ -0,0 +1,51 @@
#! /usr/bin/env bash
Copy link
Member

Choose a reason for hiding this comment

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

This is an ill-formed pseudo she-bang header. It only works because the scripts aren't executed, but sourced.
I recommend removing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hello @wilzbach, thanks for your feedback.

I am willing to implement your suggestions, but I see that the PR is already merged. Should I still go ahead push the modifications?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it was merged too eagerly. Please do so by opening a new PR. Thanks!

@wilzbach
Copy link
Member

Ping. @thewilsonator - this is yet another example why waiting for more than a day is very important. Follow-ups to a PR happen rarely and thus the debt just aggregates ...

@MoonlightSentinel
Copy link
Contributor

Rework as non-shell test: #10908

ibuclaw pushed a commit to ibuclaw/dmd that referenced this pull request Mar 13, 2020
Fix issues 19655, 19656, 19657, 19746 & 19750
merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
ibuclaw added a commit that referenced this pull request Mar 13, 2020
[dmd-cxx] Fix issues 19655, 19656, 19657, 19746 & 19750 (#9471)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants