Fix DUChainUtils::getInheriters.
AbandonedPublic

Authored by mwolff on Nov 23 2015, 6:15 PM.

Details

Reviewers
kfunk
gsmolarczyk
Group Reviewers
KDevelop
Summary

It was incorrectly reporting inner classes as inheriters.

Diff Detail

Repository
R33 KDevPlatform
Branch
master
Lint
No Linters Available
Unit
No Unit Test Coverage
gsmolarczyk updated this revision to Diff 1351.Nov 23 2015, 6:15 PM
gsmolarczyk retitled this revision from to Fix DUChainUtils::getInheriters..
gsmolarczyk updated this object.
gsmolarczyk edited the test plan for this revision. (Show Details)
Restricted Application added a subscriber: kdevelop-devel. · View Herald TranscriptNov 23 2015, 6:15 PM
mwolff added a subscriber: mwolff.Nov 24 2015, 2:21 PM

Just a question: Is the clang builder correct in importing the base for the case you have in your unit test?

class foo { class inner {}; };

Why is inner importing foo - does anyone know? If that wouldn't be the case, then this patch here wouldn't be required. So before we accept this patch, I'd appreciate if someone could dig in a bit deeper and clarify whether it isn't a bug in kdev-clang that triggers the issue, instead of a generic DUChain issue here.

language/duchain/duchainutils.cpp
485

use auto

490

please merge the conditionals and add braces. also use longer variable names:

FOREACH_FUNCTION(const auto& base, childClass->baseClasses) {
    auto structureType = base.baseClass.type<StructureType>());
    if (structureType && structureType->declaration(topContext) == base) {
        return true;
    }
}

The surrounding code really should be cleaned up by someone from us eventually... Not your fault/concern of course.

gsmolarczyk updated this revision to Diff 1377.Nov 24 2015, 8:29 PM

Perform the requested changes.

gsmolarczyk marked 2 inline comments as done.Nov 24 2015, 8:37 PM
In D583#11138, @mwolff wrote:

Just a question: Is the clang builder correct in importing the base for the case you have in your unit test?

class foo { class inner {}; };

Why is inner importing foo - does anyone know? If that wouldn't be the case, then this patch here wouldn't be required. So before we accept this patch, I'd appreciate if someone could dig in a bit deeper and clarify whether it isn't a bug in kdev-clang that triggers the issue, instead of a generic DUChain issue here.

I am not sure about the importing stuff. I thought that it visualizes a dependency between types, like type Foo imports Bar because it cannot work without the Bar.
If that is indeed the case, then importing might be a good idea. You cannot lookup the id of the inner class without the outer class. But the basic definition of the inner class should not implicitly depend on the outer class.

Regardless, the code that marks the outer class as an import of the inner class is in language/clang/duchain/builder.cpp:423 in Visitor::createContext method. According to the code, every method and class imports its semantic parent. It might be a good idea for out-of-line method/class definition, but it is done even if semantic parent == lexical parent.

In the context of kdev-clang, "should" is a bit relative, as the plugin doesn't use the DUChain for any semantic analysis -- it's (almost) purely for visualization.
AFAICT this is just kdev-clang importing whatever clang reports with clang_getCursorSemanticParent. Since kdev-clang does have a special code-path for importing base classes as well, inheritance wouldn't be broken by simply not doing that anymore. It might break something else, but the tests should say one way or another. It's worth a shot I think, because imports make lots of lookups more expensive.

kfunk added a subscriber: kfunk.Feb 2 2016, 10:19 PM

What's the status her? (I didn't follow the discussion)

Well, I did not check the other proposed solution of stopping importing the semantic parent. That could fix this issue, but in my opinion would be more of a hack, unless the importing stuff should really be a synonym for inheritance.

I could try to make a change in kdev-clang and see how that performs.

kfunk requested changes to this revision.Feb 2 2016, 10:50 PM
kfunk added a reviewer: kfunk.

Okay, thanks for your feedback. Will mark this as WIP for now.

This revision now requires changes to proceed.Feb 2 2016, 10:50 PM
mwolff commandeered this revision.Feb 14 2016, 5:44 PM
mwolff added a reviewer: gsmolarczyk.

I've now pushed a proper fix for this issue to kdev-clang. No DUChain feature needs to be changed, it was a misuse of that API that triggered this issue. Olivier was right btw, we simply should not import the semantic parent context if it equals the lexical parent.

commit f945e0f03ee5bc49a0728e4bd7fdd239351745cc
Author: Milian Wolff <mail@milianw.de>
Date: Sun Feb 14 18:38:00 2016 +0100

Don't import the semantic parent if it equals the lexical parent.

We to import the semantic parent only if it differs from the lexical
parent, as then we deal with out-of-line declarations. For the other
case, the normal DUChain tree works fine. And importing the parent
again can lead to subtle differences, like DUChainUtils::getInheriters
misbehaving for nested classes.

This change should also have a nice positive performance impact.
mwolff abandoned this revision.Feb 14 2016, 5:44 PM

not required anymore

gsmolarczyk edited edge metadata.Feb 14 2016, 8:37 PM

I have tested these changes (btw: I had to compile 5.0 branch instead of master, it's a bit confusing that the newest fixes are firstly introduced on a release branch and then merged into master from time to time).

It indeed fixes the test case, but importing the semantic parent in case it's different from the lexical parent is still not a good idea. Just moving the inner class definition outside of the outer class reintroduces the problem, i.e. the inner class is claimed to be the inheritor of the outer class.

class X { class Y; };
class X::Y {};

We could remove this importing altogether, with hope that it won't break anything else.

Thanks for testing, I'll add your code as another test case and look at it. Afaik the import is required for the out-of-line definitions of methods, but maybe it's not required for classes. But as I said, I'll test it.

Regarding the operational way of 5.0 vs. master: We are trying to make sure that 5.0 is polished first, thus fixes such as the one here must go there first. master is open for new big changes or features, but these must not hold up a 5.0 release.

I've removed the import for nested classes now. Didn't break any tests, and fixes your issue. Thanks for the tests again!