LCOV - code coverage report
Current view: top level - lib/Support - Path.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 429 491 87.4 %
Date: 2018-02-25 19:55:18 Functions: 77 84 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : //  This file implements the operating system Path API.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/Support/Path.h"
      15             : #include "llvm/ADT/ArrayRef.h"
      16             : #include "llvm/Support/Endian.h"
      17             : #include "llvm/Support/Errc.h"
      18             : #include "llvm/Support/ErrorHandling.h"
      19             : #include "llvm/Support/FileSystem.h"
      20             : #include "llvm/Support/Process.h"
      21             : #include "llvm/Support/Signals.h"
      22             : #include <cctype>
      23             : #include <cstring>
      24             : 
      25             : #if !defined(_MSC_VER) && !defined(__MINGW32__)
      26             : #include <unistd.h>
      27             : #else
      28             : #include <io.h>
      29             : #endif
      30             : 
      31             : using namespace llvm;
      32             : using namespace llvm::support::endian;
      33             : 
      34             : namespace {
      35             :   using llvm::StringRef;
      36             :   using llvm::sys::path::is_separator;
      37             :   using llvm::sys::path::Style;
      38             : 
      39             :   inline Style real_style(Style style) {
      40             : #ifdef LLVM_ON_WIN32
      41             :     return (style == Style::posix) ? Style::posix : Style::windows;
      42             : #else
      43    91520412 :     return (style == Style::windows) ? Style::windows : Style::posix;
      44             : #endif
      45             :   }
      46             : 
      47             :   inline const char *separators(Style style) {
      48             :     if (real_style(style) == Style::windows)
      49             :       return "\\/";
      50             :     return "/";
      51             :   }
      52             : 
      53             :   inline char preferred_separator(Style style) {
      54             :     if (real_style(style) == Style::windows)
      55             :       return '\\';
      56             :     return '/';
      57             :   }
      58             : 
      59    11602763 :   StringRef find_first_component(StringRef path, Style style) {
      60             :     // Look for this first component in the following order.
      61             :     // * empty (in this case we return an empty string)
      62             :     // * either C: or {//,\\}net.
      63             :     // * {/,\}
      64             :     // * {file,directory}name
      65             : 
      66    11602763 :     if (path.empty())
      67      431067 :       return path;
      68             : 
      69             :     if (real_style(style) == Style::windows) {
      70             :       // C:
      71          34 :       if (path.size() >= 2 &&
      72          77 :           std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
      73             :         return path.substr(0, 2);
      74             :     }
      75             : 
      76             :     // //net
      77    26185924 :     if ((path.size() > 2) && is_separator(path[0], style) &&
      78    15872007 :         path[0] == path[1] && !is_separator(path[2], style)) {
      79             :       // Find the next directory separator.
      80         804 :       size_t end = path.find_first_of(separators(style), 2);
      81             :       return path.substr(0, end);
      82             :     }
      83             : 
      84             :     // {/,\}
      85    22339042 :     if (is_separator(path[0], style))
      86             :       return path.substr(0, 1);
      87             : 
      88             :     // * {file,directory}name
      89     6467649 :     size_t end = path.find_first_of(separators(style));
      90             :     return path.substr(0, end);
      91             :   }
      92             : 
      93     2175465 :   size_t filename_pos(StringRef str, Style style) {
      94     2175546 :     if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
      95             :       return 0;
      96             : 
      97     3859696 :     if (str.size() > 0 && is_separator(str[str.size() - 1], style))
      98       79324 :       return str.size() - 1;
      99             : 
     100     4192268 :     size_t pos = str.find_last_of(separators(style), str.size() - 1);
     101             : 
     102             :     if (real_style(style) == Style::windows) {
     103          11 :       if (pos == StringRef::npos)
     104           0 :         pos = str.find_last_of(':', str.size() - 2);
     105             :     }
     106             : 
     107     2096957 :     if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
     108             :       return 0;
     109             : 
     110     1510312 :     return pos + 1;
     111             :   }
     112             : 
     113     2245946 :   size_t root_dir_start(StringRef str, Style style) {
     114             :     // case "c:/"
     115             :     if (real_style(style) == Style::windows) {
     116          43 :       if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
     117             :         return 2;
     118             :     }
     119             : 
     120             :     // case "//"
     121     2246717 :     if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
     122             :       return StringRef::npos;
     123             : 
     124             :     // case "//net"
     125     5347579 :     if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
     126         258 :         !is_separator(str[2], style)) {
     127         226 :       return str.find_first_of(separators(style), 2);
     128             :     }
     129             : 
     130             :     // case "/"
     131     5662892 :     if (str.size() > 0 && is_separator(str[0], style))
     132             :       return 0;
     133             : 
     134             :     return StringRef::npos;
     135             :   }
     136             : 
     137      634130 :   size_t parent_path_end(StringRef path, Style style) {
     138      634130 :     size_t end_pos = filename_pos(path, style);
     139             : 
     140             :     bool filename_was_sep =
     141     1261827 :         path.size() > 0 && is_separator(path[end_pos], style);
     142             : 
     143             :     // Skip separators except for root dir.
     144      634126 :     size_t root_dir_pos = root_dir_start(path.substr(0, end_pos), style);
     145             : 
     146     2209740 :     while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
     147     1075310 :            is_separator(path[end_pos - 1], style))
     148             :       --end_pos;
     149             : 
     150      634128 :     if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
     151             :       return StringRef::npos;
     152             : 
     153      634128 :     return end_pos;
     154             :   }
     155             : } // end unnamed namespace
     156             : 
     157             : enum FSEntity {
     158             :   FS_Dir,
     159             :   FS_File,
     160             :   FS_Name
     161             : };
     162             : 
     163             : static std::error_code
     164       17288 : createUniqueEntity(const Twine &Model, int &ResultFD,
     165             :                    SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
     166             :                    unsigned Mode, FSEntity Type,
     167             :                    sys::fs::OpenFlags Flags = sys::fs::F_None) {
     168             :   SmallString<128> ModelStorage;
     169       17288 :   Model.toVector(ModelStorage);
     170             : 
     171       17288 :   if (MakeAbsolute) {
     172             :     // Make model absolute by prepending a temp directory if it's not already.
     173        5127 :     if (!sys::path::is_absolute(Twine(ModelStorage))) {
     174             :       SmallString<128> TDir;
     175        5127 :       sys::path::system_temp_directory(true, TDir);
     176        5127 :       sys::path::append(TDir, Twine(ModelStorage));
     177        5127 :       ModelStorage.swap(TDir);
     178             :     }
     179             :   }
     180             : 
     181             :   // From here on, DO NOT modify model. It may be needed if the randomly chosen
     182             :   // path already exists.
     183       17288 :   ResultPath = ModelStorage;
     184             :   // Null terminate.
     185       17287 :   ResultPath.push_back(0);
     186             :   ResultPath.pop_back();
     187             : 
     188             : retry_random_path:
     189             :   // Replace '%' with random chars.
     190     1825385 :   for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
     191     3616194 :     if (ModelStorage[i] == '%')
     192      244424 :       ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
     193             :   }
     194             : 
     195             :   // Try to open + create the file.
     196       17288 :   switch (Type) {
     197             :   case FS_File: {
     198       12216 :     if (std::error_code EC =
     199       12216 :             sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
     200       12216 :                                       Flags | sys::fs::F_Excl, Mode)) {
     201             :       if (EC == errc::file_exists)
     202             :         goto retry_random_path;
     203          75 :       return EC;
     204             :     }
     205             : 
     206       12141 :     return std::error_code();
     207             :   }
     208             : 
     209        5030 :   case FS_Name: {
     210             :     std::error_code EC =
     211        5030 :         sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
     212             :     if (EC == errc::no_such_file_or_directory)
     213        5030 :       return std::error_code();
     214           0 :     if (EC)
     215           0 :       return EC;
     216           0 :     goto retry_random_path;
     217             :   }
     218             : 
     219             :   case FS_Dir: {
     220          42 :     if (std::error_code EC =
     221          42 :             sys::fs::create_directory(ResultPath.begin(), false)) {
     222             :       if (EC == errc::file_exists)
     223             :         goto retry_random_path;
     224           0 :       return EC;
     225             :     }
     226          42 :     return std::error_code();
     227             :   }
     228             :   }
     229           0 :   llvm_unreachable("Invalid Type");
     230             : }
     231             : 
     232             : namespace llvm {
     233             : namespace sys  {
     234             : namespace path {
     235             : 
     236    11599927 : const_iterator begin(StringRef path, Style style) {
     237             :   const_iterator i;
     238    11599927 :   i.Path      = path;
     239    11599927 :   i.Component = find_first_component(path, style);
     240    11593412 :   i.Position  = 0;
     241    11593412 :   i.S = style;
     242    11593412 :   return i;
     243             : }
     244             : 
     245    11601018 : const_iterator end(StringRef path) {
     246             :   const_iterator i;
     247    11601018 :   i.Path      = path;
     248    11601018 :   i.Position  = path.size();
     249    11601018 :   return i;
     250             : }
     251             : 
     252     6754472 : const_iterator &const_iterator::operator++() {
     253             :   assert(Position < Path.size() && "Tried to increment past end!");
     254             : 
     255             :   // Increment Position to past the current component
     256     6754472 :   Position += Component.size();
     257             : 
     258             :   // Check for end.
     259     6754472 :   if (Position == Path.size()) {
     260     1375590 :     Component = StringRef();
     261     1375590 :     return *this;
     262             :   }
     263             : 
     264             :   // Both POSIX and Windows treat paths that begin with exactly two separators
     265             :   // specially.
     266     7908062 :   bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
     267     5381252 :                  Component[1] == Component[0] && !is_separator(Component[2], S);
     268             : 
     269             :   // Handle separators.
     270    10757086 :   if (is_separator(Path[Position], S)) {
     271             :     // Root dir.
     272     4466964 :     if (was_net ||
     273             :         // c:/
     274     4466560 :         (real_style(S) == Style::windows && Component.endswith(":"))) {
     275           0 :       Component = Path.substr(Position, 1);
     276         791 :       return *this;
     277             :     }
     278             : 
     279             :     // Skip extra separators.
     280    31267455 :     while (Position != Path.size() && is_separator(Path[Position], S)) {
     281     4466860 :       ++Position;
     282             :     }
     283             : 
     284             :     // Treat trailing '/' as a '.'.
     285     8936544 :     if (Position == Path.size()) {
     286          33 :       --Position;
     287          33 :       Component = ".";
     288          33 :       return *this;
     289             :     }
     290             :   }
     291             : 
     292             :   // Find next component.
     293    10760478 :   size_t end_pos = Path.find_first_of(separators(S), Position);
     294    10759181 :   Component = Path.slice(Position, end_pos);
     295             : 
     296     5378809 :   return *this;
     297             : }
     298             : 
     299    16438485 : bool const_iterator::operator==(const const_iterator &RHS) const {
     300    16438485 :   return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
     301             : }
     302             : 
     303         287 : ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
     304         287 :   return Position - RHS.Position;
     305             : }
     306             : 
     307     1497268 : reverse_iterator rbegin(StringRef Path, Style style) {
     308             :   reverse_iterator I;
     309     1497268 :   I.Path = Path;
     310     1497268 :   I.Position = Path.size();
     311     1497268 :   I.S = style;
     312     1497268 :   return ++I;
     313             : }
     314             : 
     315       68595 : reverse_iterator rend(StringRef Path) {
     316             :   reverse_iterator I;
     317       68595 :   I.Path = Path;
     318       68595 :   I.Component = Path.substr(0, 0);
     319       68595 :   I.Position = 0;
     320       68595 :   return I;
     321             : }
     322             : 
     323     1611830 : reverse_iterator &reverse_iterator::operator++() {
     324             :   // If we're at the end and the previous char was a '/', return '.' unless
     325             :   // we are the root path.
     326     1611830 :   size_t root_dir_pos = root_dir_start(Path, S);
     327     4233720 :   if (Position == Path.size() && Path.size() > root_dir_pos + 1 &&
     328     2020124 :       is_separator(Path[Position - 1], S)) {
     329       74781 :     --Position;
     330       74781 :     Component = ".";
     331       74781 :     return *this;
     332             :   }
     333             : 
     334             :   // Skip separators unless it's the root directory.
     335     1537048 :   size_t end_pos = Position;
     336             : 
     337     2812213 :   while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
     338     2323752 :          is_separator(Path[end_pos - 1], S))
     339             :     --end_pos;
     340             : 
     341             :   // Find next separator.
     342     3074098 :   size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
     343     1537045 :   Component = Path.slice(start_pos, end_pos);
     344     1537045 :   Position = start_pos;
     345     1537045 :   return *this;
     346             : }
     347             : 
     348      114729 : bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
     349      114887 :   return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
     350      114887 :          Position == RHS.Position;
     351             : }
     352             : 
     353           3 : ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
     354           3 :   return Position - RHS.Position;
     355             : }
     356             : 
     357     2963527 : StringRef root_path(StringRef path, Style style) {
     358     2963527 :   const_iterator b = begin(path, style), pos = b, e = end(path);
     359     2964157 :   if (b != e) {
     360             :     bool has_net =
     361     3137864 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     362             :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     363             : 
     364     2778419 :     if (has_net || has_drive) {
     365        1241 :       if ((++pos != e) && is_separator((*pos)[0], style)) {
     366             :         // {C:/,//net/}, so get the first two components.
     367         411 :         return path.substr(0, b->size() + pos->size());
     368             :       } else {
     369             :         // just {C:,//net}, return the first component.
     370           4 :         return *b;
     371             :       }
     372             :     }
     373             : 
     374             :     // POSIX style root directory.
     375     5556008 :     if (is_separator((*b)[0], style)) {
     376     2312040 :       return *b;
     377             :     }
     378             :   }
     379             : 
     380      651540 :   return StringRef();
     381             : }
     382             : 
     383     4141510 : StringRef root_name(StringRef path, Style style) {
     384     4141510 :   const_iterator b = begin(path, style), e = end(path);
     385     4140023 :   if (b != e) {
     386             :     bool has_net =
     387     7921648 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     388             :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     389             : 
     390     4061712 :     if (has_net || has_drive) {
     391             :       // just {C:,//net}, return the first component.
     392           6 :       return *b;
     393             :     }
     394             :   }
     395             : 
     396             :   // No path or no name.
     397     4139965 :   return StringRef();
     398             : }
     399             : 
     400     2310117 : StringRef root_directory(StringRef path, Style style) {
     401     2310117 :   const_iterator b = begin(path, style), pos = b, e = end(path);
     402     2310652 :   if (b != e) {
     403             :     bool has_net =
     404     2781299 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     405             :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     406             : 
     407     2171299 :     if ((has_net || has_drive) &&
     408             :         // {C:,//net}, skip to the next component.
     409     2171562 :         (++pos != e) && is_separator((*pos)[0], style)) {
     410         270 :       return *pos;
     411             :     }
     412             : 
     413             :     // POSIX style root directory.
     414     6511668 :     if (!has_net && is_separator((*b)[0], style)) {
     415     1482766 :       return *b;
     416             :     }
     417             :   }
     418             : 
     419             :   // No path or no root.
     420      827576 :   return StringRef();
     421             : }
     422             : 
     423     1466870 : StringRef relative_path(StringRef path, Style style) {
     424     1466870 :   StringRef root = root_path(path, style);
     425     1466999 :   return path.substr(root.size());
     426             : }
     427             : 
     428     5211533 : void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
     429             :             const Twine &b, const Twine &c, const Twine &d) {
     430             :   SmallString<32> a_storage;
     431             :   SmallString<32> b_storage;
     432             :   SmallString<32> c_storage;
     433             :   SmallString<32> d_storage;
     434             : 
     435             :   SmallVector<StringRef, 4> components;
     436     5210565 :   if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
     437      430394 :   if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
     438      381395 :   if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
     439      198738 :   if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
     440             : 
     441    17646982 :   for (auto &component : components) {
     442             :     bool path_has_sep =
     443    16614519 :         !path.empty() && is_separator(path[path.size() - 1], style);
     444             :     if (path_has_sep) {
     445             :       // Strip separators from beginning of component.
     446     1156225 :       size_t loc = component.find_first_not_of(separators(style));
     447             :       StringRef c = component.substr(loc);
     448             : 
     449             :       // Append it.
     450     1156238 :       path.append(c.begin(), c.end());
     451     1156293 :       continue;
     452             :     }
     453             : 
     454             :     bool component_has_sep =
     455    14140011 :         !component.empty() && is_separator(component[0], style);
     456     4749721 :     if (!component_has_sep &&
     457     8713583 :         !(path.empty() || has_root_name(component, style))) {
     458             :       // Add a separator.
     459     7925186 :       path.push_back(preferred_separator(style));
     460             :     }
     461             : 
     462     5063323 :     path.append(component.begin(), component.end());
     463             :   }
     464     5208234 : }
     465             : 
     466     1208734 : void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
     467             :             const Twine &c, const Twine &d) {
     468     1208734 :   append(path, Style::native, a, b, c, d);
     469     1208705 : }
     470             : 
     471          45 : void append(SmallVectorImpl<char> &path, const_iterator begin,
     472             :             const_iterator end, Style style) {
     473         561 :   for (; begin != end; ++begin)
     474         258 :     path::append(path, style, *begin);
     475          45 : }
     476             : 
     477      620934 : StringRef parent_path(StringRef path, Style style) {
     478      620934 :   size_t end_pos = parent_path_end(path, style);
     479      620932 :   if (end_pos == StringRef::npos)
     480           0 :     return StringRef();
     481             :   else
     482             :     return path.substr(0, end_pos);
     483             : }
     484             : 
     485       13196 : void remove_filename(SmallVectorImpl<char> &path, Style style) {
     486       13196 :   size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
     487       13196 :   if (end_pos != StringRef::npos)
     488             :     path.set_size(end_pos);
     489       13196 : }
     490             : 
     491        4799 : void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
     492             :                        Style style) {
     493             :   StringRef p(path.begin(), path.size());
     494             :   SmallString<32> ext_storage;
     495        4799 :   StringRef ext = extension.toStringRef(ext_storage);
     496             : 
     497             :   // Erase existing extension.
     498             :   size_t pos = p.find_last_of('.');
     499        4799 :   if (pos != StringRef::npos && pos >= filename_pos(p, style))
     500             :     path.set_size(pos);
     501             : 
     502             :   // Append '.' if needed.
     503        9164 :   if (ext.size() > 0 && ext[0] != '.')
     504        3982 :     path.push_back('.');
     505             : 
     506             :   // Append extension.
     507        4799 :   path.append(ext.begin(), ext.end());
     508        4799 : }
     509             : 
     510          19 : void replace_path_prefix(SmallVectorImpl<char> &Path,
     511             :                          const StringRef &OldPrefix, const StringRef &NewPrefix,
     512             :                          Style style) {
     513          20 :   if (OldPrefix.empty() && NewPrefix.empty())
     514           6 :     return;
     515             : 
     516             :   StringRef OrigPath(Path.begin(), Path.size());
     517             :   if (!OrigPath.startswith(OldPrefix))
     518             :     return;
     519             : 
     520             :   // If prefixes have the same size we can simply copy the new one over.
     521          16 :   if (OldPrefix.size() == NewPrefix.size()) {
     522             :     std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
     523             :     return;
     524             :   }
     525             : 
     526          13 :   StringRef RelPath = OrigPath.substr(OldPrefix.size());
     527             :   SmallString<256> NewPath;
     528          13 :   path::append(NewPath, style, NewPrefix);
     529          13 :   path::append(NewPath, style, RelPath);
     530          13 :   Path.swap(NewPath);
     531             : }
     532             : 
     533       37345 : void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
     534             :   assert((!path.isSingleStringRef() ||
     535             :           path.getSingleStringRef().data() != result.data()) &&
     536             :          "path and result are not allowed to overlap!");
     537             :   // Clear result.
     538             :   result.clear();
     539       37345 :   path.toVector(result);
     540       37345 :   native(result, style);
     541       37345 : }
     542             : 
     543       40304 : void native(SmallVectorImpl<char> &Path, Style style) {
     544       40304 :   if (Path.empty())
     545             :     return;
     546             :   if (real_style(style) == Style::windows) {
     547             :     std::replace(Path.begin(), Path.end(), '/', '\\');
     548         159 :     if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
     549             :       SmallString<128> PathHome;
     550           0 :       home_directory(PathHome);
     551           0 :       PathHome.append(Path.begin() + 1, Path.end());
     552           0 :       Path = PathHome;
     553             :     }
     554             :   } else {
     555     7143725 :     for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
     556     3551790 :       if (*PI == '\\') {
     557          20 :         auto PN = PI + 1;
     558          20 :         if (PN < PE && *PN == '\\')
     559             :           ++PI; // increment once, the for loop will move over the escaped slash
     560             :         else
     561          19 :           *PI = '/';
     562             :       }
     563             :     }
     564             :   }
     565             : }
     566             : 
     567         182 : std::string convert_to_slash(StringRef path, Style style) {
     568             :   if (real_style(style) != Style::windows)
     569             :     return path;
     570             : 
     571             :   std::string s = path.str();
     572             :   std::replace(s.begin(), s.end(), '\\', '/');
     573             :   return s;
     574             : }
     575             : 
     576     1428556 : StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
     577             : 
     578       47389 : StringRef stem(StringRef path, Style style) {
     579       47389 :   StringRef fname = filename(path, style);
     580             :   size_t pos = fname.find_last_of('.');
     581       47389 :   if (pos == StringRef::npos)
     582       43553 :     return fname;
     583             :   else
     584        7640 :     if ((fname.size() == 1 && fname == ".") ||
     585             :         (fname.size() == 2 && fname == ".."))
     586          40 :       return fname;
     587             :     else
     588             :       return fname.substr(0, pos);
     589             : }
     590             : 
     591       23082 : StringRef extension(StringRef path, Style style) {
     592       23082 :   StringRef fname = filename(path, style);
     593             :   size_t pos = fname.find_last_of('.');
     594       23082 :   if (pos == StringRef::npos)
     595        8088 :     return StringRef();
     596             :   else
     597       29943 :     if ((fname.size() == 1 && fname == ".") ||
     598             :         (fname.size() == 2 && fname == ".."))
     599          71 :       return StringRef();
     600             :     else
     601             :       return fname.substr(pos);
     602             : }
     603             : 
     604    68912180 : bool is_separator(char value, Style style) {
     605    68912180 :   if (value == '/')
     606             :     return true;
     607             :   if (real_style(style) == Style::windows)
     608         302 :     return value == '\\';
     609             :   return false;
     610             : }
     611             : 
     612       10952 : StringRef get_separator(Style style) {
     613             :   if (real_style(style) == Style::windows)
     614          12 :     return "\\";
     615       10940 :   return "/";
     616             : }
     617             : 
     618     3963857 : bool has_root_name(const Twine &path, Style style) {
     619             :   SmallString<128> path_storage;
     620     3963857 :   StringRef p = path.toStringRef(path_storage);
     621             : 
     622    11888243 :   return !root_name(p, style).empty();
     623             : }
     624             : 
     625     2132369 : bool has_root_directory(const Twine &path, Style style) {
     626             :   SmallString<128> path_storage;
     627     2132369 :   StringRef p = path.toStringRef(path_storage);
     628             : 
     629     6396793 :   return !root_directory(p, style).empty();
     630             : }
     631             : 
     632          40 : bool has_root_path(const Twine &path, Style style) {
     633             :   SmallString<128> path_storage;
     634          40 :   StringRef p = path.toStringRef(path_storage);
     635             : 
     636         120 :   return !root_path(p, style).empty();
     637             : }
     638             : 
     639           0 : bool has_relative_path(const Twine &path, Style style) {
     640             :   SmallString<128> path_storage;
     641           0 :   StringRef p = path.toStringRef(path_storage);
     642             : 
     643           0 :   return !relative_path(p, style).empty();
     644             : }
     645             : 
     646          40 : bool has_filename(const Twine &path, Style style) {
     647             :   SmallString<128> path_storage;
     648          40 :   StringRef p = path.toStringRef(path_storage);
     649             : 
     650         120 :   return !filename(p, style).empty();
     651             : }
     652             : 
     653         238 : bool has_parent_path(const Twine &path, Style style) {
     654             :   SmallString<128> path_storage;
     655         238 :   StringRef p = path.toStringRef(path_storage);
     656             : 
     657         714 :   return !parent_path(p, style).empty();
     658             : }
     659             : 
     660          52 : bool has_stem(const Twine &path, Style style) {
     661             :   SmallString<128> path_storage;
     662          52 :   StringRef p = path.toStringRef(path_storage);
     663             : 
     664         156 :   return !stem(p, style).empty();
     665             : }
     666             : 
     667         436 : bool has_extension(const Twine &path, Style style) {
     668             :   SmallString<128> path_storage;
     669         436 :   StringRef p = path.toStringRef(path_storage);
     670             : 
     671        1308 :   return !extension(p, style).empty();
     672             : }
     673             : 
     674     1943117 : bool is_absolute(const Twine &path, Style style) {
     675             :   SmallString<128> path_storage;
     676     1943117 :   StringRef p = path.toStringRef(path_storage);
     677             : 
     678     1943316 :   bool rootDir = has_root_directory(p, style);
     679             :   bool rootName =
     680           3 :       (real_style(style) != Style::windows) || has_root_name(p, style);
     681             : 
     682     3886184 :   return rootDir && rootName;
     683             : }
     684             : 
     685      118269 : bool is_relative(const Twine &path, Style style) {
     686      118269 :   return !is_absolute(path, style);
     687             : }
     688             : 
     689        3138 : StringRef remove_leading_dotslash(StringRef Path, Style style) {
     690             :   // Remove leading "./" (or ".//" or "././" etc.)
     691        6278 :   while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
     692          13 :     Path = Path.substr(2);
     693          43 :     while (Path.size() > 0 && is_separator(Path[0], style))
     694           6 :       Path = Path.substr(1);
     695             :   }
     696        3138 :   return Path;
     697             : }
     698             : 
     699     1110592 : static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
     700             :                                     Style style) {
     701             :   SmallVector<StringRef, 16> components;
     702             : 
     703             :   // Skip the root path, then look for traversal in the components.
     704     1110592 :   StringRef rel = path::relative_path(path, style);
     705     4580281 :   for (StringRef C :
     706     6801581 :        llvm::make_range(path::begin(rel, style), path::end(rel))) {
     707       38860 :     if (C == ".")
     708       38860 :       continue;
     709             :     // Leading ".." will remain in the path unless it's at the root.
     710     4541471 :     if (remove_dot_dot && C == "..") {
     711      541024 :       if (!components.empty() && components.back() != "..") {
     712             :         components.pop_back();
     713       89566 :         continue;
     714             :       }
     715      723771 :       if (path::is_absolute(path, style))
     716      361879 :         continue;
     717             :     }
     718     4090018 :     components.push_back(C);
     719             :   }
     720             : 
     721     1110658 :   SmallString<256> buffer = path::root_path(path, style);
     722     9110686 :   for (StringRef C : components)
     723     4000259 :     path::append(buffer, style, C);
     724     1110602 :   return buffer;
     725             : }
     726             : 
     727     1110609 : bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
     728             :                  Style style) {
     729             :   StringRef p(path.data(), path.size());
     730             : 
     731     1110609 :   SmallString<256> result = remove_dots(p, remove_dot_dot, style);
     732     1110597 :   if (result == path)
     733             :     return false;
     734             : 
     735      429702 :   path.swap(result);
     736      429720 :   return true;
     737             : }
     738             : 
     739             : } // end namespace path
     740             : 
     741             : namespace fs {
     742             : 
     743        7816 : std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
     744        7816 :   file_status Status;
     745        7816 :   std::error_code EC = status(Path, Status);
     746        7816 :   if (EC)
     747           0 :     return EC;
     748        7816 :   Result = Status.getUniqueID();
     749        7816 :   return std::error_code();
     750             : }
     751             : 
     752       12001 : std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
     753             :                                  SmallVectorImpl<char> &ResultPath,
     754             :                                  unsigned Mode, sys::fs::OpenFlags Flags) {
     755             :   return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
     756       12001 :                             Flags);
     757             : }
     758             : 
     759         160 : std::error_code createUniqueFile(const Twine &Model,
     760             :                                  SmallVectorImpl<char> &ResultPath) {
     761             :   int Dummy;
     762         160 :   return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
     763             : }
     764             : 
     765             : static std::error_code
     766        5084 : createTemporaryFile(const Twine &Model, int &ResultFD,
     767             :                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type,
     768             :                     sys::fs::OpenFlags Flags) {
     769             :   SmallString<128> Storage;
     770        5084 :   StringRef P = Model.toNullTerminatedStringRef(Storage);
     771             :   assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
     772             :          "Model must be a simple filename.");
     773             :   // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
     774             :   return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
     775       15255 :                             owner_read | owner_write, Type, Flags);
     776             : }
     777             : 
     778             : static std::error_code
     779        5084 : createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
     780             :                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type,
     781             :                     sys::fs::OpenFlags Flags = sys::fs::F_None) {
     782        5084 :   const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
     783        5085 :   return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
     784       10169 :                              Type, Flags);
     785             : }
     786             : 
     787         214 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     788             :                                     int &ResultFD,
     789             :                                     SmallVectorImpl<char> &ResultPath,
     790             :                                     sys::fs::OpenFlags Flags) {
     791             :   return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File,
     792         214 :                              Flags);
     793             : }
     794             : 
     795        4870 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     796             :                                     SmallVectorImpl<char> &ResultPath) {
     797             :   int Dummy;
     798        4870 :   return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
     799             : }
     800             : 
     801             : 
     802             : // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
     803             : // for consistency. We should try using mkdtemp.
     804          42 : std::error_code createUniqueDirectory(const Twine &Prefix,
     805             :                                       SmallVectorImpl<char> &ResultPath) {
     806             :   int Dummy;
     807          42 :   return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
     808          84 :                             true, 0, FS_Dir);
     809             : }
     810             : 
     811      189200 : static std::error_code make_absolute(const Twine &current_directory,
     812             :                                      SmallVectorImpl<char> &path,
     813             :                                      bool use_current_directory) {
     814             :   StringRef p(path.data(), path.size());
     815             : 
     816      189200 :   bool rootDirectory = path::has_root_directory(p);
     817             :   bool rootName =
     818             :       (real_style(Style::native) != Style::windows) || path::has_root_name(p);
     819             : 
     820             :   // Already absolute.
     821      189191 :   if (rootName && rootDirectory)
     822       11213 :     return std::error_code();
     823             : 
     824             :   // All of the following conditions will need the current directory.
     825             :   SmallString<128> current_dir;
     826      177978 :   if (use_current_directory)
     827      177627 :     current_directory.toVector(current_dir);
     828         351 :   else if (std::error_code ec = current_path(current_dir))
     829          13 :     return ec;
     830             : 
     831             :   // Relative path. Prepend the current directory.
     832             :   if (!rootName && !rootDirectory) {
     833             :     // Append path to the current directory.
     834             :     path::append(current_dir, p);
     835             :     // Set path to the result.
     836             :     path.swap(current_dir);
     837             :     return std::error_code();
     838             :   }
     839             : 
     840             :   if (!rootName && rootDirectory) {
     841             :     StringRef cdrn = path::root_name(current_dir);
     842             :     SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
     843             :     path::append(curDirRootName, p);
     844             :     // Set path to the result.
     845             :     path.swap(curDirRootName);
     846             :     return std::error_code();
     847             :   }
     848             : 
     849             :   if (rootName && !rootDirectory) {
     850      177973 :     StringRef pRootName      = path::root_name(p);
     851      177966 :     StringRef bRootDirectory = path::root_directory(current_dir);
     852      177979 :     StringRef bRelativePath  = path::relative_path(current_dir);
     853      177980 :     StringRef pRelativePath  = path::relative_path(p);
     854             : 
     855             :     SmallString<128> res;
     856      177984 :     path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
     857      177962 :     path.swap(res);
     858      177977 :     return std::error_code();
     859             :   }
     860             : 
     861             :   llvm_unreachable("All rootName and rootDirectory combinations should have "
     862             :                    "occurred above!");
     863             : }
     864             : 
     865      177723 : std::error_code make_absolute(const Twine &current_directory,
     866             :                               SmallVectorImpl<char> &path) {
     867      177723 :   return make_absolute(current_directory, path, true);
     868             : }
     869             : 
     870       11479 : std::error_code make_absolute(SmallVectorImpl<char> &path) {
     871       11479 :   return make_absolute(Twine(), path, false);
     872             : }
     873             : 
     874        2218 : std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
     875             :                                    perms Perms) {
     876             :   SmallString<128> PathStorage;
     877        2218 :   StringRef P = Path.toStringRef(PathStorage);
     878             : 
     879             :   // Be optimistic and try to create the directory
     880        4436 :   std::error_code EC = create_directory(P, IgnoreExisting, Perms);
     881             :   // If we succeeded, or had any error other than the parent not existing, just
     882             :   // return it.
     883             :   if (EC != errc::no_such_file_or_directory)
     884        1720 :     return EC;
     885             : 
     886             :   // We failed because of a no_such_file_or_directory, try to create the
     887             :   // parent.
     888         498 :   StringRef Parent = path::parent_path(P);
     889         498 :   if (Parent.empty())
     890           0 :     return EC;
     891             : 
     892         498 :   if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
     893           0 :       return EC;
     894             : 
     895         498 :   return create_directory(P, IgnoreExisting, Perms);
     896             : }
     897             : 
     898         309 : std::error_code copy_file(const Twine &From, const Twine &To) {
     899             :   int ReadFD, WriteFD;
     900         309 :   if (std::error_code EC = openFileForRead(From, ReadFD))
     901           4 :     return EC;
     902         305 :   if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
     903           0 :     close(ReadFD);
     904           0 :     return EC;
     905             :   }
     906             : 
     907             :   const size_t BufSize = 4096;
     908         305 :   char *Buf = new char[BufSize];
     909             :   int BytesRead = 0, BytesWritten = 0;
     910             :   for (;;) {
     911         631 :     BytesRead = read(ReadFD, Buf, BufSize);
     912         631 :     if (BytesRead <= 0)
     913             :       break;
     914         978 :     while (BytesRead) {
     915         326 :       BytesWritten = write(WriteFD, Buf, BytesRead);
     916         326 :       if (BytesWritten < 0)
     917             :         break;
     918         326 :       BytesRead -= BytesWritten;
     919             :     }
     920         326 :     if (BytesWritten < 0)
     921             :       break;
     922             :   }
     923         305 :   close(ReadFD);
     924         305 :   close(WriteFD);
     925         305 :   delete[] Buf;
     926             : 
     927         305 :   if (BytesRead < 0 || BytesWritten < 0)
     928           0 :     return std::error_code(errno, std::generic_category());
     929         305 :   return std::error_code();
     930             : }
     931             : 
     932           1 : ErrorOr<MD5::MD5Result> md5_contents(int FD) {
     933           1 :   MD5 Hash;
     934             : 
     935             :   constexpr size_t BufSize = 4096;
     936           1 :   std::vector<uint8_t> Buf(BufSize);
     937             :   int BytesRead = 0;
     938             :   for (;;) {
     939           3 :     BytesRead = read(FD, Buf.data(), BufSize);
     940           2 :     if (BytesRead <= 0)
     941             :       break;
     942           1 :     Hash.update(makeArrayRef(Buf.data(), BytesRead));
     943             :   }
     944             : 
     945           1 :   if (BytesRead < 0)
     946           0 :     return std::error_code(errno, std::generic_category());
     947             :   MD5::MD5Result Result;
     948           1 :   Hash.final(Result);
     949             :   return Result;
     950             : }
     951             : 
     952           0 : ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
     953             :   int FD;
     954           0 :   if (auto EC = openFileForRead(Path, FD))
     955           0 :     return EC;
     956             : 
     957           0 :   auto Result = md5_contents(FD);
     958           0 :   close(FD);
     959             :   return Result;
     960             : }
     961             : 
     962        4820 : bool exists(const basic_file_status &status) {
     963        4820 :   return status_known(status) && status.type() != file_type::file_not_found;
     964             : }
     965             : 
     966        4820 : bool status_known(const basic_file_status &s) {
     967        4820 :   return s.type() != file_type::status_error;
     968             : }
     969             : 
     970           0 : file_type get_file_type(const Twine &Path, bool Follow) {
     971           0 :   file_status st;
     972           0 :   if (status(Path, st, Follow))
     973             :     return file_type::status_error;
     974           0 :   return st.type();
     975             : }
     976             : 
     977        3136 : bool is_directory(const basic_file_status &status) {
     978        3136 :   return status.type() == file_type::directory_file;
     979             : }
     980             : 
     981        3155 : std::error_code is_directory(const Twine &path, bool &result) {
     982        3155 :   file_status st;
     983        3155 :   if (std::error_code ec = status(path, st))
     984         376 :     return ec;
     985        2779 :   result = is_directory(st);
     986        2779 :   return std::error_code();
     987             : }
     988             : 
     989        2916 : bool is_regular_file(const basic_file_status &status) {
     990        2916 :   return status.type() == file_type::regular_file;
     991             : }
     992             : 
     993        2866 : std::error_code is_regular_file(const Twine &path, bool &result) {
     994        2866 :   file_status st;
     995        2866 :   if (std::error_code ec = status(path, st))
     996        2130 :     return ec;
     997         736 :   result = is_regular_file(st);
     998         736 :   return std::error_code();
     999             : }
    1000             : 
    1001          65 : bool is_symlink_file(const basic_file_status &status) {
    1002          65 :   return status.type() == file_type::symlink_file;
    1003             : }
    1004             : 
    1005           0 : std::error_code is_symlink_file(const Twine &path, bool &result) {
    1006           0 :   file_status st;
    1007           0 :   if (std::error_code ec = status(path, st, false))
    1008           0 :     return ec;
    1009           0 :   result = is_symlink_file(st);
    1010           0 :   return std::error_code();
    1011             : }
    1012             : 
    1013           0 : bool is_other(const basic_file_status &status) {
    1014           0 :   return exists(status) &&
    1015           0 :          !is_regular_file(status) &&
    1016           0 :          !is_directory(status);
    1017             : }
    1018             : 
    1019           0 : std::error_code is_other(const Twine &Path, bool &Result) {
    1020           0 :   file_status FileStatus;
    1021           0 :   if (std::error_code EC = status(Path, FileStatus))
    1022           0 :     return EC;
    1023           0 :   Result = is_other(FileStatus);
    1024           0 :   return std::error_code();
    1025             : }
    1026             : 
    1027      162414 : void directory_entry::replace_filename(const Twine &filename,
    1028             :                                        basic_file_status st) {
    1029      324828 :   SmallString<128> path = path::parent_path(Path);
    1030      162414 :   path::append(path, filename);
    1031      324827 :   Path = path.str();
    1032      162414 :   Status = st;
    1033      162414 : }
    1034             : 
    1035          25 : ErrorOr<perms> getPermissions(const Twine &Path) {
    1036          25 :   file_status Status;
    1037          25 :   if (std::error_code EC = status(Path, Status))
    1038           0 :     return EC;
    1039             : 
    1040          25 :   return Status.permissions();
    1041             : }
    1042             : 
    1043             : } // end namespace fs
    1044             : } // end namespace sys
    1045             : } // end namespace llvm
    1046             : 
    1047             : // Include the truly platform-specific parts.
    1048             : #if defined(LLVM_ON_UNIX)
    1049             : #include "Unix/Path.inc"
    1050             : #endif
    1051             : #if defined(LLVM_ON_WIN32)
    1052             : #include "Windows/Path.inc"
    1053             : #endif
    1054             : 
    1055             : namespace llvm {
    1056             : namespace sys {
    1057             : namespace fs {
    1058       13176 : TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
    1059       43254 : TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
    1060       21627 : TempFile &TempFile::operator=(TempFile &&Other) {
    1061       21627 :   TmpName = std::move(Other.TmpName);
    1062       21627 :   FD = Other.FD;
    1063       21627 :   Other.Done = true;
    1064       21627 :   return *this;
    1065             : }
    1066             : 
    1067       56428 : TempFile::~TempFile() { assert(Done); }
    1068             : 
    1069        6272 : Error TempFile::discard() {
    1070        6272 :   Done = true;
    1071             :   std::error_code RemoveEC;
    1072             : // On windows closing will remove the file.
    1073             : #ifndef LLVM_ON_WIN32
    1074             :   // Always try to close and remove.
    1075        6272 :   if (!TmpName.empty()) {
    1076        7682 :     RemoveEC = fs::remove(TmpName);
    1077        3841 :     sys::DontRemoveFileOnSignal(TmpName);
    1078             :   }
    1079             : #endif
    1080             : 
    1081        6272 :   if (!RemoveEC)
    1082        6272 :     TmpName = "";
    1083             : 
    1084        6272 :   if (FD != -1 && close(FD) == -1) {
    1085           0 :     std::error_code EC = std::error_code(errno, std::generic_category());
    1086           0 :     return errorCodeToError(EC);
    1087             :   }
    1088        6272 :   FD = -1;
    1089             : 
    1090        6272 :   return errorCodeToError(RemoveEC);
    1091             : }
    1092             : 
    1093        2746 : Error TempFile::keep(const Twine &Name) {
    1094             :   assert(!Done);
    1095        2746 :   Done = true;
    1096             :   // Always try to close and rename.
    1097             : #ifdef LLVM_ON_WIN32
    1098             :   // If we cant't cancel the delete don't rename.
    1099             :   std::error_code RenameEC = cancelDeleteOnClose(FD);
    1100             :   if (!RenameEC)
    1101             :     RenameEC = rename_fd(FD, Name);
    1102             :   // If we can't rename, discard the temporary file.
    1103             :   if (RenameEC)
    1104             :     removeFD(FD);
    1105             : #else
    1106        5492 :   std::error_code RenameEC = fs::rename(TmpName, Name);
    1107             :   // If we can't rename, discard the temporary file.
    1108        2746 :   if (RenameEC)
    1109           0 :     remove(TmpName);
    1110        2746 :   sys::DontRemoveFileOnSignal(TmpName);
    1111             : #endif
    1112             : 
    1113        2746 :   if (!RenameEC)
    1114             :     TmpName = "";
    1115             : 
    1116        2746 :   if (close(FD) == -1) {
    1117           0 :     std::error_code EC(errno, std::generic_category());
    1118           0 :     return errorCodeToError(EC);
    1119             :   }
    1120        2746 :   FD = -1;
    1121             : 
    1122        2746 :   return errorCodeToError(RenameEC);
    1123             : }
    1124             : 
    1125           0 : Error TempFile::keep() {
    1126             :   assert(!Done);
    1127           0 :   Done = true;
    1128             : 
    1129             : #ifdef LLVM_ON_WIN32
    1130             :   if (std::error_code EC = cancelDeleteOnClose(FD))
    1131             :     return errorCodeToError(EC);
    1132             : #else
    1133           0 :   sys::DontRemoveFileOnSignal(TmpName);
    1134             : #endif
    1135             : 
    1136           0 :   TmpName = "";
    1137             : 
    1138           0 :   if (close(FD) == -1) {
    1139           0 :     std::error_code EC(errno, std::generic_category());
    1140           0 :     return errorCodeToError(EC);
    1141             :   }
    1142           0 :   FD = -1;
    1143             : 
    1144             :   return Error::success();
    1145             : }
    1146             : 
    1147        6606 : Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
    1148             :   int FD;
    1149             :   SmallString<128> ResultPath;
    1150        6606 :   if (std::error_code EC = createUniqueFile(Model, FD, ResultPath, Mode,
    1151        6606 :                                             sys::fs::F_RW | sys::fs::F_Delete))
    1152          36 :     return errorCodeToError(EC);
    1153             : 
    1154       19764 :   TempFile Ret(ResultPath, FD);
    1155             : #ifndef LLVM_ON_WIN32
    1156        6588 :   if (sys::RemoveFileOnSignal(ResultPath)) {
    1157             :     // Make sure we delete the file when RemoveFileOnSignal fails.
    1158           0 :     consumeError(Ret.discard());
    1159             :     std::error_code EC(errc::operation_not_permitted);
    1160           0 :     return errorCodeToError(EC);
    1161             :   }
    1162             : #endif
    1163             :   return std::move(Ret);
    1164             : }
    1165             : }
    1166             : 
    1167             : namespace path {
    1168             : 
    1169           4 : bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
    1170             :                           const Twine &Path2, const Twine &Path3) {
    1171           4 :   if (getUserCacheDir(Result)) {
    1172           4 :     append(Result, Path1, Path2, Path3);
    1173           4 :     return true;
    1174             :   }
    1175             :   return false;
    1176             : }
    1177             : 
    1178             : } // end namespace path
    1179             : } // end namsspace sys
    1180             : } // end namespace llvm

Generated by: LCOV version 1.13