title: Is clang right to reject a template call with a trailing decltype return type depending on one of its overloads?
body: <p>I was surprised to see that clang failed to compile the following c++11 code:</p>
  
  <pre><code>#include &lt;type_traits&gt;
  
  template&lt;class T&gt;
  struct A {};
  
  template&lt;class T&gt;
  struct B : A&lt;T&gt; { T x; };
  
  template&lt;class T&gt;
  const typename std::remove_reference&lt;T&gt;::type&amp; add_const(T&amp;&amp; x) { return x; }
  
  template&lt;class T&gt;
  T&amp; cast_away_const(const T&amp; x) { return const_cast&lt;T&amp;&gt;(x); }
  
  template&lt;class T&gt;
  const B&lt;T&gt;&amp; downcast(const A&lt;T&gt;&amp; x) { return static_cast&lt;const B&lt;T&gt;&amp;&gt;(x); }
  
  template&lt;class T&gt;
  auto downcast(A&lt;T&gt;&amp; a) -&gt;
  decltype(cast_away_const(downcast(add_const(a)))) {
      return cast_away_const(downcast(add_const(a)));
  }
  
  int main() {
      B&lt;int&gt; b;
      b.x = 42;
      A&lt;int&gt;&amp; a = b;
      B&lt;int&gt;&amp; b_again = downcast(a);
      return b_again.x;
  }
  </code></pre>
  
  <p>To be more accurate, clang 3.7.1 complains about a long template instantiation chain, behaving as if the instantiation of <code>auto downcast(A&lt;T&gt;&amp; a) -&gt; /*...*/</code> with <code>T=int</code> required the instantiation of itself.
  clang 5.0.0 or 6.0.0 merely crashes (!).
  Both gcc and msvc accept.</p>
  
  <p><a href="https://godbolt.org/g/f1obMv" rel="nofollow noreferrer">godbolt link</a></p>
  
  <p>Now, clang-5.0.0 crashing is obviously a bug, but clang-3.7.1 error made some sense so…
  <strong>Is that code legal in the first place?</strong></p>
  
  <p>Let me emphasize I'm asking for whether this code is legal, not for a workaround (an easy workaround would be to split <code>overload</code> in <code>overload</code> and <code>overload_const</code>, have the later handle only const references and have the former call the later).</p>
  
  <p>I could find the following somewhat related point of contention between clang and gcc <a href="https://stackoverflow.com/questions/3744400/trailing-return-type-using-decltype-with-a-variadic-template-function">(trailing return type using decltype with a variadic template function, SO link)</a> alongside with this similar question whose answer cites the standard <a href="https://stackoverflow.com/questions/26274207/gcc-can-compile-a-variadic-template-while-clang-cannot?noredirect=1&amp;lq=1">(gcc can compile a variadic template while clang cannot)</a>
  I'm however not sure the exact same argument applies here (as <code>downcast</code> should refer to a previously declared overload and not itself in the trailing return type).</p>