Skip to content

[SystemZ][z/OS] Refactor AutoConvert.h to remove large MVS guard #143174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 11, 2025

Conversation

abhina-sree
Copy link
Contributor

This AutoConvert.h header frequently gets mislabeled as an unused include because it is guarded by MVS internally and every usage is also guarded. This refactors the change to remove this guard and instead make these functions a noop on other non-z/OS platforms.

@abhina-sree abhina-sree self-assigned this Jun 6, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category llvm:support testing-tools labels Jun 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 6, 2025

@llvm/pr-subscribers-clang

Author: Abhina Sree (abhina-sree)

Changes

This AutoConvert.h header frequently gets mislabeled as an unused include because it is guarded by MVS internally and every usage is also guarded. This refactors the change to remove this guard and instead make these functions a noop on other non-z/OS platforms.


Full diff: https://github.com/llvm/llvm-project/pull/143174.diff

7 Files Affected:

  • (modified) clang/tools/c-index-test/c-index-test.c (+2-2)
  • (modified) llvm/include/llvm/Support/AutoConvert.h (+1-2)
  • (modified) llvm/lib/Support/AutoConvert.cpp (+24-7)
  • (modified) llvm/lib/Support/InitLLVM.cpp (+3-3)
  • (modified) llvm/lib/Support/MemoryBuffer.cpp (+3-6)
  • (modified) llvm/lib/Support/raw_ostream.cpp (+6-4)
  • (modified) llvm/utils/count/count.c (+4-2)
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 4a887cd0c1e2e..3922aa9c31386 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -5199,13 +5199,13 @@ static void flush_atexit(void) {
 int main(int argc, const char **argv) {
   thread_info client_data;
 
-#ifdef __MVS__
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdout)) == -1)
     fprintf(stderr, "Setting conversion on stdout failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stderr, "Setting conversion on stderr failed\n");
-#endif
 
   atexit(flush_atexit);
 
diff --git a/llvm/include/llvm/Support/AutoConvert.h b/llvm/include/llvm/Support/AutoConvert.h
index 352493e9be25f..7f8f6f96b4847 100644
--- a/llvm/include/llvm/Support/AutoConvert.h
+++ b/llvm/include/llvm/Support/AutoConvert.h
@@ -16,6 +16,7 @@
 
 #ifdef __MVS__
 #include <_Ccsid.h>
+#endif
 #ifdef __cplusplus
 #include "llvm/Support/ErrorOr.h"
 #include <system_error>
@@ -66,6 +67,4 @@ ErrorOr<bool> needzOSConversion(const char *FileName, const int FD = -1);
 } /* namespace llvm */
 #endif /* __cplusplus */
 
-#endif /* __MVS__ */
-
 #endif /* LLVM_SUPPORT_AUTOCONVERT_H */
diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp
index f7918548df1d0..3c82454f2a3ac 100644
--- a/llvm/lib/Support/AutoConvert.cpp
+++ b/llvm/lib/Support/AutoConvert.cpp
@@ -11,8 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifdef __MVS__
-
 #include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Error.h"
 #include <cassert>
@@ -25,6 +23,9 @@ using namespace llvm;
 static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
 
 int disablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   static const struct f_cnvrt Convert = {
       SETCVTOFF, // cvtcmd
       0,         // pccsid
@@ -32,9 +33,13 @@ int disablezOSAutoConversion(int FD) {
   };
 
   return fcntl(FD, F_CONTROL_CVT, &Convert);
+#endif
 }
 
 int restorezOSStdHandleAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
   if (savedStdHandleAutoConversionMode[FD] == -1)
     return 0;
@@ -44,9 +49,13 @@ int restorezOSStdHandleAutoConversion(int FD) {
       0,                                    // fccsid
   };
   return (fcntl(FD, F_CONTROL_CVT, &Cvt));
