[llvm] r375002 - [llvm-ar] Make paths case insensitive when on windows

Owen Reynolds via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 16 07:07:57 PDT 2019


Author: gbreynoo
Date: Wed Oct 16 07:07:57 2019
New Revision: 375002

URL: http://llvm.org/viewvc/llvm-project?rev=375002&view=rev
Log:
[llvm-ar] Make paths case insensitive when on windows

When on windows gnu-ar treats member names as case insensitive. This
commit implements the same behaviour.

Differential Revision: https://reviews.llvm.org/D68033

Added:
    llvm/trunk/test/tools/llvm-ar/Inputs/path-names.a
    llvm/trunk/test/tools/llvm-ar/non-windows-name-case.test
    llvm/trunk/test/tools/llvm-ar/path-names.test
    llvm/trunk/test/tools/llvm-ar/windows-name-case.test
Modified:
    llvm/trunk/docs/CommandGuide/llvm-ar.rst
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

Modified: llvm/trunk/docs/CommandGuide/llvm-ar.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-ar.rst?rev=375002&r1=375001&r2=375002&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-ar.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-ar.rst Wed Oct 16 07:07:57 2019
@@ -35,6 +35,12 @@ Here's where **llvm-ar** departs from pr
 
  Currently **llvm-ar** can read GNU and BSD long file names, but only writes
  archives with the GNU format.
+ 
+*Windows Paths*
+
+ When on Windows **llvm-ar** treats the names of archived *files* in the same
+ case sensitive manner as the operating system. When on a non-Windows machine
+ **llvm-ar** does not consider character case.
 
 OPTIONS
 -------

