Hi Swapnil,
Thanks for your interest in GSoC!
As for the "Extend clang AST to provide information for the type as written in template instantiations", the ClassTemplateSpecializationDecl represents the canonicalized
result of forming the specialization, so
using Foo = int;
vector<Foo> x;
vector<int> y;
auto v = x.begin();
... will result in x and y denoting the same ClassTemplateSpecializationDecl. It doesn't make sense for that declaration to track the sugared type, because that declaration is used for accesses with different sugar. The type sugar should not ever affect the behavior of the instantiation, so should not be part of the instantiation. Rather, it's part of the way that the instantiation is named, so should be part of that naming context.
For example, when we form the "x.begin" expression in the above example (in BuildMemberReferenceExpr or somewhere near there), we
could:
* take the type T1 of 'x':
`-TemplateSpecializationType 0xdafa140 'vector<Foo>' sugar vector
>-TemplateArgument type 'Foo':'int'
`-RecordType 0xdafa120 'vector<int>'
`-ClassTemplateSpecialization 0xdafa040 'vector'
* take the type T2 of 'begin':
`-FunctionProtoType 0xdb287b0 'vector<int,
allocator<int>>::iterator ()' cdecl
`-RecordType 0xdb28780 'vector<int, allocator<int>>::iterator'
`-CXXRecord 0xdafa428 'iterator'
* form a new type sugar node (say, MemberSugarType) that tracks T1 and T2, and has the same canonical type as T2, but that has custom desugaring logic to allow it to produce a more friendly type name
In this case, desguaring a MemberSugarType wrapped around a FunctionProtoType would push the member sugar onto the return type and parameter types of the type; desugaring a MemberSugarType wrapped around a RecordType representing a member of the type tracked by a MemberSugarType would form an ElaboratedType describing the name of that member as a member of the sugared type. So we'd end up with the type of "x.begin" desugaring to vector<Foo>::iterator(), as desired. (When we grab the return type of a function in a function call, we'll need to be careful to single-step desugar it until we reach a function type, to move the sugar onto the return type. And likewise in other places too.)
Likewise, for x.front(), where the type of 'front' is something like:
\`\-FunctionProtoType 0xdb3a0b0 'vector<int, allocator<int>
> ::value_type ()' cdecl
`-TypedefType 0xdb3a060 'vector<int, allocator<int> >::value_type' sugar
>-TypeAlias 0xdb39e38 'value_type'
`-SubstTemplateTypeParmType 0xdb39910 'int' sugar
>-TemplateTypeParmType 0xdb09a80 'T' dependent depth 0 index 0
> `-TemplateTypeParm 0xdb09a38 'T'
`-BuiltinType 0xdacd950 'int'
... we'd wrap that in a MemberSugarType, and desugaring the wrapped function type would produce a function type whose parameter and return types are wrapped. But then we can do something more: once we get to a MemberSugarType wrapped around a SubstTemplateTypeParmType, we can desugar that type to "Foo" (taking the type sugar for the template argument from the TemplateSpecializationType). So we can desugar the type of a call to x.front() to Foo.
You'd need to work out exactly what kinds of sugar type nodes to add, and which information it makes sense to track in the sugar type. For instance, it might make sense for the sugar type that we use for a class member access to track whether the member was found in the type of the object expression (the expression to the left of the . or ->), or if it was found in a base class (and if so, which one).
This information was provided a last year GSoC candidate by Richard Smith. It should contain enough hints for you to assess if that's something interesting to do this summer.
In the meantime, could you send Richard and me your CV?
Best, Vassil
PS: Thanks Stefanos for cc-ing us!