https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85269

--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
Your example in comment #2 should not warn.  Projects often have their own
"base" header that includes a a bunch of standard headers and that by
convention is included in each of the project's source files so they don't have
to worry about this kind of portability problem.

I envision an algorithm that would look up the standard header where each
standard symbol used in a translation unit is declared or defined and see if
the standard header has been directly included at that point by some
non-standard file; if not, the warning would trigger.

I imagine there would need to be exceptions for the common cases you describe
where this warning would be unhelpful, and the algorithm would need to be
parameterized on the version of the standard to account for changes to the
synopses of the headers.

The <iosfwd> problem is interesting.  A solution to it might involve a separate
enhancement to the existing machinery.  For example, in the following, GCC
suggests to include <vector> (as expected) but doesn't provide a similar
suggestion for the incomplete char_traits (which is required to be
forward-declared in <iosfwd>).  GCC also doesn't provide such a suggestion for
std::string which isn't required to be declared in <iostfwd>.  The warning
should be able to differentiate these cases and trigger for any mention of
std::string but avoid triggering for uses of std::char_traits that don't
require it to be a complete type.  This also suggests that for uses of types
declared in <iosfwd> without the appropriate header included GCC might want to
suggest to include <iosfwd> when the use doesn't require the type to be
complete, rather than suggesting to include the header that defines the type.

#include <iosfwd>

enum {
  e0 = sizeof (std::char_traits<char>*),    // okay, no warning
  e1 = sizeof (std::char_traits<char>),     // warn if not error

  e2 = sizeof (std::basic_string<char>*),   // warn
  e3 = sizeof (std::basic_string<char>),    // warn if not error

  e4 = sizeof (std::vector<int>*),          // warn if not error
  e5 = sizeof (std::vector<int>)            // warn if not error
};
pr85269.C:5:38: error: invalid application of ‘sizeof’ to incomplete type
‘std::char_traits<char>’
   e1 = sizeof (std::char_traits<char>),     // warn if not error
                                      ^
pr85269.C:8:39: error: invalid application of ‘sizeof’ to incomplete type
‘std::__cxx11::basic_string<char>’
   e3 = sizeof (std::basic_string<char>),    // warn if not error
                                       ^
pr85269.C:10:21: error: ‘vector’ is not a member of ‘std’
   e4 = sizeof (std::vector<int>*),          // warn if not error
                     ^~~~~~
pr85269.C:10:21: note: ‘std::vector’ is defined in header ‘<vector>’; did you
forget to ‘#include <vector>’?
pr85269.C:2:1:
+#include <vector>

pr85269.C:10:21:
   e4 = sizeof (std::vector<int>*),          // warn if not error
                     ^~~~~~
pr85269.C:10:28: error: expected primary-expression before ‘int’
   e4 = sizeof (std::vector<int>*),          // warn if not error
                            ^~~
pr85269.C:10:28: error: expected ‘)’ before ‘int’
   e4 = sizeof (std::vector<int>*),          // warn if not error
               ~            ^~~
                            )

Reply via email to