[cfe-dev] Access to user supplied argument list when instantiating the injected-class-name
Mihai Rusu
dizzy at google.com
Fri Mar 25 18:52:53 PDT 2011
Hi,
I'm working on http://llvm.org/bugs/show_bug.cgi?id=7238 and I'm
trying to improve clang display (in diagnostics) of the
injected-class-name instantiations (which is why I think diagnostics
are so verbose in that bug) to omit showing the arguments that where
not specified by the user (but which took values from the default
parameters). Example, for this code:
template<typename T, typename Default = void>
struct S {
typedef S type1;
};
int main() {
float f = S<int>::type1();
}
The produced error:
error: no viable conversion from 'S<int>::type1'
(aka 'S<int, void>') to 'float'
float f = S<int>::type1();
^ ~~~~~~~~~~~~~~~
"clang" could do better and not have to display "void" but use the
user supplied argument list when instantiating the
injected-class-name.
Now, when clang parses the template class definition it creates an
InjectedClassNameType that caches a pointer to a
TemplateSpecializationType that uses all arguments (in the above
example it would make a TemplateSpecializationType for "S<T,
Default>"). This makes sense since when it's parsing the definition it
cannot know yet which instantiations will happen.
Further in the code "clang" tries to instantiate "S<int>" and it
creates a TemplateSpecializationType<converted-arguments> (where the
arguments are completed, including the default values) but it also
caches a TemplateSpecializationType as the user wrote it (in
Sema::ActOnExplicitInstantiation). It then goes through the code to
instantiate the TemplateInstantiationType with complete arguments by
creating a TemplateDeclInstantiator and using it to visit every member
of the class template. The "typedef" visitor handling function will
want to resolve the dependent source type (the injected class name)
and it does so calling SubstType which calls FindInstantiatedDecl and
finally it is this function that takes the TemplateSpecializationType
cached earlier by the InjectedClassNameType (created when the class
definition was parsed) and further substitutes the types.
It is in FindInstantiatedDecl() that I'm thinking of adding some code
that would create a temporary copy of the injected-class-name
TemplateSpecializationType but only copying the number of the
arguments that the user used (so from "S<T, Default>" I want to create
an "S<T>" and call SubstType on that). Problem is that in
FindInstantiatedDecl() I don't seem to have anymore the user given
argument list (seems to be lost when the typedef visitor handler calls
SubstType on the source type). The available argument list is a
MultiLevelArgumentList instance that was built from the completed
argument lists of each context.
Any suggestions how to get the length of that list at this point? Or
if you have any other suggestions please let me know, thanks.
--
Mihai Rusu
More information about the cfe-dev
mailing list