* symtab.cc (Odr_violation_compare::operator()): Sort by just the
authorIan Lance Taylor <ian@airs.com>
Sat, 5 Feb 2011 01:52:40 +0000 (01:52 +0000)
committerIan Lance Taylor <ian@airs.com>
Sat, 5 Feb 2011 01:52:40 +0000 (01:52 +0000)
filename.

gold/ChangeLog
gold/symtab.cc

index e09ed793b2e0aedf335adc692cfd2de778e3f9cd..ef5ab361c595bc61e904ba2822ee779b59395145 100644 (file)
@@ -1,3 +1,8 @@
+2011-02-04  Jeffrey Yasskin  <jyasskin@google.com>
+
+       * symtab.cc (Odr_violation_compare::operator()): Sort by just the
+       filename.
+
 2011-02-02  Sriraman Tallam  <tmsriram@google.com>
 
        * icf.h (is_section_foldable_candidate): Change type of parameter
index 853191154dc1ec0c80a9f9c0f2caaea693d3f0c8..cb650fb088a30868046b081387a651a537b2ad80 100644 (file)
@@ -3012,11 +3012,12 @@ Symbol_table::print_stats() const
 // We check for ODR violations by looking for symbols with the same
 // name for which the debugging information reports that they were
 // defined in different source locations.  When comparing the source
-// location, we consider instances with the same base filename and
-// line number to be the same.  This is because different object
-// files/shared libraries can include the same header file using
-// different paths, and we don't want to report an ODR violation in
-// that case.
+// location, we consider instances with the same base filename to be
+// the same.  This is because different object files/shared libraries
+// can include the same header file using different paths, and
+// different optimization settings can make the line number appear to
+// be a couple lines off, and we don't want to report an ODR violation
+// in those cases.
 
 // This struct is used to compare line information, as returned by
 // Dwarf_line_info::one_addr2line.  It implements a < comparison
@@ -3027,13 +3028,28 @@ struct Odr_violation_compare
   bool
   operator()(const std::string& s1, const std::string& s2) const
   {
-    std::string::size_type pos1 = s1.rfind('/');
-    std::string::size_type pos2 = s2.rfind('/');
-    if (pos1 == std::string::npos
-       || pos2 == std::string::npos)
-      return s1 < s2;
-    return s1.compare(pos1, std::string::npos,
-                     s2, pos2, std::string::npos) < 0;
+    // Inputs should be of the form "dirname/filename:linenum" where
+    // "dirname/" is optional.  We want to compare just the filename.
+
+    // Find the last '/' and ':' in each string.
+    std::string::size_type s1begin = s1.rfind('/');
+    std::string::size_type s2begin = s2.rfind('/');
+    std::string::size_type s1end = s1.rfind(':');
+    std::string::size_type s2end = s2.rfind(':');
+    // If there was no '/' in a string, start at the beginning.
+    if (s1begin == std::string::npos)
+      s1begin = 0;
+    if (s2begin == std::string::npos)
+      s2begin = 0;
+    // If the ':' appeared in the directory name, compare to the end
+    // of the string.
+    if (s1end < s1begin)
+      s1end = s1.size();
+    if (s2end < s2begin)
+      s2end = s2.size();
+    // Compare takes lengths, not end indices.
+    return s1.compare(s1begin, s1end - s1begin,
+                     s2, s2begin, s2end - s2begin) < 0;
   }
 };