]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Optimize fs::path::operator+=(const path&) alias check
authorJonathan Wakely <jwakely@redhat.com>
Tue, 17 Mar 2026 15:58:10 +0000 (15:58 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 20 Mar 2026 09:39:37 +0000 (09:39 +0000)
Instead of a loop that compares &p to the address of each path
component, we can just do two pointer comparisons to see if &p is within
the contiguous array of components.

We don't need to make the same change to experimental::filesystem::path
because as noted in r15-9709-gbeb0ffd36eedf0 the TS implementation
doesn't attempt to optimize operator+= so doesn't care if the parameter
aliases *this.

libstdc++-v3/ChangeLog:

* src/c++17/fs_path.cc (path::operator+=): Use pointer
comparison to detect aliasing instead of a loop.

Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com>
libstdc++-v3/src/c++17/fs_path.cc

index c217dc27801835d1cf1868f73d65b39d7acfcd2d..763d5609c7f77bdaf094521feff93d98ca05a39e 100644 (file)
@@ -927,9 +927,11 @@ path::operator+=(const path& p)
     return *this += p.native();
   // Handle p += *i where i is in [p.begin(),p.end()), for the same reason.
   if (_M_type() == _Type::_Multi && p._M_type() != _Type::_Multi)
-    for (const path& cmpt : *this)
-      if (&cmpt == &p) [[unlikely]]
+    {
+      const auto first = _M_cmpts.begin(), last = first + _M_cmpts.size();
+      if (!std::less<>()(&p, first) && std::less<>()(&p, last)) [[unlikely]]
        return *this += p.native();
+    }
 
 #if _GLIBCXX_FILESYSTEM_IS_WINDOWS
   if (_M_type() == _Type::_Root_name