[cfe-dev] A question related to bug 5866.

Enea Zaffanella zaffanella at cs.unipr.it
Thu May 27 15:44:46 PDT 2010


John McCall wrote:
> On May 26, 2010, at 4:44 AM, Enea Zaffanella wrote:
> 
>> Hello.
>>
>> I was struggling against friend declarations of template function 
>> specializations, i.e., something strongly related to the following 
>> (resolved) bug:
>>
>>   http://llvm.org/bugs/show_bug.cgi?id=5866
>>
>> The problem we have is the following: when visiting a friend declaration 
>> such as the one used in the bug report above
>>
>>     friend streamsize
>>     __copy_streambufs_eof<>(__streambuf_type*,
>>                             __streambuf_type*, bool&);
>>
>> we call method getFriendDecl() and obtain a FunctionDecl*,
>> but when querying this pointer using method
>>     bool FunctionDecl::isFunctionTemplateSpecialization()
>> the answer turns out to be negative.
>>
>> Is this a bug, or are we just calling the method above out of its 
>> specification? Are there other ways to check if a friend declaration is 
>> referring to a template function specialization?
> 
> It sounds like a bug.
> 
> John.

OK, I managed to obtain more info and better understand the issue.
Strictly speaking, it looks like the one above is not a real bug ...

The example is as follows:
=========
template <typename T> void foo(T);

template <typename T>
class C {
   friend void foo<>(T);
};
=========

Here the FriendDecl is declaring a
    "dependent function template specialization".

If I understand the ratio from clang documentation, since these are 
dependent, they are not actual function template 
specializations/instances, hence method
    FunctionDecl::isFunctionTemplateSpecialization()
is allowed to return false and method
    FunctionDecl::getTemplateSpecializationKind()
returns TSK_Undeclared.

The info I was looking for, i.e., the (empty) list of template 
arguments, can be found by using method:
   DependentFunctionTemplateSpecializationInfo*
      getDependentSpecializationInfo()


As a side note ... we observed that there are several slightly different 
ways of iterating on collections of TemplateArg and TemplateArgLoc 
objects ... and the methods to retrieve these collections have slightly 
different names, sometimes they return pointers, sometimes they return 
references, etc. For instance:

In DependentFunctionTemplateSpecializationInfo we have:
   unsigned getNumTemplateArgs() const;
   const TemplateArgumentLoc& getTemplateArg(unsigned I) const;

In FunctionTemplateSpecializationInfo we have:
   const TemplateArgumentList* TemplateArguments;
   const TemplateArgumentListInfo* TemplateArgumentsAsWritten;

In ClassTemplateSpecializationDecl we have:
   const TemplateArgumentList& getTemplateArgs() const

In ClassTemplatePartialSpecializationDecl we also have:
   TemplateArgumentLoc* getTemplateArgsAsWritten() const;
   unsigned getNumTemplateArgsAsWritten() const;

TemplateArgumentList has methods
   unsigned size() const;
   const TemplateArgument& operator[](unsigned Idx) const;
   const TemplateArgument& get(unsigned Idx) const;

while TemplateArgumentListInfo has methods:
   unsigned size() const;
   const TemplateArgumentLoc& operator[](unsigned I) const;
   const TemplateArgumentLoc* getArgumentArray() const;

It would be nicer if a more uniform naming scheme and a common iteration 
pattern were available.

Cheers,
Enea.



More information about the cfe-dev mailing list