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.
pushing ...
--
Nathan Sidwell
diff --git c/gcc/c-family/c-common.c w/gcc/c-family/c-common.c
index 51ecde69f2d..98b80d56cae 100644
--- c/gcc/c-family/c-common.c
+++ w/gcc/c-family/c-common.c
@@ -8764,8 +8764,7 @@ c_family_tests (void)
#endif /* #if CHECKING_P */
/* Attempt to locate a suitable location within FILE for a
- #include directive to be inserted before. FILE should
- be a string from libcpp (pointer equality is used).
+ #include directive to be inserted before.
LOC is the location of the relevant diagnostic.
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
= 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_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)
first_ord_map_in_file = ord_map;
diff --git c/gcc/testsuite/g++.dg/lookup/missing-std-include-10.C w/gcc/testsuite/g++.dg/lookup/missing-std-include-10.C
new file mode 100644
index 00000000000..9dfa78fb60e
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/missing-std-include-10.C
@@ -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} }
diff --git c/gcc/testsuite/g++.dg/lookup/missing-std-include-10.h w/gcc/testsuite/g++.dg/lookup/missing-std-include-10.h
new file mode 100644
index 00000000000..40a8c178f10
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/missing-std-include-10.h
@@ -0,0 +1 @@
+/* empty */
diff --git c/gcc/testsuite/g++.dg/lookup/missing-std-include-11.C w/gcc/testsuite/g++.dg/lookup/missing-std-include-11.C
new file mode 100644
index 00000000000..ec2c494c557
--- /dev/null
+++ w/gcc/testsuite/g++.dg/lookup/missing-std-include-11.C
@@ -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} }