Bug 183614 - Code completition inside template specialization not working
Summary: Code completition inside template specialization not working
Status: RESOLVED FIXED
Alias: None
Product: kdevelop
Classification: Applications
Component: Language Support: CPP (old) (show other bugs)
Version: unspecified
Platform: unspecified Linux
: HI normal
Target Milestone: ---
Assignee: kdevelop-bugs-null
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-02-07 22:17 UTC by Thomas McGuire
Modified: 2012-10-15 12:54 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas McGuire 2009-02-07 22:17:24 UTC
Version:            (using KDE 4.2.0)
OS:                Linux

I have the following code:

class Foo
{
    public:

        template<class T>
        Foo& operator << ( T& value ) {
        }

        void bar(){}
};

template<>
Foo& Foo::operator<<( std::string& value )
{
    this-><cursor>
}

If I now try to invoke code completion, KDevelop does nothing.
It should at least offer me to call bar().

(BTW, the summary is probably wrong, I don't know if this is really a template specialization)
Comment 1 Andreas Pakulat 2009-07-25 15:39:08 UTC
Interestingly it works just fine if one doesn't use this->, but just starts completion on the empty line. Then I get bar+operator<< on the completion list.
Comment 2 Olivier.jg 2009-12-01 07:29:06 UTC
FunctionContexts seem to operate on the assumption that for every declaration there is one definition. Since the template allows any number of additional definitions for any given declaration, any definitions after the first have no mapping to the declaration, therefore it's unable to find the class context it that the function belongs to.
As far as I can tell, the only reason it works without the "this" is because it then gets to MissingIncludeCompletion.
So a dirty little hack would be to detect this happenstance and give it MissingIncludeCompletion, but to fix the real underlying problem could mean a healthy amount of work, affecting much of the cpp support (in particular I'm thinking of the cpp codegen codeassistant, but the real implications are unknown to me).
I might be interested in chewing on the full solution when I have a larger chunk of time, but should that even happen in this release? Is a dirty hack better for now? Or perhaps not consider this bug a 4.0.0 target?
Comment 3 David Nolden 2009-12-05 13:33:46 UTC
@Olivier.jg:
It won't need such a high amount of work to get this basically working.

What seems to work: The context of the class "Foo" is correctly imported into the function-context, so the function and the class have _some_ connection.

What doesn't work here is the correct resolution of the "this" expression, which happens at expressionvisitor.cpp:667. It indeed relies on the definition -> declaration mapping there.

However the definition/declaration mapping is _not_ unique, which means that multiple definitions can be mapped to one declaration. There's a semantic problem here though, is the 'definition' mentioned in this case is _not really_ a definition, but rather a _specialization_ declaration, so that definition/declaration mapping probably shouldn't even be used here.

The proper solution here would be:
A) Make sure that the specialization and the declaration are connected through TemplateDeclaration::specializations() and TemplateDeclarations::specializedFrom(), as I didn't care about explicit function specializations until now.
B) At expressionvisitor.cpp:673, when no function-declaration was retrieved through definition/declaration mapping, try retrieving the declaration through "dynamic_cast<TemplateDeclaration*>(..)->specializedFrom().data()".

Should you try to fix this, a unit-test in test_expressionparser.cpp to verify these things would be great.
Comment 4 Olivier.jg 2010-12-18 13:19:37 UTC
All clear on the expressionvisitor part, but as you suspected, the specialization and declaration are not connected.
I can see in DeclarationBuilder where I assume this should be happening, but it looks like it only does setSpecializedFrom() when there are template identifiers (declarationbuilder.cpp:590).

Given the AbstractFunctionDeclaration cast combined with a TemplateDeclaration cast, I can identify the functions that should be specialized, I only wonder what's the best way to get the declaration that they're specialized from.

Also, I'm just thinking functions because of this bug, but should every TemplateDeclaration have an associated specializedFrom?
Comment 5 David Nolden 2010-12-30 18:15:16 UTC
Only those TemplateDeclarations that are _specializations_ should have a SpecializedFrom. If the function has no teimplate identifiers, then it isn't specialized, no? In that case, the mapping between definition and declaration should simply happen through definitionForDeclaration(..) and declarationForDefinition(..) mechanism (in definitions.h/cpp I think). However I also think that this already works for non-specialized template functions.
Comment 6 Olivier.jg 2011-06-13 09:37:39 UTC
The function in the example case doesn't have any template identifiers, but the fact that the template context has no declarations should give it away as a specialization anyhow.

On the other hand, there are no imported parent contexts for that function declaration, definitionForDeclaration doesn't seem to exist, and declarationForDefinition (from duchainutils.cpp) just returns itself.

So the question is: from where do you get the declaration that the specialization is specializedFrom?
Comment 7 David Nolden 2011-06-18 20:31:36 UTC
Is this specialization actually valid? Shouldn't it be written like this?:

template<>
Foo& Foo::operator<< <std::string>( std::string& value )

eg. with template-identifiers.

The specializedFrom should be set in DeclarationBuilder::openDeclarationReal, but it's tailored for class-declarations at the moment.
Comment 8 Olivier.jg 2012-10-15 12:54:34 UTC
Git commit cdf19180a4016db1b6ec5c772fbb9299107ddda7 by Olivier JG.
Committed on 15/10/2012 at 14:51.
Pushed by olivierjg into branch 'master'.

Support function specialization in the CPP DUChain. Add tests.
REVIEW: 106765

M  +79   -40   languages/cpp/cppduchain/declarationbuilder.cpp
M  +3    -0    languages/cpp/cppduchain/declarationbuilder.h
M  +8    -1    languages/cpp/cppduchain/expressionvisitor.cpp
M  +1    -4    languages/cpp/cppduchain/tests/test_duchain.cpp
M  +50   -0    languages/cpp/cppduchain/tests/test_expressionparser.cpp
M  +1    -0    languages/cpp/cppduchain/tests/test_expressionparser.h

http://commits.kde.org/kdevelop/cdf19180a4016db1b6ec5c772fbb9299107ddda7