[cfe-dev] On template instantiations and specializations.

Douglas Gregor dgregor at apple.com
Tue Jun 15 07:59:01 PDT 2010


On Jun 15, 2010, at 12:35 AM, Enea Zaffanella wrote:

> Abramo Bagnara wrote:
>> Il 14/06/2010 22:33, Douglas Gregor ha scritto:
>>> Hello Enea,
>>> 
>>> On Jun 14, 2010, at 2:33 AM, Enea Zaffanella wrote:
>>> 
>>>> Hello.
>>>> 
>>>> clang AST is missing nodes able to represent various kinds of instantiations and/or specializations of (member of class) templates, such as the following:
>>>> 
>>>> ============================================
>>>> // Explicit specialization.
>>>> template <> void foo<int>(int a) {}
>>>> 
>>>> // Explicit instantiation declaration.
>>>> extern template void foo<char*>(char* s);
>>>> 
>>>> typedef char Char;
>>>> // Another (redundant) explicit inst. decl.
>>>> extern template void foo(Char* s);
>>>> 
>>>> // Explicit instantiation definition.
>>>> template void foo(double);
>>>> ============================================
>>>> 
>>>> Quoting from Sema::SemaTemplate.cpp:
>>>> 
>>>>    // FIXME: Create an ExplicitInstantiation node?
>>>> [...]
>>>>   // FIXME: We may still want to build some representation of this
>>>>   // explicit specialization.
>>>> [...]
>>>>  // FIXME: Create some kind of ExplicitInstantiationDecl here.
>>>> 
>>>> We would like to hear opinions about the following proposal for filling in those FIXMEs. The main goal is to provide a better distinction between the syntactic and semantic issues. As hinted in the comments above, we should introduce a new Decl node whose purpose is to represent all syntactic aspects of the explicit specialization/instantiation of (members of) templates. Let us call this new class (better names are welcome)
>>>> 
>>>>   ExplicitSpecOrInstDecl
>>>> 
>>>> In our opinion, this class should be derived directly from Decl (rather than inheriting from more concrete classes), provide all and only the syntactic info which is peculiar of explicit template specializations/instantiations (i.e., source locations of the optional "extern" keyword, of the "template" keyword and of the optional "<>" brackets) and then contain an appropriate Decl node for a proper representation of the other stuff. That is, the new node will be somehow similar to a LinkageSpecDecl node (but it will not be a DeclContext).
>>>> 
>>>> Note that even the declaration contained in the ExplicitSpecOrInstDecl node will be mainly providing syntactic info: that is, for a construct such as
>>>> 
>>>>  extern template void foo(Char* s);
>>>> 
>>>> we will have an ExplicitSpecOrInstDecl node
>>>> (representing "extern template")
>>>> containing a FunctionDecl node
>>>> (representing "void foo(Char* s);"
>>> I agree that this is a good way to model explicit instantiations and specializations.
>>> 
>>>> The actual, semantic instantiation of the function template foo for template argument char* will be stored somewhere else (and will be possibly be completely unaffected by this syntactic declaration).
>>> We'll need to create a (re-)declaration of the function template specialization that contains the various parameters, template arguments, etc. as written in the explicit specialization or instantiation. 
>>>> If the proposal above makes some sense, then we should also consider whether or not it would be appropriate to extend it to the case of class template specializations or instantiations (and even member classes of class templates). We stress this point because currently for class template a different approach is being used, whereby a class template specialization is inheriting from CXXRecordDecl. This in our opinion is a suboptimal design choice.
>>> There is a difference here... FunctionDecl stores its template arguments and associated specialization information in members, while CXXRecordDecl has the ClassTemplateSpecializationDecl subclass to store this information. How is it suboptimal?
>> What'is the reason to not follow a similar pattern to what is proposed
>> above for functions?
> 
> Having a uniform approach is one of the pros.
> 
> Anyway, when reasoning about the suboptimality of design, I was (implicitly) referring to the whole CXXRecordDecl inheritance hierarchy.
> It may just be a matter of taste (no one here is pretending to separate what is "right" from what is "wrong"), but I find it strange to see a ClassTemplatePartialSpecializationDecl inheriting from ClassTemplateSpecializationDecl inheriting from CXXRecordDecl ... these do not look to be proper ISA relationships. Why should a partial specialization provide info about the "extern" keyword or the "<>" braces? Why should it have method getSpecializationKind() when all partial specialization are explicit?

Well, "extern" doesn't make sense for explicit specializations or implicit instantiations, either, but I understand your point that the CXXRecordDecl hierarchy could be cleaned up. CXXRecordDecl, for example, should be eliminated, and its C++-specific methods migrated to RecordDecl. ClassTemplateSpecializationDecl could also be collapsed into RecordDecl, so long as we find a place to introduce the FoldingSetNode. There may even been 

As for ClassTemplatePartialSpecializationDecl... it is somewhat odd, because it is neither a class nor a template of its own, but it acts like both. 

	- Doug



More information about the cfe-dev mailing list