Templates (again)

I found that I’m going to have a little free time since my university is basically shutting down for the holidays, so I thought I’d spend some time revisiting my previous templates work. I’m just not entirely sure where to start. I started looking at building an AST node for template template parameters (for parity with type and non-type params) and realized that I probably have to define a TemplateDecl AST node as a base class that can also serve as a utility or node for template definitions.

Does this sound way off base? I think it’s probably the right direction, but wanted to check before I proceed.

I’m pulling all of my changes through mercurial so I can publish the diffs a little easier. It’s based on Dan’s tree on BitBucket. My local copy is here:

http://warhol.sdml.cs.kent.edu/~asutton/clang/

If you clone this, the changes aren’t merged so you’ll need to “hg merge asutton/template-2” before the patches are applied to your local copy.

Andrew Sutton
andrew.n.sutton@gmail.com

I’m pulling all of my changes through mercurial so I can publish the diffs a little easier. It’s based on Dan’s tree on BitBucket. My local copy is here:

http://warhol.sdml.cs.kent.edu/~asutton/clang/

For the record, I’m the Dan in question :wink:

I took the liberty of pushing the changes to BitBucket; they can be viewed here:
<http://www.bitbucket.org/danchr/clang/changeset/84b7ff0b249a/>
<http://www.bitbucket.org/asutton/>

If you clone this, the changes aren’t merged so you’ll need to “hg merge asutton/template-2” before the patches are applied to your local copy.

Doing a ‘hg update -r asutton/template-2’ should do the trick as well.

Hi Andy,

I found that I'm going to have a little free time since my university is basically shutting down for the holidays, so I thought I'd spend some time revisiting my previous templates work. I'm just not entirely sure where to start. I started looking at building an AST node for template template parameters (for parity with type and non-type params) and realized that I probably have to define a TemplateDecl AST node as a base class that can also serve as a utility or node for template definitions.

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.

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. The underlying declaration of a class template is a RecordDecl, the underlying declaration of a template alias would be some kind of alias-declaration or typedef, and the underlying declaration of a template template parameter might also be a RecordDecl (?).

In any case, starting with the representation of template template parameters is a good idea, IMHO, because introducing TemplateDecls for function and class templates is going to require quite a lot of logic in, e.g., declaration matching and overloading. Much better to get the TemplateDecl pieces in place *first*.

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.

+ 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.

Additionally, you'll want to add

  static bool classof(const TemplateTemplateParmDecl *) { return true; }

(and similarly for other template declarations, as we add them).

In Decl::getIdentifierNamespace(), I suggest that all TemplateDecls return IDNS_Ordinary | IDNS_Tag, since template names need to be unique in their scope.

I actually have a partial patch (that includes a TemplateDecl that's surprisingly similar to yours <g>) which starts to deal with some of the AST nodes and parser state for template parameter lists. It might answer the question you have in the ActOnTemplateTemplateParameter FIXME about the "signature" of the template template parameter. I'll try to commit the non-TemplateDecl parts of that tonight, so you don't have to re-invent it (and we don't conflict).

+TemplateDecl *TemplateDecl::Create(ASTContext &C, Kind DK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id) {
+ void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>();
I suspect that TemplateDecl and TranslationUnitDecl won't always be the same size :slight_smile:

In Sema::ActOnTemplateTemplateParameter, you can go ahead and S- >AddDecl(Param) the parameter you create.

You should update Sema::isTemplateName to return "true" when it sees a TemplateDecl (or any of its subclasses). It won't actually work yet, but that'll enable template-ids whose template-name is a template template parameter.

  - Doug

[CC’ing cfe-dev]

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 :slight_smile:

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 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 :slight_smile:

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

Please CC cfe-dev on these discussions. (Reply All)

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 think my way is simpler :slight_smile:

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.).

To summarize, we’re talking about something like this:

class TemplateDecl : ScopedDecl // (?)
{
ScopedDecl* decl;
// One of FunctionDecl, ClassDecl, etc.
// but not one of *TemplateDecl?
};

class ClassTemplateDecl : TemplateDecl { };
class FunctionTemplateDecl : TemplateDecl { };
// template alias, template template parameter, etc.

And we’d generally be creating derived decl nodes during parsing. Is that about right?

Yes.

