title: std::declval() firing assertion error with warnings in GCC
body: <p>Consider this snippet:</p>
  
  <pre><code>#include &lt;utility&gt;
  
  template &lt;typename U&gt;
  auto foo() -&gt; decltype(std::declval&lt;U&gt;() + std::declval&lt;U&gt;());
  
  template &lt;typename T&gt;
  decltype(foo&lt;T&gt;()) bar(T)
  {}
  
  int main()
  {
      bar(1);
      return 0;
  }
  </code></pre>
  
  <p>This fires a warning <em>and</em> a static assertion failure in all versions of GCC I tried it on (4.7.3, 4.8.1, 4.9-some-git) when compiled with <code>-Wall -Wextra</code>. For instance, this is the output of 4.8.1:</p>
  
  <pre>
  main.cpp: In instantiation of ‘decltype (foo&lt;T>()) bar(T) [with T = int; decltype (foo&lt;T>()) = int]’:
  main.cpp:12:7:   required from here
  main.cpp:8:2: warning: no return statement in function returning non-void [-Wreturn-type]
   {}
    ^
  In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/move.h:57:0,
                   from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/stl_pair.h:59,
                   from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/utility:70,
                   from main.cpp:1:
  /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/type_traits: In instantiation of ‘typename std::add_rvalue_reference&lt; &lt;template-parameter-1-1> >::type std::declval() [with _Tp = int; typename std::add_rvalue_reference&lt; &lt;template-parameter-1-1> >::type = int&&]’:
  main.cpp:8:2:   required from ‘decltype (foo&lt;T>()) bar(T) [with T = int; decltype (foo&lt;T>()) = int]’
  main.cpp:12:7:   required from here
  /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/type_traits:1871:7: error: static assertion failed: declval() must not be used!
         static_assert(__declval_protector::__stop,
  </pre>
  
  <p>If one either disables the warnings <em>or</em> supplies <code>bar</code> with a return statement, e.g.,</p>
  
  <pre><code>template &lt;typename T&gt;
  decltype(foo&lt;T&gt;()) bar(T a)
  {
      return a + a;
  }
  </code></pre>
  
  <p>the assertion failure disappears. Clang++ 3.3 does not fire assertion errors in any case. Is this standard-conforming behaviour from GCC?</p>