common: Use strcmp to compare location file names
authorNathan Sidwell <nathan@acm.org>
Mon, 27 Jul 2020 20:05:28 +0000 (13:05 -0700)
committerNathan Sidwell <nathan@acm.org>
Mon, 27 Jul 2020 20:13:32 +0000 (13:13 -0700)
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.

gcc/c-family/c-common.c
gcc/testsuite/g++.dg/lookup/missing-std-include-10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/missing-std-include-10.h [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/missing-std-include-11.C [new file with mode: 0644]

index e2569c6..116867a 100644 (file)
@@ -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 a/gcc/testsuite/g++.dg/lookup/missing-std-include-10.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-10.C
new file mode 100644 (file)
index 0000000..9dfa78f
--- /dev/null
@@ -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 a/gcc/testsuite/g++.dg/lookup/missing-std-include-10.h b/gcc/testsuite/g++.dg/lookup/missing-std-include-10.h
new file mode 100644 (file)
index 0000000..40a8c17
--- /dev/null
@@ -0,0 +1 @@
+/* empty */
diff --git a/gcc/testsuite/g++.dg/lookup/missing-std-include-11.C b/gcc/testsuite/g++.dg/lookup/missing-std-include-11.C
new file mode 100644 (file)
index 0000000..ec2c494
--- /dev/null
@@ -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} }