[cfe-dev] Bug shown by out-of-line definition of template method.

Enea Zaffanella zaffanella at cs.unipr.it
Tue Feb 9 08:16:20 PST 2010


The following C++ code triggers a bug in clang:

template <typename T>
struct Outer {
   template <typename U>
   struct Inner {};

   template <typename U>
   typename Outer<T>::template Inner<U>
   foo(typename Outer<T>::template Inner<U>);

template <typename T>
template <typename U>
typename Outer<T>::template Inner<U>
Outer<T>::foo(typename Outer<T>::template Inner<U>) {
   return Inner<U>();

# llvm/Debug/bin/clang++ -fsyntax-only bug.cc
bug.cc:14:11: error: out-of-line definition of 'foo' does not match any
       declaration in 'struct Outer'
Outer<T>::foo(typename Outer<T>::template Inner<U>) {
1 diagnostic generated.

I tried to trace it to its origin: the wrong error message is generated 
in a call to method

   bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old);

namely, in the very last of the following tests:

   if (NewTemplate &&
                                  false, TPL_TemplateMatch) ||
       OldType->getResultType() != NewType->getResultType()))
     return true;

The result types of the out-of-line method definition type (NewType) and 
the method declaration type (OldType) do not match:

declaration result type: TemplateSpecializationType

definition  result type: TypenameType
typename Outer<type-parameter-0-0>::Inner<type-parameter-1-0>

In contrast, parameter types do match, as they are both normalized to 

This instance of the bug will disappear if the result type of the method 
definition is normalized before comparision ... but honestly I am not 
sure at all regarding how to perform such a normalization (is it enough 
to query TemplateType::getTemplateId() ?) and whether or not this is the 
right place to do it.

Anyway, I hope that the observations above are useful for clang experts.

Enea Zaffanella.

More information about the cfe-dev mailing list