3

Answer 1 of the post How to declare array with auto works fine:

template<typename T> using unsized_raw_array = T[];
auto &&z = unsized_raw_array<int>{1, 2, 3};

Trying out the same but without the double ampersand (&&) results in different behavior of clang and gcc:

template<typename T> using unsized_raw_array = T[];
auto   z = unsized_raw_array<int>{1, 2, 3};

I expected this to be an error because it is an rvalue (universal/forwarding/temporary-object) reference and the double ampersand is missing (&&). And that is what happens with gcc 6.3.0:

  • error: taking address of temporary array

However, clang 3.9.1 compiles and executes it successfully, allowing printing the values of the array in the next statements. I only get this warning (in some scenarios I don't even get the warning):

  • warning: pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression [-Waddress-of-array-temporary]

Which compiler is correct?

Community
  • 1
  • 1
J L
  • 563
  • 3
  • 17

2 Answers2

6

Clang is correct; see [conv.array]:

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

Even if the array is a temporary, and therefore a prvalue, it is legal to perform the array-to-pointer conversion on it.

It appears that the restriction on converting array prvalues into pointers was introduced in a patch that resolved gcc bug 53220. It seems that a consensus emerged on the thread that allowing the conversion was dangerous since initializing a pointer variable from the array would not extend the lifetime of the array. However, treating such code as though it is ill-formed is not the correct solution, since, as pointed out later in the thread, it is possible to use this conversion in a safe way, e.g., if the array is being passed to a function that takes a pointer (and therefore will live until the function returns).

You would probably have to file a new bug against gcc in order to get them to fix the issue.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • In that case, why does clang output a warning saying that the array `will be destroyed at the end of the full-expression`? If I get it right, that means that after that statement the array would be destroyed and, thus, not accesible. However, I can access and print the contents of the array after that, so it seems it is not destroyed as clang suggests. Many thanks for your help. – J L Mar 13 '17 at 15:45
  • 1
    @JL It's true, the array is destroyed. Attempting to access it after the end of the statement results in undefined behaviour. – Brian Bi Mar 13 '17 at 19:32
0

Actually, both compilers might be right! Although I'm not sure about the specific case (anybody willing to look up?), there are many situations the C++ standard just requires to give any diagnostic at all, but does not mandate a specific one of them, so both error or warning only can comply with the standard.

Additionally, have a look at your compiler flags - most (including GCC) compilers allow to turn warnings into errors via flags...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • I know what you mean, I faced a similar situation to what you describe several weeks ago. However, I'm not sure if this is one of this cases where both may be right... Regarding the compiler flags, I am just interested in knowing what is the correct approach, not to get my code compile. Thanks. – J L Mar 13 '17 at 15:41