| Summary: | Problems with identifying a typedef template arguments in a CPPClassInstance object (binding of a template instance) | ||
|---|---|---|---|
| Product: | [Tools] CDT | Reporter: | Pavan V <pavan.ananth> |
| Component: | cdt-core | Assignee: | Project Inbox <cdt-core-inbox> |
| Status: | NEW --- | QA Contact: | Jonah Graham <jonah> |
| Severity: | normal | ||
| Priority: | P3 | CC: | sanjesh.nair, shanbala |
| Version: | 7.0 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows XP | ||
| Whiteboard: | |||
Introducing a separate binding for the TemplateClass<TYPEINT> would cause other issues:
Different to a typedef you'd have no way to get the expanded version of the type (for a typedef you use 'ITypedef.getType()') . This especially important when you have an explicit specialization
template<> class TemplateClass<int> {};
How could you figure out that 'TemplateClass<TYPEINT>' denotes the explicit specialziation 'TemplateClass<int>'?
Also consider the reverse of having an explicit specialization 'TemplateClass<TYPEINT>'. How would you see that 'TemplateClass<int>' denotes 'TemplateClass<TYPEINT>'?
Markus, not sure I understand your comment fully. Am not asking for a separate binding for TemplateClass<TYPEINT>, am only saying that the template argument inside the template instance here should hold ITypedef (instead of the IBasicType it holds here). From the ITypedef I can always do a getType() and retrieve the IBasicType - but the other way round is not possible Guess, CDT should be setting an ITypedef object on the template argument instead of the resolved type, as is the case with the setting of the type of a variable. (In reply to comment #2) > Markus, not sure I understand your comment fully. > > Am not asking for a separate binding for TemplateClass<TYPEINT>, am only saying > that the template argument inside the template instance here should hold > ITypedef (instead of the IBasicType it holds here). From the ITypedef I can > always do a getType() and retrieve the IBasicType - but the other way round is > not possible > > Guess, CDT should be setting an ITypedef object on the template argument > instead of the resolved type, as is the case with the setting of the type of a > variable. As soon as you request that the binding for the template instance (ICPPTemplateInstance) returns the typedef as the template argument (ICPPTemplateInstance.getTemplateArguments()) you do ask for two different bindings to represent 'TemplateClass<int>' and 'TemplateClass<TYPEINT>'. This would lead to the issues outlined above because there would be no link between the two bindings although they denote the same type. That would be the case in all places where a typedef can be used (as variable types, method parameter types, etc). When the typedef is represented as ITypedef in the binding in all these cases, why make an exception for a template argument ?
What I mean is, consider a method -
RETURN_TYPE testMethod(){
}
where RETURN_TYPE is a typedef denoting int.
If you notice the binding object for testMethod(), it can be seen that the return type of the method is a CPPTypedef object and not IBasicType. How does CDT link this to the method binding of -
int testMethod(){
}
I'm sure in all cases involving typedefs, there is internal logic to resolve to the final type from the typedef (using the call getType() on the typedef i suppose?) - the same should hold good for template arguments as well.
(In reply to comment #4) > That would be the case in all places where a typedef can be used (as variable > types, method parameter types, etc). When the typedef is represented as > ITypedef in the binding in all these cases, why make an exception for a > template argument ? I see your point. Note, that providing the typedef in the variable/function binding is and cannot be consistent. As soon as you use different notations for a type in a variable/function declaration the type returned by the binding will randomly be one of the versions. --> The type as specified by the user is not really a property of the binding, rather than that it is a property of a specific declaration. For variables and functions it is quite likely that the types are equally denoted in all declarations. Therefore, in general there will be no surprises. Given the complexity of template instantiation I am reluctant introduce a model that includes this random behavior. Therefore I argued that I'd need separate bindings for different versions of the same instantiation. I guess there is room for an implementation that randomly returns one of the notations for the template argument. However, this is not a small change and has some risk. Despite such a change, you would likely run into a situation where an unexpected version of argument is returned, because there are many instantiations (compared to the number of declarations for a function/variable). --> A risky change that yields a potentially unsatisfactory situation. I get your point. Perhaps, we could use the information in the AST to know if the argument is a typedef or not. As to implementing the tricky change, you can take a call on it. All I feel is that there should be some consistency in the design. (In reply to comment #6) > I get your point. > Perhaps, we could use the information in the AST to know if the argument is a > typedef or not. As to implementing the tricky change, you can take a call on > it. All I feel is that there should be some consistency in the design. I try to look into this for the next release. |
If a member field is of a typedef type, the getType() call on the ICPPField returns an object of type ICPPTypedef. However, if a member field is of a template instance type and one of the arguments is a typedef - the call getType() on the template argument ICPPTemplateArgument returns the resolved type of the typedef always and never ICPPTypedef. From the template instance binding object (CPPClassInstance) it is practically impossible to know if one of the template arguments is a typedef type. Steps to see the issue: 1. Create a header file with contents typedef int TYPEINT; template<class T> class TemplateClass{ }; class Usage{ TYPEINT var1; TemplateClass<TYPEINT> var2; }; 2. On the AST of this file, retrieve the bindings for the fields var1 and var2 inside class Usage. Notice that while the type of var1 is shown as ICPPTypedef while it is not possible to deduce this from the binding of the field var2