This makes me wonder what the AST would look like for something like this:

template
struct S
{
template void f(U u);
};

template
template
void S::f(U u)
{ }

It looks like we’d have to a) defer the creation of the ClassTemplateDecl until we see S or b) I’m misintepreting what you’re saying and we’d create a TemplateDecl for each template<…>, and then create a ClassTemplateDecl when we S and have it reference the outer-most TemplateDecl.

So, walking through this: when we get the ActOnTag callback, we create the TemplateDecl and RecordDecl for class template ‘S’ (basically, when we see the ‘{’ after the ‘S’).

When we get the ActOnDeclarator callback for ‘f’, we build the FunctionDecl and TemplateDecl for that member template.

For the out-of-line member definition, we’ll get an ActOnDeclarator call with a declarator ‘f’ in scope S. We’ll then create a TemplateDecl+FunctionDecl for that out-of-line definition.

This is in the tree now. Basically, we keep track of the template parameter lists that we've parsed and then provide those to the various Action routines that will end up constructing templates, e.g., ActOnTag for creating class templates (but not enum templates <g>).

The Depth/Position stuff is working toward a fix in the type system. Basically, template parameters in the type system will be identified by their kind, depth (= the number of enclosing template parameter lists), and position with in that template parameter list. For example, 'T' in

  template<typename T> void foo(T);

is a template type parameter with depth=0 and position=0. That's the canonical type for 'T', and we'll use some sugar to give it the name 'T'. That way, we can quickly match the declaration above with the definition below

  template<class U> void foo(U) { }

  - Doug

The Depth/Position stuff is working toward a fix in the type system. Basically, template parameters in the type system will be identified by their kind, depth (= the number of enclosing template parameter lists), and position with in that template parameter list. For example, ‘T’ in

template void foo(T);

is a template type parameter with depth=0 and position=0. That’s the canonical type for ‘T’, and we’ll use some sugar to give it the name ‘T’. That way, we can quickly match the declaration above with the definition below

template void foo(U) { }

This corresponds to the GCC errors with phrases like “template parameter-1-1”, right?

Andrew Sutton
andrew.n.sutton@gmail.com

This is in the tree now. Basically, we keep track of the template parameter lists that we’ve parsed and then provide those to the various Action routines that will end up constructing templates, e.g., ActOnTag for creating class templates (but not enum templates ).

The Depth/Position stuff is working toward a fix in the type system. Basically, template parameters in the type system will be identified by their kind, depth (= the number of enclosing template parameter lists), and position with in that template parameter list. For example, ‘T’ in

template void foo(T);

is a template type parameter with depth=0 and position=0. That’s the canonical type for ‘T’, and we’ll use some sugar to give it the name ‘T’. That way, we can quickly match the declaration above with the definition below

template void foo(U) { }

  • Doug

I just merged my patches onto yours and started stubbing out some declaration classes. I also broke the template node declarations out into DeclTemplates.h/cpp so I could navigate around a little easier. It’s included at the bottom of DeclCXX for now. The new code doesn’t really do anything yet.

Also, I’m not entirely sure how to use TemplateParameterList. It’s not quite like any “list/array/vector” structure that I’ve run across. I’m guessing that I’d have TemplateDecl contain a ptr to it, since the list is likely created and populated during parsing.

I merged the changes into Dan (Christiansen’s) Mercurial mirror on BitBucket, here:

http://bitbucket.org/danchr/clang/

It’s just a start, an offering for comments. More code to follow, but probably not today or tomorrow.

Andrew Sutton
andrew.n.sutton@gmail.com

Yes, we're using the same encoding that GCC does, and the "names" of the canonical types for template parameters will end up being something like "type param 1-1" or "non-type param 0-1". Of course, we'll use a sugared type to keep the appropriate names around in each of the templates.

  - Doug

This is in the tree now. Basically, we keep track of the template parameter lists that we’ve parsed and then provide those to the various Action routines that will end up constructing templates, e.g., ActOnTag for creating class templates (but not enum templates ).

The Depth/Position stuff is working toward a fix in the type system. Basically, template parameters in the type system will be identified by their kind, depth (= the number of enclosing template parameter lists), and position with in that template parameter list. For example, ‘T’ in

template void foo(T);

is a template type parameter with depth=0 and position=0. That’s the canonical type for ‘T’, and we’ll use some sugar to give it the name ‘T’. That way, we can quickly match the declaration above with the definition below

template void foo(U) { }

  • Doug

I just merged my patches onto yours and started stubbing out some declaration classes. I also broke the template node declarations out into DeclTemplates.h/cpp so I could navigate around a little easier. It’s included at the bottom of DeclCXX for now. The new code doesn’t really do anything yet.

Splitting the code out into DeclTemplate.h/.cpp makes a lot of sense. For the most part, clients of a completed AST won’t need to deal with the AST nodes in DeclTemplate.h.

Also, I’m not entirely sure how to use TemplateParameterList. It’s not quite like any “list/array/vector” structure that I’ve run across. I’m guessing that I’d have TemplateDecl contain a ptr to it, since the list is likely created and populated during parsing.

Right. ActOnTemplateParameterList creates them, and they’ll go into ActOnTag, ActOnDeclarator, etc., where they’ll get hooked into a TemplateDecl.

I merged the changes into Dan (Christiansen’s) Mercurial mirror on BitBucket, here:

http://bitbucket.org/danchr/clang/

It’s just a start, an offering for comments. More code to follow, but probably not today or tomorrow.

Aside from the move to DeclTemplate.h/.cpp, I’m having a hard time determining what else has changed here. Is there something specific I can look at?

  • Doug

Aside from the move to DeclTemplate.h/.cpp, I’m having a hard time determining what else has changed here. Is there something specific I can look at?

I think I’ve gotten AST construction for template template parameters mostly done in that the parser now builds decl nodes that include their template parameter lists. Default values aren’t plugged into that just yet. I think I did the right thing with the layering/casting of TemplateParameterLists through the Action interface by re-casting it as a TemplateParamsTy*.

I’m also not entirely sure how to go about verifying that this does what I think it does. I can probably make -ast-print dump template information. That would probably help.

Changes are pushed here https://www.bitbucket.org/danchr/clang/. The branch name is still asutton/templates-3 although this also seems to also be tagged “tip” (which it probably shouldn’t be).

Andrew Sutton
andrew.n.sutton@gmail.com

Aside from the move to DeclTemplate.h/.cpp, I'm having a hard time determining what else has changed here. Is there something specific I can look at?

I think I've gotten AST construction for template template parameters mostly done in that the parser now builds decl nodes that include their template parameter lists. Default values aren't plugged into that just yet. I think I did the right thing with the layering/casting of TemplateParameterLists through the Action interface by re-casting it as a TemplateParamsTy*.

I have some comments below.

I'm also not entirely sure how to go about verifying that this does what I think it does. I can probably make -ast-print dump template information. That would probably help.

-ast-print might be the only way you can do this now, since we don't yet have the ability to turn a template-id into a type.

Changes are pushed here https://www.bitbucket.org/danchr/clang/. The branch name is still asutton/templates-3 although this also seems to also be tagged "tip" (which it probably shouldn't be).

I browsed through a few of these. I'm not a Mercurial user, so when you think part of this is ready to go into the main tree I'll need a traditional patch.

In isTemplateName:

   // FIXME: Do we need to look up Ordinary | Tag since templates seem to
   // exist in both namespaces?
Just IDNS_Ordinary is fine. We ask LookupDecl which namespace to look in, and some entities can be found in multiple namespaces.
Deprecating the FunctionDecl/isDependentType hack below this code probably breaks some of the regression tests. I'd suggest leaving it as-is for now.
In TemplateDecl:

  static bool classof(const Decl *D)
   { return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast; }
   static bool classof(const TemplateDecl *D)
   { return true; }
You'll want to add

   static bool classof(const FunctionTemplateDecl *) { return true; }

and so on for the other TemplateDecl subclasses.

- FunctionDecl* getTemplatedFunction() const {
+ FunctionDecl *getFunctionDecl() const {
     return static_cast<FunctionDecl*>(TemplatedDecl);
   }

I think it'd be best for these functions to keep the same name "getTemplatedDecl" as in TemplateDecl. When we're in one of its subclasses, we get more a more-specific type.

The handling of TemplateParmsTy* in ActOnTemplateTemplateParameter looks fine to me.

  - Doug

I browsed through a few of these. I’m not a Mercurial user, so when you think part of this is ready to go into the main tree I’ll need a traditional patch.

Building a patch against svn shouldn’t be too much trouble. I’m going try to finish off the template-template param basics with ast-print support (hopefully) without introducing any regressions before submitting.

You’ll want to add

static bool classof(const FunctionTemplateDecl *) { return true; }

To TemplateDecl? Wouldn’t that be handled by the TemplateFirst/TemplateLast range? It’s already in FunctionTemplateDecl.

Andrew Sutton
andrew.n.sutton@gmail.com

I browsed through a few of these. I'm not a Mercurial user, so when you think part of this is ready to go into the main tree I'll need a traditional patch.

Building a patch against svn shouldn't be too much trouble. I'm going try to finish off the template-template param basics with ast-print support (hopefully) without introducing any regressions before submitting.

Okay.

You'll want to add

static bool classof(const FunctionTemplateDecl *) { return true; }

To TemplateDecl? Wouldn't that be handled by the TemplateFirst/TemplateLast range? It's already in FunctionTemplateDecl.

Yes, to TemplateDecl, for efficiency. If the static type is known to be a FunctionTemplateDecl, we skip the run-time computation that compares its Kind against TemplateFirst/TemplateLast.

  - Doug

Building a patch against svn shouldn’t be too much trouble. I’m going try to finish off the template-template param basics with ast-print support (hopefully) without introducing any regressions before submitting.

Okay.

It turns out to be impossible to ast-print template template parameters without handling template declarations. This seems so obvious in retrospect… So I’m working on AST building for class templates. It’s kind of working, but I can’t seem to get the DeclPrinter to see top-level template declarations. Probably some kind of weird name conflict because I’m forcing the TemplateDecl to take the same name as its underlying ScopedDecl.

Quick question though. You started building support for depth/position stuff for template parameters, but the values aren’t handled in Sema. Are you envisioning the depth/position as properties of template parameters or will they be dealt with elsewhere?

Andrew Sutton
andrew.n.sutton@gmail.com

Here’s my incremental patch for template support to date as diff’d against svn. Here’s what I’ve done:

  • Moved all template-related decls into new files DeclTemplate.h and DeclTemplate.cpp
  • Stubbed out the basic TemplateDecl hierarchy with derivatives ClassTemplateDecl, and FunctionTemplateDecl and integrated this into the isa/dyncast system (also added names to the getDeclKindName)
  • Modified the TemplateParameter classes to include Depth/Position info as properties, and stubbed out serialization support for all of them.
  • Improved Sema support for building template template parameters.
  • Create ClassTemplateDecls in ActOnTag when there are template parameters
  • Blocked out support for printing template information in DeclPrinter

I never actually got -ast-print to print top-level template declarations. For some reason, top-level template declarations seem to a) evaporate from the list of top-level declarations or b) aren’t actually being added to that list.

