common: Use strcmp to compare location file names

The logic to figure out where a missing #include should be inserted
uses pointer equality to check filenames -- the routine even says so.
But cpplib makes no such guarantee.  It happens to be true for input
that it preprocesses[* see line zero below], but is not true for
source that has already been preprocessed -- all those '# ...' line
directives produce disctinct filename strings.  That renders using
-fdirectives-only as a prescanning stage (as I understand some people
do), broken.

This patch changes to string comparisons, and explicitly rejects any
line-zero location map that occurs at the beginning of a file.  The
very first map of a file has a different string to the remaining maps,
and we never tripped on that because of the pointer comparison.  The
second testcase deploys -save-temps to cause an intermediate
preprocessed output that is read back.

	gcc/c-family/
	* c-common.c (try_to_locate_new_include_insertion_point): Use
	strcmp, not pointer equality.
	gcc/testsuite/
	* g++.dg/lookup/missing-std-include-10.h: New.
	* g++.dg/lookup/missing-std-include-10.C: New.
	* g++.dg/lookup/missing-std-include-11.C: New.
This commit is contained in:
Nathan Sidwell 2020-07-27 13:05:28 -07:00
parent b95eba48a1
commit 06aa77035c
4 changed files with 94 additions and 4 deletions

View File

@ -8764,8 +8764,7 @@ c_family_tests (void)
#endif /* #if CHECKING_P */ #endif /* #if CHECKING_P */
/* Attempt to locate a suitable location within FILE for a /* Attempt to locate a suitable location within FILE for a
#include directive to be inserted before. FILE should #include directive to be inserted before.
be a string from libcpp (pointer equality is used).
LOC is the location of the relevant diagnostic. LOC is the location of the relevant diagnostic.
Attempt to return the location within FILE immediately Attempt to return the location within FILE immediately
@ -8800,13 +8799,17 @@ try_to_locate_new_include_insertion_point (const char *file, location_t loc)
if (const line_map_ordinary *from if (const line_map_ordinary *from
= linemap_included_from_linemap (line_table, ord_map)) = linemap_included_from_linemap (line_table, ord_map))
if (from->to_file == file) /* We cannot use pointer equality, because with preprocessed
input all filename strings are unique. */
if (0 == strcmp (from->to_file, file))
{ {
last_include_ord_map = from; last_include_ord_map = from;
last_ord_map_after_include = NULL; last_ord_map_after_include = NULL;
} }
if (ord_map->to_file == file) /* Likewise, use strcmp, and reject any line-zero introductory
map. */
if (ord_map->to_line && 0 == strcmp (ord_map->to_file, file))
{ {
if (!first_ord_map_in_file) if (!first_ord_map_in_file)
first_ord_map_in_file = ord_map; first_ord_map_in_file = ord_map;

View File

@ -0,0 +1,43 @@
// { dg-do compile }
// { dg-additional-options -fdiagnostics-show-caret }
// comment
// Intentional blank lines
#include "missing-std-include-10.h"
// HERE
// Intentional blank lines
int main ()
{
return strcmp ("", "");
}
// { dg-additional-files "missing-std-include-10.h" }
// { dg-regexp {[^\n]*: error: 'strcmp' was not declared in this scope\n *return strcmp [^\n]*;\n *\^~*\n} }
// { dg-regexp {[^\n]* note: 'strcmp' is defined in header[^\n]*\n #include "missing-std-include-10.h"\n\+#include <cstring>\n // HERE\n} }

View File

@ -0,0 +1 @@
/* empty */

View File

@ -0,0 +1,43 @@
// { dg-do compile }
// { dg-additional-options {-fdiagnostics-show-caret -save-temps} }
// comment save-temps causes us to compile preprocessed output
// Intentional blank lines
#include "missing-std-include-10.h"
// HERE
// Intentional blank lines
int main ()
{
return strcmp ("", "");
}
// { dg-additional-files "missing-std-include-10.h" }
// { dg-regexp {[^\n]*: error: 'strcmp' was not declared in this scope\n *return strcmp [^\n]*;\n *\^~*\n} }
// { dg-regexp {[^\n]* note: 'strcmp' is defined in header[^\n]*\n #include "missing-std-include-10.h"\n\+#include <cstring>\n // HERE\n} }