Bug shown by out-of-line definition of template method.


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


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.

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:


and will address it when I can.

  - Doug