There’s also an interesting case in ActOnTag when a previous declaration happens to be a class template. My solution is to simply make PrevDecl reference the TemplatedDecl and temporarily punt on determining if a) the previous is a forward declaration, or if the current tag is a full or partial specialization. That logic probably needs to show up when we’re creating the AST nodes.

There are almost certainly some memory leaks and issues with ownership.

Andrew Sutton
andrew.n.sutton@gmail.com

templates.patch (52.7 KB)

Building a patch against svn shouldn't be too much trouble. I'm going try to finish off the template-template param basics with ast-print support (hopefully) without introducing any regressions before submitting.

Okay.

It turns out to be impossible to ast-print template template parameters without handling template declarations. This seems so obvious in retrospect... So I'm working on AST building for class templates. It's kind of working, but I can't seem to get the DeclPrinter to see top-level template declarations. Probably some kind of weird name conflict because I'm forcing the TemplateDecl to take the same name as its underlying ScopedDecl.

Is the TemplateDecl getting returned all the way through to ParseExternalDeclaration? That's how declarations get back to the

Quick question though. You started building support for depth/position stuff for template parameters, but the values aren't handled in Sema. Are you envisioning the depth/position as properties of template parameters or will they be dealt with elsewhere?

For template type parameters, the depth and position will become a part of the Type. For non-type and template template parameters, they'll probably be a part of the Decl. However, templates might need to be "types" in the type system, in which case template template parameters would probably have a specific kind of type; I haven't thought about this part much, yet.

  - Doug