+#endif
 }
 
 int enablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   struct f_cnvrt Query = {
       QUERYCVT, // cvtcmd
       0,        // pccsid
@@ -81,30 +90,35 @@ int enablezOSAutoConversion(int FD) {
   // Assume untagged files to be IBM-1047 encoded.
   Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
   return fcntl(FD, F_CONTROL_CVT, &Query);
+#endif
 }
 
 std::error_code llvm::disablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::disablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::enablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::enablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::restorezOSStdHandleAutoConversion(int FD) {
+#ifdef __MVS__
   if (::restorezOSStdHandleAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
+#ifdef __MVS__
   assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
          "FT_UNTAGGED and FT_BINARY are not allowed for text files");
   struct file_tag Tag;
@@ -115,6 +129,7 @@ std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
 
   if (fcntl(FD, F_SETTAG, &Tag) == -1)
     return errnoAsErrorCode();
+#endif
   return std::error_code();
 }
 
@@ -138,6 +153,9 @@ ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) {
 }
 
 ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
+#ifndef __MVS__
+  return false;
+#else
   ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(FileName, FD);
   if (std::error_code EC = Ccsid.getError())
     return EC;
@@ -152,6 +170,5 @@ ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
   default:
     return true;
   }
+#endif
 }
-
-#endif //__MVS__
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 50f7a43cc34a7..f7b3838f9c9ad 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -20,6 +20,7 @@
 
 #ifdef __MVS__
 #include <unistd.h>
+#endif
 
 void CleanupStdHandles(void *Cookie) {
   llvm::raw_ostream *Outs = &llvm::outs(), *Errs = &llvm::errs();
@@ -29,7 +30,6 @@ void CleanupStdHandles(void *Cookie) {
   llvm::restorezOSStdHandleAutoConversion(STDOUT_FILENO);
   llvm::restorezOSStdHandleAutoConversion(STDERR_FILENO);
 }
-#endif
 
 using namespace llvm;
 using namespace llvm::sys;
@@ -41,10 +41,10 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
   assert(!Initialized && "InitLLVM was already initialized!");
   Initialized = true;
 #endif
-#ifdef __MVS__
+
   // Bring stdin/stdout/stderr into a known state.
   sys::AddSignalHandler(CleanupStdHandles, nullptr);
-#endif
+
   if (InstallPipeSignalExitHandler)
     // The pipe signal handler must be installed before any other handlers are
     // registered. This is because the Unix \ref RegisterHandlers function does
diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp
index e2044bcc4e4f0..ffa494d5d7727 100644
--- a/llvm/lib/Support/MemoryBuffer.cpp
+++ b/llvm/lib/Support/MemoryBuffer.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/Alignment.h"
+#include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -34,9 +35,7 @@
 #include <io.h>
 #endif
 
-#ifdef __MVS__
-#include "llvm/Support/AutoConvert.h"
-#endif
+
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -507,7 +506,6 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
       return std::move(Result);
   }
 
-#ifdef __MVS__
   ErrorOr<bool> NeedConversion = needzOSConversion(Filename.str().c_str(), FD);
   if (std::error_code EC = NeedConversion.getError())
     return EC;
@@ -516,9 +514,8 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
   // off the stream.
   // Note: This only works with the assumption of reading a full file (i.e,
   // Offset == 0 and MapSize == FileSize). Reading a file slice does not work.
-  if (Offset == 0 && MapSize == FileSize && *NeedConversion)
+  if (*NeedConversion && Offset == 0 && MapSize == FileSize)
     return getMemoryBufferForStream(FD, Filename);
