Bug 43167 - Warnings should not be disabled when instantiating templates defined in system headers
Summary: Warnings should not be disabled when instantiating templates defined in syste...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 114237 (view as bug list)
Depends on:
Blocks: 87614
  Show dependency treegraph
 
Reported: 2010-02-24 19:33 UTC by Ian Lance Taylor
Modified: 2024-03-05 14:29 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.5.3, 4.8.3, 4.9.3, 5.3.0, 6.3.0, 7.0
Last reconfirmed: 2019-03-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Lance Taylor 2010-02-24 19:33:55 UTC
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.
Comment 1 Andrew Pinski 2010-02-24 19:35:42 UTC
There was a bug asking the opposite way IIRC.
Comment 2 Andrew Pinski 2010-02-24 19:37:39 UTC
PR 36760 is an example where it was asking the opposite way.  I thought there was more than that bug though.
Comment 3 Andrew Pinski 2010-02-24 19:38:54 UTC
Found it, PR 30500 was the exact bug which changed this behavior :).
Comment 4 Andrew Pinski 2010-02-24 19:41:57 UTC
>This warning indicates a problem with user code. 

Or is it?  Since long long does not exist in C++03 :).
Comment 5 Ian Lance Taylor 2010-02-24 20:56:32 UTC
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.
Comment 6 Paolo Carlini 2010-02-24 21:43:07 UTC
Out of curiosity: what happens with ICC? (normally installed with the system libstdc++ as C++ run-time)?
Comment 7 Ian Lance Taylor 2010-02-24 22:33:39 UTC
I don't know about icc, but see also http://llvm.org/PR6418 .
Comment 8 Paolo Carlini 2010-02-24 22:47:09 UTC
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.
Comment 9 Manuel López-Ibáñez 2010-02-24 22:52:08 UTC
(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?)
Comment 10 Andrew Pinski 2010-02-24 22:56:00 UTC
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
Comment 11 Andrew Pinski 2010-02-24 23:00:02 UTC
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> > >
Comment 12 Manuel López-Ibáñez 2010-02-24 23:20:42 UTC
(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"?
Comment 13 Ian Lance Taylor 2010-02-25 00:17:01 UTC
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.
Comment 14 Jonathan Wakely 2010-04-21 19:02:22 UTC
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
Comment 15 Martin Sebor 2017-01-24 20:31:38 UTC
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;
                  ^
Comment 16 Jonathan Wakely 2019-03-22 15:21:20 UTC
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
Comment 17 Jonathan Wakely 2019-03-22 15:31:07 UTC
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.
Comment 18 Jonathan Wakely 2019-03-22 15:33:29 UTC
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
Comment 19 Manuel López-Ibáñez 2019-03-22 20:21:14 UTC
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.
Comment 20 Jonathan Wakely 2019-03-22 23:25:02 UTC
(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.
Comment 21 Jonathan Wakely 2020-06-19 19:10:13 UTC
*** Bug 95765 has been marked as a duplicate of this bug. ***
Comment 22 Jonathan Wakely 2024-03-05 14:29:30 UTC
*** Bug 114237 has been marked as a duplicate of this bug. ***