Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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".

like image 968
Mike Kinghan Avatar asked Jul 09 '13 22:07

Mike Kinghan


People also ask

Does a class template need to have a type argument?

A class template does not need to have a type argument if it has non-type arguments. For example, the following template is a valid class template: Again, these two declarations refer to distinct classes because the values of their non-type arguments differ.

What are the requirements for non-type address arguments?

For non-type address arguments, the type of the instance argument must be of the form identifier or & identifier , and the type of the instance argument must match the template parameter exactly, except that a function name is changed to a pointer to function type before matching.

Why are the objects created by template arguments identical?

An object of such a template class is created with both the type argument T of the class and the value of the non-type template argument size. The objects created by these expressions are identical because the template arguments evaluate identically.

What is the difference between instance argument and template parameter?

For non-type integral arguments, the instance argument matches the corresponding template parameter as long as the instance argument has a value and sign appropriate to the parameter type.


1 Answers

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)

like image 128
Sergey K. Avatar answered Sep 21 '22 17:09

Sergey K.