Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::declval() firing assertion error with warnings in GCC

Tags:

c++

gcc

c++11

Consider this snippet:

#include <utility>

template <typename U>
auto foo() -> decltype(std::declval<U>() + std::declval<U>());

template <typename T>
decltype(foo<T>()) bar(T)
{}

int main()
{
    bar(1);
    return 0;
}

This fires a warning and 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 -Wall -Wextra. For instance, this is the output of 4.8.1:

main.cpp: In instantiation of ‘decltype (foo<T>()) bar(T) [with T = int; decltype (foo<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< <template-parameter-1-1> >::type std::declval() [with _Tp = int; typename std::add_rvalue_reference< <template-parameter-1-1> >::type = int&&]’:
main.cpp:8:2:   required from ‘decltype (foo<T>()) bar(T) [with T = int; decltype (foo<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,

If one either disables the warnings or supplies bar with a return statement, e.g.,

template <typename T>
decltype(foo<T>()) bar(T a)
{
    return a + a;
}

the assertion failure disappears. Clang++ 3.3 does not fire assertion errors in any case. Is this standard-conforming behaviour from GCC?

like image 654
bluescarni Avatar asked Jul 08 '13 22:07

bluescarni


1 Answers

My copy of GCC 4.9 built in early June compiles it without complaint as long as I add return {}; or throw; inside the function. With no return, it does fire that static assertion. This is certainly a bug, but only a minor one, since the function only "crashes" upon execution.

I have seen that error when trying to execute declval() in a constant expression, so something like that may be happening in your case. The "cannot be used" is presumably referring to ODR-use or using the result.

Perhaps in the absence of any statement it tried to manufacture one with the content of the decltype. Adding even a simple statement like 0; silences the spurious error. (But static_assert( true, "" ) or even void(0) are insufficient.)

Filed a GCC bug.

like image 125
Potatoswatter Avatar answered Oct 28 '22 00:10

Potatoswatter