-#endif
 
   auto Buf =
       WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename, Alignment);
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 16631a63d1921..129723dd11653 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -894,10 +894,11 @@ void raw_fd_ostream::anchor() {}
 raw_fd_ostream &llvm::outs() {
   // Set buffer settings to model stdout behavior.
   std::error_code EC;
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   EC = enablezOSAutoConversion(STDOUT_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S("-", EC, sys::fs::OF_None);
   assert(!EC);
   return S;
@@ -905,10 +906,11 @@ raw_fd_ostream &llvm::outs() {
 
 raw_fd_ostream &llvm::errs() {
   // Set standard error to be unbuffered.
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   std::error_code EC = enablezOSAutoConversion(STDERR_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S(STDERR_FILENO, false, true);
   return S;
 }
diff --git a/llvm/utils/count/count.c b/llvm/utils/count/count.c
index 9166145fcc10a..a1faa3a642284 100644
--- a/llvm/utils/count/count.c
+++ b/llvm/utils/count/count.c
@@ -11,13 +11,15 @@
 #include <stdlib.h>
 
 int main(int argc, char **argv) {
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdin)) == -1)
     fprintf(stderr, "Setting conversion on stdin failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stdout, "Setting conversion on stderr failed\n");
-#endif
+
   size_t Count, NumLines, NumRead;
   char Buffer[4096], *End;
 

@llvmbot
Copy link
Member

llvmbot commented Jun 6, 2025

@llvm/pr-subscribers-llvm-support

Author: Abhina Sree (abhina-sree)

Changes

This AutoConvert.h header frequently gets mislabeled as an unused include because it is guarded by MVS internally and every usage is also guarded. This refactors the change to remove this guard and instead make these functions a noop on other non-z/OS platforms.


Full diff: https://github.com/llvm/llvm-project/pull/143174.diff

7 Files Affected:

  • (modified) clang/tools/c-index-test/c-index-test.c (+2-2)
  • (modified) llvm/include/llvm/Support/AutoConvert.h (+1-2)
  • (modified) llvm/lib/Support/AutoConvert.cpp (+24-7)
  • (modified) llvm/lib/Support/InitLLVM.cpp (+3-3)
  • (modified) llvm/lib/Support/MemoryBuffer.cpp (+3-6)
  • (modified) llvm/lib/Support/raw_ostream.cpp (+6-4)
  • (modified) llvm/utils/count/count.c (+4-2)
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 4a887cd0c1e2e..3922aa9c31386 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -5199,13 +5199,13 @@ static void flush_atexit(void) {
 int main(int argc, const char **argv) {
   thread_info client_data;
 
-#ifdef __MVS__
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdout)) == -1)
     fprintf(stderr, "Setting conversion on stdout failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stderr, "Setting conversion on stderr failed\n");
-#endif
 
   atexit(flush_atexit);
 
diff --git a/llvm/include/llvm/Support/AutoConvert.h b/llvm/include/llvm/Support/AutoConvert.h
index 352493e9be25f..7f8f6f96b4847 100644
--- a/llvm/include/llvm/Support/AutoConvert.h
+++ b/llvm/include/llvm/Support/AutoConvert.h
@@ -16,6 +16,7 @@
 
 #ifdef __MVS__
 #include <_Ccsid.h>
+#endif
 #ifdef __cplusplus
 #include "llvm/Support/ErrorOr.h"
 #include <system_error>
@@ -66,6 +67,4 @@ ErrorOr<bool> needzOSConversion(const char *FileName, const int FD = -1);
 } /* namespace llvm */
 #endif /* __cplusplus */
 
-#endif /* __MVS__ */
-
 #endif /* LLVM_SUPPORT_AUTOCONVERT_H */
diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp
index f7918548df1d0..3c82454f2a3ac 100644
--- a/llvm/lib/Support/AutoConvert.cpp
+++ b/llvm/lib/Support/AutoConvert.cpp
@@ -11,8 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifdef __MVS__
-
 #include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Error.h"
 #include <cassert>
@@ -25,6 +23,9 @@ using namespace llvm;
 static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
 
 int disablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   static const struct f_cnvrt Convert = {
       SETCVTOFF, // cvtcmd
       0,         // pccsid
@@ -32,9 +33,13 @@ int disablezOSAutoConversion(int FD) {
   };
 
   return fcntl(FD, F_CONTROL_CVT, &Convert);
+#endif
 }
 
 int restorezOSStdHandleAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
   if (savedStdHandleAutoConversionMode[FD] == -1)
     return 0;
@@ -44,9 +49,13 @@ int restorezOSStdHandleAutoConversion(int FD) {
       0,                                    // fccsid
   };
   return (fcntl(FD, F_CONTROL_CVT, &Cvt));
+#endif
 }
 
 int enablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   struct f_cnvrt Query = {
       QUERYCVT, // cvtcmd
       0,        // pccsid
@@ -81,30 +90,35 @@ int enablezOSAutoConversion(int FD) {
   // Assume untagged files to be IBM-1047 encoded.
   Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
   return fcntl(FD, F_CONTROL_CVT, &Query);
+#endif
 }
 
 std::error_code llvm::disablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::disablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::enablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::enablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::restorezOSStdHandleAutoConversion(int FD) {
+#ifdef __MVS__
   if (::restorezOSStdHandleAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
+#ifdef __MVS__
   assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
          "FT_UNTAGGED and FT_BINARY are not allowed for text files");
   struct file_tag Tag;
@@ -115,6 +129,7 @@ std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
 
   if (fcntl(FD, F_SETTAG, &Tag) == -1)
     return errnoAsErrorCode();
+#endif
   return std::error_code();
 }
 
@@ -138,6 +153,9 @@ ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) {
 }
 
 ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
+#ifndef __MVS__
+  return false;
+#else
   ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(FileName, FD);
   if (std::error_code EC = Ccsid.getError())
     return EC;
@@ -152,6 +170,5 @@ ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
   default:
     return true;
   }
