Template parameters for out-of-line definitions of class template methods.

Hello.

We have a somewhat naive question regarding the AST generated for the following program fragment:

Hello.

We have a somewhat naive question regarding the AST generated for the
following program fragment:

template <typename T>
struct S {
  void foo();
};

template <class W>
void S<W>::foo() {}

We would like to retrieve the template parameter list for the
out-of-line definition of method foo(), that is
  template <class W>
but we cannot see if and how this could be achieved.

Clang's AST doesn't actually store the template parameter list that was used in the out-of-line definition. It should.

Apparently, clang++ produces a plain CXXMethodDecl, with no explicit
indication that this is actually a "member function template" (C++98
14.5.1.1).

Technically, it's a member function of a class template.

Are we missing some existing clang methods that allow to retrieve this
info or is it really missing? In the latter case, is there any plan to
add this info to the generated AST?

It is missing, and we will add this info to the generated AST at some point.

The same question can be asked for the case of an out-of-line definition
of a static data member (which generates a VarDecl node) and of a member
class (generating a plain CXXRecordDecl).

Right, this is the same kind of issue. We're missing this information for out-of-line definitions of everything.

  - Doug

Douglas Gregor wrote:

Hello.

We have a somewhat naive question regarding the AST generated for the following program fragment:

template <typename T>
struct S {
  void foo();
};

template <class W>
void S<W>::foo() {}

We would like to retrieve the template parameter list for the out-of-line definition of method foo(), that is
  template <class W>
but we cannot see if and how this could be achieved.

Clang's AST doesn't actually store the template parameter list that was used in the out-of-line definition. It should.

Hello.

Reconsidering the point above, we would like to propose a solution.

The template parameter lists we are interested in are simply thrown away after calls to method

   TemplateParameterList*
   Sema::MatchTemplateParametersToScopeSpecifier
     (SourceLocation DeclStartLoc, const CXXScopeSpec &SS,
      TemplateParameterList **ParamLists, unsigned NumParamLists,
      bool IsFriend, bool &IsExplicitSpecialization);

Hence, we simply have to store somewhere the lists of parameters that have been matched against the CXXScopeSpec: either all of the lists in ParamLists, or all but the last one (which would be the one returned as result).

As far as we can see, the best place for this info is in the ExtInfo struct inside DeclaratorDecl, so that the space overhead will be paid only in the uncommon case of an out-of-line declaration:

00369 class DeclaratorDecl : public ValueDecl {
00370 // A struct representing both a TInfo and a syntactic qualifier,
00371 // to be used for the (uncommon) case of out-of-line declarations.
00372 struct ExtInfo {
00373 TypeSourceInfo *TInfo;
00374 NestedNameSpecifier *NNS;
00375 SourceRange NNSRange;
00376 };

A similar chnage will be done for the ExtInfo struct inside TagDecl nodes.

Would this be OK?

Cheers,
Enea Zaffanella.

The attached patch shows better and implement the proposal of Enea for
your review/approval.

MatchedTemplateParamLists.patch (11.3 KB)

Yes, this would be great!

  - Doug

I've alread submitted a patch for your review/approval:

http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-June/009259.html

P.S. Sorry if I have misunderstood this message and you already meant to
approve the patch.

If NNSInfo is going to be used in multiple places, which I think is the intent, please
lift it out of DeclaratorDecl and give it a better name. QualifierInfo, maybe?
OutOfLineInfo?

+ unsigned getNumTemplateParameterLists() const {
+ return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NumTemplParamLists : 0;
+ }

Please use getExtInfo() consistently.

Otherwise looks good!

John.

Commited with suggested changes in r105882.