Is the TemplateDecl getting returned all the way through to ParseExternalDeclaration? That’s how declarations get back to the

Knowing that helps a lot. Here’s iteration n + 1. This starts to add -ast-print support for class templates, but it doesn’t print template parameters just yet. You’ll get “template <…> Read top-level tag…”.

Getting this to work is… not very pretty. It’s actually pretty tough to push the TemplateDecl all the way up to ParseExternalDeclaration since, somewhere in the call sequence, the created declaration node is wrapped in a DeclSpec (in ParseDeclarationOrFunctionDefinition IIRC) and ActOnTag only returns a TagDecl. I modified ActOnTag to return either a TagDecl or a TemplateDecl. This has the unfortunate side-effect of requiring you to think about DeclTy’s in the Action interface as either a Tag or Template. It’s easy to get the Tag from the Template, but unfortuntely you still have to perform the cast (so far only in 3 places). This also means that I’m setting the TypeRep of a DeclSpec as a TemplateDecl, which may or may not have unseen consequences down the road.

It’s a big patch, but I tried to make it as unintrusive as possible. Best of all, it doesn’t cause any regressions on my system.

Andrew Sutton
andrew.n.sutton@gmail.com

templates.patch (60 KB)

Hi Andy,

Is the TemplateDecl getting returned all the way through to ParseExternalDeclaration? That’s how declarations get back to the