+#endif
 }
-
-#endif //__MVS__
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 50f7a43cc34a7..f7b3838f9c9ad 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -20,6 +20,7 @@
 
 #ifdef __MVS__
 #include <unistd.h>
+#endif
 
 void CleanupStdHandles(void *Cookie) {
   llvm::raw_ostream *Outs = &llvm::outs(), *Errs = &llvm::errs();
@@ -29,7 +30,6 @@ void CleanupStdHandles(void *Cookie) {
   llvm::restorezOSStdHandleAutoConversion(STDOUT_FILENO);
   llvm::restorezOSStdHandleAutoConversion(STDERR_FILENO);
 }
-#endif
 
 using namespace llvm;
 using namespace llvm::sys;
@@ -41,10 +41,10 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
   assert(!Initialized && "InitLLVM was already initialized!");
   Initialized = true;
 #endif
-#ifdef __MVS__
+
   // Bring stdin/stdout/stderr into a known state.
   sys::AddSignalHandler(CleanupStdHandles, nullptr);
-#endif
+
   if (InstallPipeSignalExitHandler)
     // The pipe signal handler must be installed before any other handlers are
     // registered. This is because the Unix \ref RegisterHandlers function does
diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp
index e2044bcc4e4f0..ffa494d5d7727 100644
--- a/llvm/lib/Support/MemoryBuffer.cpp
+++ b/llvm/lib/Support/MemoryBuffer.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/Alignment.h"
+#include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -34,9 +35,7 @@
 #include <io.h>
 #endif
 
-#ifdef __MVS__
-#include "llvm/Support/AutoConvert.h"
-#endif
+
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -507,7 +506,6 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
       return std::move(Result);
   }
 
-#ifdef __MVS__
   ErrorOr<bool> NeedConversion = needzOSConversion(Filename.str().c_str(), FD);
   if (std::error_code EC = NeedConversion.getError())
     return EC;
@@ -516,9 +514,8 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
   // off the stream.
   // Note: This only works with the assumption of reading a full file (i.e,
   // Offset == 0 and MapSize == FileSize). Reading a file slice does not work.
-  if (Offset == 0 && MapSize == FileSize && *NeedConversion)
+  if (*NeedConversion && Offset == 0 && MapSize == FileSize)
     return getMemoryBufferForStream(FD, Filename);
