Consider this C++ code: #include <vector> #include <numeric> #include <inttypes.h> int64_t sum(const std::vector<int64_t>& values) { return std::accumulate(values.begin(), values.end(), 0); } I'm using mainline. When I compile this with -Wconversion I get no warning. When I compile it with -Wconversion -Wsystem-headers I get In file included from ../install/include/c++/4.5.0/numeric:63:0, from /home/iant/foo1.cc:2: ../install/include/c++/4.5.0/bits/stl_numeric.h: In function ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = __gnu_cxx::__normal_iterator<const long long int*, std::vector<long long int> >, _Tp = int]’: /home/iant/foo1.cc:6:55: instantiated from here ../install/include/c++/4.5.0/bits/stl_numeric.h:122:2: warning: conversion to ‘int’ from ‘long long int’ may alter its value This warning indicates a problem with user code. It is being disabled because the template is defined in a system header. That is incorrect in this sort of case. When a template is instantiated, we should issue warnings as appropriate, even if the template is defined in a system header.
There was a bug asking the opposite way IIRC.
PR 36760 is an example where it was asking the opposite way. I thought there was more than that bug though.
Found it, PR 30500 was the exact bug which changed this behavior :).
>This warning indicates a problem with user code. Or is it? Since long long does not exist in C++03 :).
The use of long long is irrelevant here. PR 30500 appears to be about non-dependent types. So let's make this bug be about dependent types. I know that makes it harder, but it seems to me to be the right thing to do.
Out of curiosity: what happens with ICC? (normally installed with the system libstdc++ as C++ run-time)?
I don't know about icc, but see also http://llvm.org/PR6418 .
ICC doesn't warn (emits another spurious warning, by the way, which has nothing to do with this issue). More generally, compilers using the EDG front-end, eg, Comeau, apparently do not warn at the most strict diagnostic level. Likewise SunStudio. I'm not saying we cannot do better, just, seems a pretty sophisticated goal, and really, in my opinion, we should be *very* careful with false positive, because normally it's unacceptable to emit warnings about internal details of the implementation.
(In reply to comment #7) > I don't know about icc, but see also http://llvm.org/PR6418 . Out of curiosity. Is it really the output of g++ so messy compared with clang, or is it an artifact of copy+paste from the console? It looks totally broken (printing "In function" after filename?)
looks like the terminial is wrapping funny. In file included from /home/apinski/local-gcc/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/numeric:62:0, from t.cc:2: /home/apinski/local-gcc/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_numeric.h: In function '_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = __gnu_cxx::__normal_iterator<const long int*, std::vector<long int> >, _Tp = int]': t.cc:6:57: instantiated from here /home/apinski/local-gcc/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_numeric.h:123:2: warning: conversion to 'int' from 'long int' may alter its value
Note this is much better than what it was in 4.3 where std::vector<long> was shown as: std::vector<long int, std::allocator<long int> > >
(In reply to comment #11) > Note this is much better than what it was in 4.3 where std::vector<long> was > shown as: > std::vector<long int, std::allocator<long int> > > That part looks better GCC, however, in the context information, the clang output is far clearer. Why we print the file with no location info just above the "In function"?
Paolo: It is definitely a complicated case, the concern about false positives is entirely valid. This leads us to introducing more command line options, plus getting #pragma GCC diagnostic to work. I'm not sure what the best solution is.
Bug 43820 shows cases where libstdc++ was *relying* on the front-end issuing warnings about calling delete with a pointer to incomplete types. I'm going to change the library code to handle it instead, but it's an extra data point related to this bug
I can confirm that the warnings are still suppressed in GCC 7.0: Without -Wsystem-headers: $ /build/gcc-git/gcc/xg++ -B /build/gcc-git/gcc -nostdinc++ -I /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include -I /src/gcc/git/libstdc++-v3/libsupc++ -I /src/gcc/git/libstdc++-v3/include/backward -I /src/gcc/git/libstdc++-v3/testsuite/util -L /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -S -Wall -Wextra -Wpedantic -Wconversion t.C $ With -Wsystem-headers: $ /build/gcc-git/gcc/xg++ -B /build/gcc-git/gcc -nostdinc++ -I /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include -I /src/gcc/git/libstdc++-v3/libsupc++ -I /src/gcc/git/libstdc++-v3/include/backward -I /src/gcc/git/libstdc++-v3/testsuite/util -L /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -S -Wall -Wextra -Wpedantic -Wconversion -Wsystem-headers t.C In file included from /usr/include/inttypes.h:27:0, from t.C:4: /build/gcc-git/gcc/include/stdint.h:9:3: warning: #include_next is a GCC extension # include_next <stdint.h> ^~~~~~~~~~~~ In file included from /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/vector:60:0, from t.C:2: /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h: In function ‘constexpr int std::__lg(int)’: /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:1001:44: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value -Wconversion] { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } ^ /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h: In function ‘constexpr unsigned int std::__lg(unsigned int)’: /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_algobase.h:1005:44: warning: conversion to ‘unsigned int’ from ‘long unsigned int’ may alter its value [-Wconversion] { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } ^ In file included from /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/numeric:62:0, from t.C:3: /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_numeric.h: In instantiation of ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = __gnu_cxx::__normal_iterator<const long int*, std::vector<long int> >; _Tp = int]’: t.C:7:57: required from here /build/gcc-git/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_numeric.h:127:18: warning: conversion to ‘int’ from ‘long int’ may alter its value [-Wconversion] __init = __init + *__first; ^
Bug 80472 comment 4 is another case where GCC detects undefined behaviour caused by user-provided values, but the warning is suppressed because it's inside a template defined in a system header: In file included from /home/jwakely/gcc/9/include/c++/9.0.1/bits/stl_algobase.h:66, from /home/jwakely/gcc/9/include/c++/9.0.1/bits/forward_list.h:38, from /home/jwakely/gcc/9/include/c++/9.0.1/forward_list:38, from prev.cc:1: /home/jwakely/gcc/9/include/c++/9.0.1/bits/stl_iterator_base_funcs.h:153:7: warning: iteration 9223372036854775807 invokes undefined behavior [-Waggressive-loop-optimizations] 153 | while (__n--) | ^~~~~ /home/jwakely/gcc/9/include/c++/9.0.1/bits/stl_iterator_base_funcs.h:153:7: note: within this loop
And Bug 87614 is a simpler form of Ian's original example in comment 0: #include <vector> int main() { std::vector<unsigned short> a; a.emplace_back(70000); } With -Wsystem-header -Wconversion: [...] 87614.cc:5:25: required from here /home/jwakely/gcc/9/include/c++/9.0.1/ext/new_allocator.h:147:4: warning: conversion from 'int' to 'short unsigned int' may change value [-Wconversion] 147 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } | ^ This error comes from the user's code, the fact the actual conversion happens deep inside libstdc++ rather than at the call site is only because the function templates preserves the original type all the way down. But the error is in the user's code, not in the libstdc++ code which is just doing what it was told to by the user. The better GCC gets at detecting such problems and warning about them, the bigger a problem it becomes that using templates from the C++ standard library suppresses all GCC's useful warnings.
From Matthias Kretz on IRC: GCC needs to make a difference between warnings that apply when reading the system headers and warnings that only manifest on a template instantiation or constprop
I think the solution is to have more locations. If the diagnostic code knew where the user value came from then it will know to not suppress the diagnostic. I wonder what happens if you used something that actually has a location, like an expression, for the first test case using emplace(). On Fri, 22 Mar 2019, 15:33 redi at gcc dot gnu.org, < gcc-bugzilla@gcc.gnu.org> wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43167 > > --- Comment #18 from Jonathan Wakely <redi at gcc dot gnu.org> --- > From Matthias Kretz on IRC: > > GCC needs to make a difference between warnings that apply when reading the > system headers and warnings that only manifest on a template instantiation > or > constprop > > -- > You are receiving this mail because: > You are on the CC list for the bug.
(In reply to Manuel López-Ibáñez from comment #19) > I wonder what happens if you used something that actually has a > location, like an expression, for the first test case using emplace(). It doesn't make any difference.
*** Bug 95765 has been marked as a duplicate of this bug. ***
*** Bug 114237 has been marked as a duplicate of this bug. ***