[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