Knowing that helps a lot. Here’s iteration n + 1. This starts to add -ast-print support for class templates, but it doesn’t print template parameters just yet. You’ll get “template <…> Read top-level tag…”.

Sorry for the long delay… it’s about time for us to get rolling on templates, eh?

Getting this to work is… not very pretty. It’s actually pretty tough to push the TemplateDecl all the way up to ParseExternalDeclaration since, somewhere in the call sequence, the created declaration node is wrapped in a DeclSpec (in ParseDeclarationOrFunctionDefinition IIRC) and ActOnTag only returns a TagDecl. I modified ActOnTag to return either a TagDecl or a TemplateDecl. This has the unfortunate side-effect of requiring you to think about DeclTy’s in the Action interface as either a Tag or Template. It’s easy to get the Tag from the Template, but unfortuntely you still have to perform the cast (so far only in 3 places). This also means that I’m setting the TypeRep of a DeclSpec as a TemplateDecl, which may or may not have unseen consequences down the road.

Hrm. I’m not thrilled with this, especially since it’s only really there to make the TemplateDecl get up to ParseExternalDeclaration. I left off this part of the patch, which we can revisit later when we need it. DeclSpecs shouldn’t refer to templates at all, and the DeclSpec itself won’t even be used for anything.

It’s a big patch, but I tried to make it as unintrusive as possible. Best of all, it doesn’t cause any regressions on my system.

… and, after resolving all of the conflicts from a month of development, no regressions on my system, either. Yay!

I’ve committed this patch, here:

http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20090202/011754.html

Thanks!

  • Doug

Sorry for the long delay… it’s about time for us to get rolling on templates, eh?

No problem… I’ve had lots to keep my busy in the meantime :slight_smile: I’m not enturely sure what to work on from here. I’ve been thinking about revisit the parsing and look at improving ICE parsing for default non-type parameters and the ‘>>’ problem.

I modified ActOnTag to return either a TagDecl or a TemplateDecl.

Hrm. I’m not thrilled with this, especially since it’s only really there to make the TemplateDecl get up to ParseExternalDeclaration. I left off this part of the patch, which we can revisit later when we need it. DeclSpecs shouldn’t refer to templates at all, and the DeclSpec itself won’t even be used for anything.

I wasn’t entirely thrilled with the solution either.

… and, after resolving all of the conflicts from a month of development, no regressions on my system, either. Yay!

I’ve committed this patch, here:

http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20090202/011754.html

I’m going to have to spend a weekend relearning the code base - I haven’t looked at it since I submitted that last patch. It’s too bad I don’t have another Christmas break coming up soon.

On a side note, I am now a big fan of variadic templates.

Andrew Sutton
andrew.n.sutton@gmail.com