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

Douglas Gregor dgregor at apple.com
Tue Feb 9 20:36:46 PST 2010


On Feb 9, 2010, at 8:16 AM, Enea Zaffanella wrote:

> Hello.
> 
> 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 &&
> (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
>                                  OldTemplate->getTemplateParameters(),
>                                  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
> Inner<type-parameter-1-0>
> 
> 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 
> Inner<type-parameter-1-0>.
> 
> 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.

Sema::RebuildTypeInCurrentInstantiation is supposed to perform this normalization, because we can't actually get the types right until we know that we're in the scope of Outer<T> (which happens after we've parsed the return type). Since this is probably a bug in that normalization, it's best if I address it, because it requires fairly deep knowledge of the type and template systems to get right.

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


Very useful, thank you! I've filed this bug here:

	http://llvm.org/bugs/show_bug.cgi?id=6268

and will address it when I can.

	- Doug



More information about the cfe-dev mailing list