[cfe-dev] On template instantiations and specializations.

Enea Zaffanella zaffanella at cs.unipr.it
Tue Jun 15 00:35:32 PDT 2010


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?

To my eyes, a design based on containment rather than inheritance would 
probably be a little bit cleaner. Unless there are other reasons to 
prefer inheritance ...

Cheers,
Enea.




More information about the cfe-dev mailing list