-#endif
 
   auto Buf =
       WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename, Alignment);
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 16631a63d1921..129723dd11653 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -894,10 +894,11 @@ void raw_fd_ostream::anchor() {}
 raw_fd_ostream &llvm::outs() {
   // Set buffer settings to model stdout behavior.
   std::error_code EC;
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   EC = enablezOSAutoConversion(STDOUT_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S("-", EC, sys::fs::OF_None);
   assert(!EC);
   return S;
@@ -905,10 +906,11 @@ raw_fd_ostream &llvm::outs() {
 
 raw_fd_ostream &llvm::errs() {
   // Set standard error to be unbuffered.
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   std::error_code EC = enablezOSAutoConversion(STDERR_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S(STDERR_FILENO, false, true);
   return S;
 }
diff --git a/llvm/utils/count/count.c b/llvm/utils/count/count.c
index 9166145fcc10a..a1faa3a642284 100644
--- a/llvm/utils/count/count.c
+++ b/llvm/utils/count/count.c
@@ -11,13 +11,15 @@
 #include <stdlib.h>
 
 int main(int argc, char **argv) {
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdin)) == -1)
     fprintf(stderr, "Setting conversion on stdin failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stdout, "Setting conversion on stderr failed\n");
-#endif
+
   size_t Count, NumLines, NumRead;
   char Buffer[4096], *End;
 

@llvmbot
Copy link
Member

llvmbot commented Jun 6, 2025

@llvm/pr-subscribers-testing-tools

Author: Abhina Sree (abhina-sree)

Changes

This AutoConvert.h header frequently gets mislabeled as an unused include because it is guarded by MVS internally and every usage is also guarded. This refactors the change to remove this guard and instead make these functions a noop on other non-z/OS platforms.


Full diff: https://github.com/llvm/llvm-project/pull/143174.diff

7 Files Affected:

  • (modified) clang/tools/c-index-test/c-index-test.c (+2-2)
  • (modified) llvm/include/llvm/Support/AutoConvert.h (+1-2)
  • (modified) llvm/lib/Support/AutoConvert.cpp (+24-7)
  • (modified) llvm/lib/Support/InitLLVM.cpp (+3-3)
  • (modified) llvm/lib/Support/MemoryBuffer.cpp (+3-6)
  • (modified) llvm/lib/Support/raw_ostream.cpp (+6-4)
  • (modified) llvm/utils/count/count.c (+4-2)
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 4a887cd0c1e2e..3922aa9c31386 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -5199,13 +5199,13 @@ static void flush_atexit(void) {
 int main(int argc, const char **argv) {
   thread_info client_data;
 
-#ifdef __MVS__
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdout)) == -1)
     fprintf(stderr, "Setting conversion on stdout failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stderr, "Setting conversion on stderr failed\n");
-#endif
 
   atexit(flush_atexit);
 
diff --git a/llvm/include/llvm/Support/AutoConvert.h b/llvm/include/llvm/Support/AutoConvert.h
index 352493e9be25f..7f8f6f96b4847 100644
--- a/llvm/include/llvm/Support/AutoConvert.h
+++ b/llvm/include/llvm/Support/AutoConvert.h
@@ -16,6 +16,7 @@
 
 #ifdef __MVS__
 #include <_Ccsid.h>
+#endif
 #ifdef __cplusplus
 #include "llvm/Support/ErrorOr.h"
 #include <system_error>
@@ -66,6 +67,4 @@ ErrorOr<bool> needzOSConversion(const char *FileName, const int FD = -1);
 } /* namespace llvm */
 #endif /* __cplusplus */
 
-#endif /* __MVS__ */
-
 #endif /* LLVM_SUPPORT_AUTOCONVERT_H */
diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp
index f7918548df1d0..3c82454f2a3ac 100644
--- a/llvm/lib/Support/AutoConvert.cpp
+++ b/llvm/lib/Support/AutoConvert.cpp
@@ -11,8 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifdef __MVS__
-
 #include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Error.h"
 #include <cassert>
@@ -25,6 +23,9 @@ using namespace llvm;
 static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1};
 
 int disablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   static const struct f_cnvrt Convert = {
       SETCVTOFF, // cvtcmd
       0,         // pccsid
@@ -32,9 +33,13 @@ int disablezOSAutoConversion(int FD) {
   };
 
   return fcntl(FD, F_CONTROL_CVT, &Convert);
+#endif
 }
 
 int restorezOSStdHandleAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO);
   if (savedStdHandleAutoConversionMode[FD] == -1)
     return 0;
@@ -44,9 +49,13 @@ int restorezOSStdHandleAutoConversion(int FD) {
       0,                                    // fccsid
   };
   return (fcntl(FD, F_CONTROL_CVT, &Cvt));
+#endif
 }
 
 int enablezOSAutoConversion(int FD) {
+#ifndef __MVS__
+  return 0;
+#else
   struct f_cnvrt Query = {
       QUERYCVT, // cvtcmd
       0,        // pccsid
@@ -81,30 +90,35 @@ int enablezOSAutoConversion(int FD) {
   // Assume untagged files to be IBM-1047 encoded.
   Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid;
   return fcntl(FD, F_CONTROL_CVT, &Query);
+#endif
 }
 
 std::error_code llvm::disablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::disablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::enablezOSAutoConversion(int FD) {
+#ifdef __MVS__
   if (::enablezOSAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::restorezOSStdHandleAutoConversion(int FD) {
+#ifdef __MVS__
   if (::restorezOSStdHandleAutoConversion(FD) == -1)
     return errnoAsErrorCode();
-
+#endif
   return std::error_code();
 }
 
 std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
+#ifdef __MVS__
   assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) &&
          "FT_UNTAGGED and FT_BINARY are not allowed for text files");
   struct file_tag Tag;
@@ -115,6 +129,7 @@ std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
 
   if (fcntl(FD, F_SETTAG, &Tag) == -1)
     return errnoAsErrorCode();
+#endif
   return std::error_code();
 }
 
@@ -138,6 +153,9 @@ ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) {
 }
 
 ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
