[llvm-ar][mri] Ensure CREATE commands overwrite the output file
authorBen Dunbobbin <Ben.Dunbobbin@sony.com>
Fri, 13 May 2022 22:37:16 +0000 (23:37 +0100)
committerBen Dunbobbin <Ben.Dunbobbin@sony.com>
Fri, 13 May 2022 22:50:10 +0000 (23:50 +0100)
The CREATE/CREATETHIN commands should overwrite the output file:
https://sourceware.org/binutils/docs/binutils/ar-scripts.html.

This fixes a regression for MRI scripts introduced in:
https://reviews.llvm.org/D123142 which put logic into
performWriteOperation. performWriteOperation is called for all MRI
commands that write an archive out (one's with a SAVE command).
performWriteOperation is unaware of MRI semantics and loads an
existing archive if present. If an existing archive is loaded, llvm-ar
checks the properties of the existing archive for decisions about the
output archive (for example making the output archive thin if the
existing one was). https://reviews.llvm.org/D123142 adds the following
logic...

if (OldArchive) {
  if (Thin && !OldArchive->isThin())
    fail("cannot convert a regular archive to a thin one");
  if (OldArchive->isThin())
    Thin = true;
}

... which errors for a script with CREATETHIN in effect if there is an
existing regular archive, and causes CREATE to output a thin archive
if there is an existing thin archive.

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

llvm/test/tools/llvm-ar/mri-create-overwrite.test [new file with mode: 0644]
llvm/tools/llvm-ar/llvm-ar.cpp

diff --git a/llvm/test/tools/llvm-ar/mri-create-overwrite.test b/llvm/test/tools/llvm-ar/mri-create-overwrite.test
new file mode 100644 (file)
index 0000000..3a43826
--- /dev/null
@@ -0,0 +1,70 @@
+## Show that CREATE/CREATETHIN overwrite existing files appropriately.
+
+# RUN: rm -rf %t
+# RUN: split-file %s %t
+# RUN: cd %t
+
+## Show that an existing file that is not an archive is overwritten by CREATE.
+# RUN: touch test.a
+# RUN: llvm-ar -M < create.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=ARCH,TWO
+
+## Show that an existing file that is not an archive is overwritten by CREATETHIN.
+# RUN: rm -f test.a
+# RUN: touch test.a
+# RUN: llvm-ar -M < createthin.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=THIN,TWO
+
+## Show that an existing regular archive is overwritten by CREATE.
+# RUN: rm -f test.a
+# RUN: llvm-ar cr test.a 1.txt
+# RUN: llvm-ar -M < create.mri
+# RUN: llvm-ar tv test.a
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=ARCH,TWO --implicit-check-not=1.txt
+
+## Show that an existing regular archive is overwritten by CREATETHIN.
+# RUN: rm -f test.a
+# RUN: llvm-ar cr test.a 1.txt
+# RUN: llvm-ar -M < createthin.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=THIN,TWO --implicit-check-not=1.txt
+
+## Show that an existing thin archive is overwritten by CREATE.
+# RUN: rm -f test.a
+# RUN: llvm-ar crT test.a 1.txt
+# RUN: llvm-ar -M < create.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=ARCH,TWO --implicit-check-not=1.txt
+
+## Show that an existing thin archive is overwritten by CREATETHIN.
+# RUN: rm -f test.a
+# RUN: llvm-ar crT test.a 1.txt
+# RUN: llvm-ar -M < createthin.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=THIN,TWO --implicit-check-not=1.txt
+
+## Show that the output is not overwritten without a SAVE.
+# RUN: rm -f test.a
+# RUN: llvm-ar crT test.a 1.txt
+# RUN: llvm-ar -M < nosave.mri
+# RUN: FileCheck --input-file=test.a %s --check-prefixes=THIN,ONE --implicit-check-not=2.txt
+
+# ARCH: !<arch>
+# THIN: !<thin>
+# ONE:  1.txt
+# TWO:  2.txt
+
+#--- 1.txt
+
+#--- 2.txt
+
+#--- create.mri
+CREATE test.a
+ADDMOD 2.txt
+SAVE
+
+#--- createthin.mri
+CREATETHIN test.a
+ADDMOD 2.txt
+SAVE
+
+#--- nosave.mri
+CREATE test.a
+ADDMOD 2.txt
index 3f6be71..22f6b86 100644 (file)
@@ -1138,7 +1138,8 @@ static void runMRIScript() {
 
   // Nothing to do if not saved.
   if (Saved)
-    performOperation(ReplaceOrInsert, &NewMembers);
+    performOperation(ReplaceOrInsert, /*OldArchive=*/nullptr,
+                     /*OldArchiveBuf=*/ nullptr, &NewMembers);
   exit(0);
 }