[cfe-dev] Templates (again)

Douglas Gregor dgregor at apple.com
Tue Dec 23 13:18:18 PST 2008


[CC'ing cfe-dev]

On Dec 23, 2008, at 3:51 PM, Andrew Sutton wrote:

> Yes, I agree with this. I think we'll need a TemplateDecl AST node  
> to represent any kind of template. TemplateDecl will store the  
> template parameters themselves, and the various kinds of templates  
> (class template, function template, template alias, or template- 
> template parameter) will probably have corresponding subclasses  
> (ClassTemplateDecl, FunctionTemplateDecl, TemplateAliasDecl,  
> TemplateTemplateParmDecl) with whatever members are appropriate for  
> that kind of template. Class templates will have instantiations,  
> specializations, and partial specializations; function templates  
> will just have instantiations and specializations, etc.
>
> Don't forget about concept_maps :)

Eh? What's that?

> I was thinking along these lines, but hoping to avoid the explosion  
> of template-derived subclasses. After giving it some thought, the  
> alternatives are probably less attractive.

I think there are only 4 template-derived subclasses (5, when concept  
maps come along). The trick is that FunctionTemplate covers all of the  
various subclasses of FunctionDecl under a single TemplateDecl subclass.

>
> I suggest that the TemplateDecl not be a DeclContext. Rather, it  
> should have a ScopedDecl member for the "underlying declaration" of  
> the template, which is essentially the AST node that was parsed for  
> the template itself. For example, given
>
>        template<typename T> void foo(T);
>
> "foo" would be represented by a TemplateDecl or subclass, and its  
> underlying declaration would be a FunctionDecl.
>
> So a FunctionTemplateDecl holding and FunctionDecl in this case?

Yes. TemplateDecl will probably have a ScopedDecl* for its underlying  
declaration; FunctionTemplateDecl can just cast this to a FunctionDecl*.

> From a parsing perspective, I suppose that means we have to defer  
> the creation of of the TemplateDecl-derived node until we know what  
> the underlying declaration is.

Yes. I suspect that the template parameters will be passed directly to  
ActOnDeclarator, so it can do the work of building the template  
declaration.

>
> It might be easier to simply have a general TemplateDecl node that  
> then holds the TemplateFunctionDecl. The contained node would be  
> part function, part template-decl "glue", and know about its  
> specializations (and partials for classes) and instances.

I think my way is simpler :)

We have the TemplateDecl, which has a ScopedDecl of some sort. Clients  
that deal with templates abstractly can use TemplateDecl. Then, there  
are subclasses of TemplateDecl that put more requirements on that  
underlying declaration and add extra fields (specializations,  
instantiations, partial specializations, etc.).

> Thanks for working on this. I have a few specific comments about  
> your current changeset:
>
> +  static TemplateDecl *Create(ASTContext &C, Kind DK, DeclContext  
> *DC,
> +                              SourceLocation L, IdentifierInfo *Id);
> Please use DeclarationName instead of IdentifierInfo *.  
> DeclarationName supports constructors\ names, overloaded operator  
> names, and other special names that IdentifierInfo* does not.
>
> Should I update the other template nodes to use these? My svn  
> version doesn't seem to use them.

Those template nodes that can have these special names (or have  
subclasses that can have these special names) should use  
DeclarationName. FunctionTemplateDecl is probably the only subclass  
that will need DeclarationName, depending on how we deal with the  
names of specializations and partial specializations.

>
> + static bool classof(const Decl *D) {
> + return D->getKind() == Template;
> + }
> You also need to check for D->getKind() == TemplateTemplateParm.  
> Actually, I suggest that you add aliases TemplateFirst and  
> TemplateLast to the enumeration, since we'll eventually have several  
> kinds of templates.
>
> This is the node-kind "hierarchy"? I think I see how this works.

Yes.

>
> Additionally, you'll want to add
>
>        static bool classof(const TemplateTemplateParmDecl *)  
> { return true; }
>
> (and similarly for other template declarations, as we add them).
>
> I thought I had that... maybe not.

You want it both in TemplateDecl and in TemplateTemplateParmDecl. That  
way, if some code asks "is a TemplateTemplateParmDecl a TemplateDecl?"  
we have an immediate answer rather than looking into the declaration  
kind.

>
>
> In Decl::getIdentifierNamespace(), I suggest that all TemplateDecls  
> return IDNS_Ordinary | IDNS_Tag, since template names need to be  
> unique in their scope.
>
> Sounds good to me. I really don't understand the meaning of these  
> tags - or at least how it plays into the parsing/name resolution.

Within a single scope, you can have both an ordinary name and a tag  
name. For example, this is well-formed

	class A;
	int A;

This works because the class 'A' is in the "tag" identifier namespace  
while the int 'A' is in the ordinary namespace. In C++, ordinary name  
lookup actually searches both identifier namespaces, but prefers the  
ordinary name. Thus, 'A' refers to the integer (even if it is declared  
before the class). The terminology really comes from C, but it's used  
in C++ as well.

C++-specific entities like templates and namespaces basically live in  
both namespaces, because you can't declare, e.g., a namespace and a  
type, with the same name in the same scope.

	- Doug
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20081223/a03d17ba/attachment.html>


More information about the cfe-dev mailing list