+#ifndef __MVS__
+  return false;
+#else
   ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(FileName, FD);
   if (std::error_code EC = Ccsid.getError())
     return EC;
@@ -152,6 +170,5 @@ ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) {
   default:
     return true;
   }
+#endif
 }
-
-#endif //__MVS__
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 50f7a43cc34a7..f7b3838f9c9ad 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -20,6 +20,7 @@
 
 #ifdef __MVS__
 #include <unistd.h>
+#endif
 
 void CleanupStdHandles(void *Cookie) {
   llvm::raw_ostream *Outs = &llvm::outs(), *Errs = &llvm::errs();
@@ -29,7 +30,6 @@ void CleanupStdHandles(void *Cookie) {
   llvm::restorezOSStdHandleAutoConversion(STDOUT_FILENO);
   llvm::restorezOSStdHandleAutoConversion(STDERR_FILENO);
 }
-#endif
 
 using namespace llvm;
 using namespace llvm::sys;
@@ -41,10 +41,10 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
   assert(!Initialized && "InitLLVM was already initialized!");
   Initialized = true;
 #endif
-#ifdef __MVS__
+
   // Bring stdin/stdout/stderr into a known state.
   sys::AddSignalHandler(CleanupStdHandles, nullptr);
-#endif
+
   if (InstallPipeSignalExitHandler)
     // The pipe signal handler must be installed before any other handlers are
     // registered. This is because the Unix \ref RegisterHandlers function does
diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp
index e2044bcc4e4f0..ffa494d5d7727 100644
--- a/llvm/lib/Support/MemoryBuffer.cpp
+++ b/llvm/lib/Support/MemoryBuffer.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/Alignment.h"
+#include "llvm/Support/AutoConvert.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -34,9 +35,7 @@
 #include <io.h>
 #endif
 
-#ifdef __MVS__
-#include "llvm/Support/AutoConvert.h"
-#endif
+
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -507,7 +506,6 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
       return std::move(Result);
   }
 
-#ifdef __MVS__
   ErrorOr<bool> NeedConversion = needzOSConversion(Filename.str().c_str(), FD);
   if (std::error_code EC = NeedConversion.getError())
     return EC;
@@ -516,9 +514,8 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
   // off the stream.
   // Note: This only works with the assumption of reading a full file (i.e,
   // Offset == 0 and MapSize == FileSize). Reading a file slice does not work.
-  if (Offset == 0 && MapSize == FileSize && *NeedConversion)
+  if (*NeedConversion && Offset == 0 && MapSize == FileSize)
     return getMemoryBufferForStream(FD, Filename);
