Is gcc wrong not diagnose narrowing conversions in non-type template arguments?
Asked Answered
T

1

11

The following program compiles without errors or warning with gcc 4.8.1, -Wall -std=c++11:

template<unsigned N>
struct A{};

int main(){
    A<1-2> a;
    (void)a;
    return 0;
}

clang 3.3 with the same options gives this error:

error: non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int' [-Wc++11-narrowing]

As per this question, it looks like gcc's present policy just to give warnings for narrowing conversions where the Standard indicates errors, and where clang gives the indicated errors. But in this case gcc does not even give a warning.

None of the examples of narrowing conversion errors that are given by the Standard at § 8.5.4/7 (reproduced in that question) covers the case of a narrowing conversion of a non-type template argument, but at § 14.3.2/5 the Standard says:

For a non-type template-parameter of integral or enumeration type, conversions permitted in a con- verted constant expression (5.19) are applied.

And § 5.19/3 says:

A converted constant expression of type T is a literal constant expression, implicitly converted to type T, where the implicit conversion (if any) is permitted in a literal constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4)

(my emphasis).

This seems to me to mean that even by its own yardstick gcc is at fault in not at all diagnosing a narrowing conversion in this case. Do I read this right? Is there a Standard-based counter-argument?

I am asking the question with more feeling that mere curiosity. In a recursive TMP setting, clang's error diagnostic in this case will pinpoint a bug in which an unsigned non-type template argument falls through 0, whereas all you get from gcc is "maximum template instantiation depth exceeded".

Tormentor answered 9/7, 2013 at 22:8 Comment(5)
The standard never "calls for errors" or for warnings - the standard only requires an implementation to issue a diagnostic. Whether such a diagnostic takes the form of a compiler error, or a warning, or something entirely different from them both, is outside the scope of the standard.Trinatrinal
@Casey. I understand, but I am questioning the absence of any diagnostic; the absence of anything but success.Tormentor
@Casey. No, my apologies. I said "the required errors", and shouldn't have.Tormentor
I also understand, thus comment instead of answer ;)Trinatrinal
In c++03 this was valid (IIRC). -1 -> unsigned is a narrowing conversion, so GCC is wrong to allow that in C++11 mode.Pachalic
L
2

GCC is not so pedantic like Clang, however, it can still detect those kind of errors:

gcc -Wsign-conversion 1.cpp
1.cpp: In function 'int main()':
1.cpp:5:10: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]
     A<1-2> a;
          ^

-Wall does not actually turn on all possible checks. Read this page for more examples: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

I'm using gcc.EXE (GCC) 4.8.0 20130203 (experimental)

Loesceke answered 21/7, 2013 at 17:4 Comment(2)
That is a useful point (+1), but I don't think it is an answer. § 5.19/3 (quoted) permits the converted constant expression to be implicitly converted to target type but still expressly prohibits a narrowing conversion. -Wsign-conversion gives a useful diagnostic of a conversion the Standard permits. Thus is not activated even by -pedantic, but even with -pedantic there is no diagnostic of the narrowing conversion which the Standard prohibits. This GCC warning is also common to C and is much older than the banning of narrowing conversions in C++11.Tormentor
I have tried -pedantic also and was disappointed. This looks like a compiler bug to me.Loesceke

© 2022 - 2024 — McMap. All rights reserved.