Added: llvm/trunk/test/tools/llvm-ar/Inputs/path-names.a
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/path-names.a?rev=375002&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/path-names.a (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/path-names.a Wed Oct 16 07:07:57 2019
@@ -0,0 +1,8 @@
+!<arch>
+//                                              22        `
+a/foo.txt/
+b/foo.txt/
+/0              0           0     0     644     8         `
+hello-a
+/11             0           0     0     644     8         `
+hello-b

Added: llvm/trunk/test/tools/llvm-ar/non-windows-name-case.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/non-windows-name-case.test?rev=375002&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/non-windows-name-case.test (added)
+++ llvm/trunk/test/tools/llvm-ar/non-windows-name-case.test Wed Oct 16 07:07:57 2019
@@ -0,0 +1,27 @@
+## Test that on windows, members are case insensitive.
+# UNSUPPORTED: system-windows
+
+# RUN: mkdir -p %t
+# RUN: rm -rf %t/lowerCase %t/UPPERCASE && mkdir %t/lowerCase %t/UPPERCASE
+# RUN: echo lowerCase > %t/lowerCase/file.txt
+# RUN: echo UPPERCASE > %t/UPPERCASE/FILE.TXT
+
+# RUN: rm -f %t/archive.a
+# RUN: llvm-ar rc %t/archive.a %t/lowerCase/file.txt
+# RUN: llvm-ar rc %t/archive.a %t/UPPERCASE/FILE.TXT
+# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=ARCHIVE
+
+# ARCHIVE: file.txt
+# ARCHIVE: FILE.TXT
+
+# RUN: rm -f %t/thin-archive.a
+# RUN: llvm-ar Trc %t/thin-archive.a %t/lowerCase/file.txt %t/UPPERCASE/FILE.TXT
+# RUN: llvm-ar dTP %t/thin-archive.a %t/uppercase/file.txt
+
+# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
+
+# RUN: llvm-ar dTP %t/thin-archive.a %t/LOWERCASE/FILE.TXT
+# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
+
+# THIN-ARCHIVE: [[PATH]]/lowerCase/file.txt
+# THIN-ARCHIVE: [[PATH]]/UPPERCASE/FILE.TXT

Added: llvm/trunk/test/tools/llvm-ar/path-names.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/path-names.test?rev=375002&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/path-names.test (added)
+++ llvm/trunk/test/tools/llvm-ar/path-names.test Wed Oct 16 07:07:57 2019
@@ -0,0 +1,9 @@
+RUN: llvm-ar t %S/Inputs/path-names.a | FileCheck %s --check-prefix=CONTENTS --implicit-check-not {{.}}
+CONTENTS: a/foo.txt
+CONTENTS-NEXT: b/foo.txt
+
+RUN: llvm-ar p %S/Inputs/path-names.a b/foo.txt | FileCheck %s --check-prefix=NO-FULL-PATH --implicit-check-not {{.}}
+NO-FULL-PATH: hello-a
+
+RUN: llvm-ar Pp %S/Inputs/path-names.a b/foo.txt | FileCheck %s --check-prefix=FULL-PATH --implicit-check-not {{.}}
+FULL-PATH: hello-b

Added: llvm/trunk/test/tools/llvm-ar/windows-name-case.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/windows-name-case.test?rev=375002&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/windows-name-case.test (added)
+++ llvm/trunk/test/tools/llvm-ar/windows-name-case.test Wed Oct 16 07:07:57 2019
@@ -0,0 +1,29 @@
+## Test that on windows, members are case insensitive.
+# REQUIRES: system-windows
+
+# RUN: mkdir -p %t
+# RUN: rm -rf %t/lowerCase %t/UPPERCASE && mkdir %t/lowerCase %t/UPPERCASE
+# RUN: echo lowerCase > %t/lowerCase/file.txt
+# RUN: echo UPPERCASE > %t/UPPERCASE/FILE.TXT
+
+# RUN: rm -f %t/archive.a
+# RUN: llvm-ar rc %t/archive.a %t/lowerCase/file.txt
+# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=LOWER --implicit-check-not=FILE.TXT
+# RUN: llvm-ar rc %t/archive.a %t/UPPERCASE/FILE.TXT
+# RUN: FileCheck %s -input-file=%t/archive.a --check-prefix=UPPER --implicit-check-not=file.txt
+
+# LOWER: file.txt
+# UPPER: FILE.TXT
+
+# RUN: rm -f %t/thin-archive.a
+# RUN: llvm-ar Trc %t/thin-archive.a %t/lowerCase/file.txt %t/UPPERCASE/FILE.txt
+# RUN: llvm-ar dTP %t/thin-archive.a %t/uppercase/file.txt
+
+# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=THIN-ARCHIVE -DPATH=%/t
+# THIN-ARCHIVE-NOT: [[PATH]]/UPPERCASE/FILE.TXT
+# THIN-ARCHIVE: [[PATH]]/lowerCase/file.txt
+
+# RUN: llvm-ar dTP %t/thin-archive.a %t/LOWERCASE/FILE.TXT
+# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=EMPTY --implicit-check-not {{.}}
+
+EMPTY: !<thin>

Modified: llvm/trunk/tools/llvm-ar/llvm-ar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-ar/llvm-ar.cpp?rev=375002&r1=375001&r2=375002&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Wed Oct 16 07:07:57 2019
@@ -43,6 +43,11 @@
 #include <io.h>
 #endif
 
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
 using namespace llvm;
 
 // The name this program was invoked as.
@@ -488,6 +493,23 @@ static std::string normalizePath(StringR
                          : std::string(sys::path::filename(Path));
 }
 
+static bool comparePaths(StringRef Path1, StringRef Path2) {
+// When on Windows this function calls CompareStringOrdinal
+// as Windows file paths are case-insensitive. 
+// CompareStringOrdinal compares two Unicode strings for
+// binary equivalence and allows for case insensitivity.
+#ifdef _WIN32
+  SmallVector<wchar_t, 128> WPath1, WPath2;
+  failIfError(sys::path::widenPath(normalizePath(Path1), WPath1));
+  failIfError(sys::path::widenPath(normalizePath(Path2), WPath2));
+
+  return CompareStringOrdinal(WPath1.data(), WPath1.size(), WPath2.data(),
+                              WPath2.size(), true) == CSTR_EQUAL;
+#else
+  return normalizePath(Path1) == normalizePath(Path2);
+#endif
+}
+
 // Implement the 'x' operation. This function extracts files back to the file
 // system.
 static void doExtract(StringRef Name, const object::Archive::Child &C) {
@@ -561,7 +583,7 @@ static void performReadOperation(Archive
 
       if (Filter) {
         auto I = find_if(Members, [Name](StringRef Path) {
-          return Name == normalizePath(Path);
+          return comparePaths(Name, Path);
         });
         if (I == Members.end())
           continue;
@@ -691,7 +713,7 @@ static InsertAction computeInsertAction(
   if (Operation == QuickAppend || Members.empty())
     return IA_AddOldMember;
   auto MI = find_if(
-      Members, [Name](StringRef Path) { return Name == normalizePath(Path); });
+      Members, [Name](StringRef Path) { return comparePaths(Name, Path); });
 
   if (MI == Members.end())
     return IA_AddOldMember;
@@ -742,15 +764,14 @@ computeNewArchiveMembers(ArchiveOperatio
   std::vector<NewArchiveMember> Moved;
   int InsertPos = -1;
   if (OldArchive) {
-    std::string PosName = normalizePath(RelPos);
     Error Err = Error::success();
     StringMap<int> MemberCount;
     for (auto &Child : OldArchive->children(Err)) {
       int Pos = Ret.size();
       Expected<StringRef> NameOrErr = Child.getName();
       failIfError(NameOrErr.takeError());
-      StringRef Name = NameOrErr.get();
-      if (Name == PosName) {
+      std::string Name = NameOrErr.get();
+      if (comparePaths(Name, RelPos)) {
         assert(AddAfter || AddBefore);
         if (AddBefore)
           InsertPos = Pos;
@@ -1018,9 +1039,9 @@ static void runMRIScript() {
       ArchiveName = Rest;
       break;
     case MRICommand::Delete: {
-      std::string Name = normalizePath(Rest);
-      llvm::erase_if(NewMembers,
-                     [=](NewArchiveMember &M) { return M.MemberName == Name; });
+      llvm::erase_if(NewMembers, [=](NewArchiveMember &M) {
+        return comparePaths(M.MemberName, Rest);
+      });
       break;
     }
     case MRICommand::Save:




More information about the llvm-commits mailing list