-#endif
 
   auto Buf =
       WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename, Alignment);
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 16631a63d1921..129723dd11653 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -894,10 +894,11 @@ void raw_fd_ostream::anchor() {}
 raw_fd_ostream &llvm::outs() {
   // Set buffer settings to model stdout behavior.
   std::error_code EC;
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   EC = enablezOSAutoConversion(STDOUT_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S("-", EC, sys::fs::OF_None);
   assert(!EC);
   return S;
@@ -905,10 +906,11 @@ raw_fd_ostream &llvm::outs() {
 
 raw_fd_ostream &llvm::errs() {
   // Set standard error to be unbuffered.
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   std::error_code EC = enablezOSAutoConversion(STDERR_FILENO);
   assert(!EC);
-#endif
+
   static raw_fd_ostream S(STDERR_FILENO, false, true);
   return S;
 }
diff --git a/llvm/utils/count/count.c b/llvm/utils/count/count.c
index 9166145fcc10a..a1faa3a642284 100644
--- a/llvm/utils/count/count.c
+++ b/llvm/utils/count/count.c
@@ -11,13 +11,15 @@
 #include <stdlib.h>
 
 int main(int argc, char **argv) {
-#ifdef __MVS__
+
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stdin)) == -1)
     fprintf(stderr, "Setting conversion on stdin failed\n");
 
+  // On z/OS we need to enable auto conversion
   if (enablezOSAutoConversion(fileno(stderr)) == -1)
     fprintf(stdout, "Setting conversion on stderr failed\n");
-#endif
+
   size_t Count, NumLines, NumRead;
   char Buffer[4096], *End;
 

@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch from ae10555 to 101542e Compare June 6, 2025 17:19
@abhina-sree abhina-sree changed the title [SystemZ][z/OS] Refactor AutoConvert.h to remove MVS guard [SystemZ][z/OS] Refactor AutoConvert.h to remove large MVS guard Jun 6, 2025
Copy link

github-actions bot commented Jun 6, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch 7 times, most recently from cedf7e2 to adae2d2 Compare June 9, 2025 13:15
Comment on lines 29 to 37
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to define these here, shouldn't they be defined in unistd.h? Or is that header not available on all platforms?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving these to InitLLVM.cpp & raw_ostream.cpp. They should bechecked/ defined after unistd.h is included or we could get into a timing problem defining them here.

Another option is to change the code to use fileno(stderr) instead of STDERR_FILENO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Windows CI was failing because it did not have that header, I think. they have io.h which is equivalent

Comment on lines 29 to 37
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving these to InitLLVM.cpp & raw_ostream.cpp. They should bechecked/ defined after unistd.h is included or we could get into a timing problem defining them here.

Another option is to change the code to use fileno(stderr) instead of STDERR_FILENO.

@@ -516,7 +514,7 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
// off the stream.
// Note: This only works with the assumption of reading a full file (i.e,
// Offset == 0 and MapSize == FileSize). Reading a file slice does not work.
if (Offset == 0 && MapSize == FileSize && *NeedConversion)
if (*NeedConversion && Offset == 0 && MapSize == FileSize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the original code ... what happens if you need conversion but you're not reading a full file? If that should never happen we should have an assert.

@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch from adae2d2 to eedc956 Compare June 9, 2025 19:01
@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch from eedc956 to 65c363f Compare June 9, 2025 19:05
@@ -28,16 +29,55 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

int enablezOSAutoConversion(int FD);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are these C variations of the functions handled? Do we declare macros for enableAutoConversion() if not c++ and expand that to enablezOSAutoConversion() for MVS? And how does this integrate with the c++ inline functions? It might be the inline functions for c++ call these extern "C" functions for z/OS instead of having the z/OS function in the llvm namespace that returns std::error_code.

Copy link
Contributor Author

@abhina-sree abhina-sree Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left those guarded for now, I checked the usages and the headers were not removed from those files since being added so it's not as urgent to refactor those. The C++ functions are calling the C functions under the covers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you simplify the functions some so that the general inline functions for C++ that return std::error_code call the z/OS functions for C that return an int. I was thinking:

std::error_code llvm::enableAutoConversion(int FD) {
#ifdef __MVS__
  if (::enablezOSAutoConversion(FD) == -1)
    return errnoAsErrorCode();
#endif

  return std::error_code();
}

This would eliminate the extra z/OS functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is done in the latest commit

@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch 2 times, most recently from 1c49b62 to 731a441 Compare June 11, 2025 17:37
Copy link
Contributor

@perry-ca perry-ca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@abhina-sree abhina-sree force-pushed the abhina/refactor_autoconvert branch from 731a441 to 47357b1 Compare June 11, 2025 17:47
@abhina-sree abhina-sree merged commit 22fd11f into llvm:main Jun 11, 2025
7 checks passed
@abhina-sree abhina-sree deleted the abhina/refactor_autoconvert branch June 11, 2025 19:26
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
…m#143174)

This AutoConvert.h header frequently gets mislabeled as an unused
include because it is guarded by MVS internally and every usage is also
guarded. This refactors the change to remove this guard and instead make
these functions a noop on other non-z/OS platforms.
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
…m#143174)

This AutoConvert.h header frequently gets mislabeled as an unused
include because it is guarded by MVS internally and every usage is also
guarded. This refactors the change to remove this guard and instead make
these functions a noop on other non-z/OS platforms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category llvm:support testing-tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants