sepavloff updated this revision to Diff 458216.
sepavloff added a comment.

Change help message


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133325/new/

https://reviews.llvm.org/D133325

Files:
  clang/docs/UsersManual.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/Inputs/config/config-3.cfg
  clang/test/Driver/config-file.c
  clang/unittests/Driver/ToolChainTest.cpp
  llvm/include/llvm/Support/CommandLine.h
  llvm/lib/Support/CommandLine.cpp

Index: llvm/lib/Support/CommandLine.cpp
===================================================================
--- llvm/lib/Support/CommandLine.cpp
+++ llvm/lib/Support/CommandLine.cpp
@@ -1184,6 +1184,15 @@
 
   if (!RelativeNames)
     return Error::success();
+
+  if (InConfigFile) {
+    if (std::find_if(NewArgv.begin(), NewArgv.end(),
+                     [](const char *Arg) -> bool {
+                       return StringRef("--search-config-dirs") == Arg;
+                     }) != NewArgv.end())
+      setSearchAsConfig(true);
+  }
+
   llvm::StringRef BasePath = llvm::sys::path::parent_path(FName);
   // If names of nested response files should be resolved relative to including
   // file, replace the included response file names with their full paths
@@ -1207,8 +1216,17 @@
 
     SmallString<128> ResponseFile;
     ResponseFile.push_back('@');
-    ResponseFile.append(BasePath);
-    llvm::sys::path::append(ResponseFile, FileName);
+    if (SearchAsConfig) {
+      std::string FilePath;
+      if (!findConfigFile(FileName, FilePath))
+        return llvm::createStringError(
+            std::make_error_code(std::errc::no_such_file_or_directory),
+            "Could not find config file: " + FileName);
+      ResponseFile.append(FilePath);
+    } else {
+      ResponseFile.append(BasePath);
+      llvm::sys::path::append(ResponseFile, FileName);
+    }
     Arg = Saver.save(ResponseFile.str()).data();
   }
   return Error::success();
@@ -1350,15 +1368,48 @@
                                    llvm::vfs::FileSystem *FS)
     : Saver(S), Tokenizer(T), FS(FS ? FS : vfs::getRealFileSystem().get()) {}
 
-bool ExpansionContext::readConfigFile(StringRef CfgFile,
-                                      SmallVectorImpl<const char *> &Argv) {
-  SmallString<128> AbsPath;
-  if (sys::path::is_relative(CfgFile)) {
-    AbsPath.assign(CfgFile);
-    if (std::error_code EC = FS->makeAbsolute(AbsPath))
+bool ExpansionContext::findConfigFile(StringRef FileName,
+                                      std::string &FilePath) {
+  SmallString<128> CfgFilePath;
+  const auto FileExists = [this](SmallString<128> Path) -> bool {
+    auto Status = FS->status(Path);
+    return Status &&
+           Status->getType() == llvm::sys::fs::file_type::regular_file;
+  };
+
+  // If file name contains directory separator, treat it as a path to
+  // configuration file.
+  if (llvm::sys::path::has_parent_path(FileName)) {
+    CfgFilePath = FileName;
+    if (llvm::sys::path::is_relative(FileName)) {
+      if (FS->makeAbsolute(CfgFilePath))
+        return false;
+    }
+    if (!FileExists(CfgFilePath))
       return false;
-    CfgFile = AbsPath.str();
+    FilePath = CfgFilePath.str();
+    return true;
+  }
+
+  // Look for the file in search directories.
+  for (const StringRef &Dir : SearchDirs) {
+    if (Dir.empty())
+      continue;
+    CfgFilePath.assign(Dir);
+    llvm::sys::path::append(CfgFilePath, FileName);
+    llvm::sys::path::native(CfgFilePath);
+    if (FileExists(CfgFilePath)) {
+      FilePath = CfgFilePath.str();
+      return true;
+    }
   }
+
+  return false;
+}
+
+bool ExpansionContext::readConfigFile(StringRef CfgFile,
+                                      SmallVectorImpl<const char *> &Argv) {
+  assert(llvm::sys::path::is_absolute(CfgFile));
   InConfigFile = true;
   RelativeNames = true;
   if (llvm::Error Err = expandResponseFile(CfgFile, Argv)) {
Index: llvm/include/llvm/Support/CommandLine.h
===================================================================
--- llvm/include/llvm/Support/CommandLine.h
+++ llvm/include/llvm/Support/CommandLine.h
@@ -2080,6 +2080,9 @@
   /// used instead.
   StringRef CurrentDir;
 
+  /// Directories used for search of config files.
+  ArrayRef<StringRef> SearchDirs;
+
   /// True if names of nested response files must be resolved relative to
   /// including file.
   bool RelativeNames = false;
@@ -2091,6 +2094,10 @@
   /// If true, body of config file is expanded.
   bool InConfigFile = false;
 
+  /// If true, the file included by '@file' is searched for as a config file, in
+  /// the config search directories.
+  bool SearchAsConfig = false;
+
   llvm::Error expandResponseFile(StringRef FName,
                                  SmallVectorImpl<const char *> &NewArgv);
 
@@ -2116,6 +2123,29 @@
     return *this;
   }
 
+  ArrayRef<StringRef> getSearchDirs() const { return SearchDirs; }
+  ExpansionContext &setSearchDirs(ArrayRef<StringRef> X) {
+    SearchDirs = X;
+    return *this;
+  }
+
+  bool getSearchAsConfig() const { return SearchAsConfig; }
+  ExpansionContext &setSearchAsConfig(bool X) {
+    SearchAsConfig = X;
+    return *this;
+  }
+
+  /// Looks for the specified configuration file.
+  ///
+  /// \param[in]  FileName Name of the file to search for.
+  /// \param[out] FilePath File absolute path, if it was found.
+  /// \return True if file was found.
+  ///
+  /// If the specified file name contains a directory separator, it is searched
+  /// for by its absolute path. Otherwise looks for file sequentially in
+  /// directories specified by SearchDirs field.
+  bool findConfigFile(StringRef FileName, std::string &FilePath);
+
   /// Reads command line options from the given configuration file.
   ///
   /// \param [in] CfgFile Path to configuration file.
Index: clang/unittests/Driver/ToolChainTest.cpp
===================================================================
--- clang/unittests/Driver/ToolChainTest.cpp
+++ clang/unittests/Driver/ToolChainTest.cpp
@@ -506,9 +506,12 @@
   FS->addFile("/home/test/bin/root.cfg", 0,
               llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform2\n"));
 
+  SmallString<128> ClangExecutable("/home/test/bin/clang");
+  FS->makeAbsolute(ClangExecutable);
+
   {
-    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
-                    "clang LLVM compiler", FS);
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
     std::unique_ptr<Compilation> C(
         TheDriver.BuildCompilation({"/home/test/bin/clang",
                                     "--config", "root.cfg",
@@ -519,7 +522,7 @@
     EXPECT_EQ("/opt/sdk/platform1", TheDriver.SysRoot);
   }
   {
-    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
                      "clang LLVM compiler", FS);
     std::unique_ptr<Compilation> C(
         TheDriver.BuildCompilation({ "/home/test/bin/clang",
@@ -531,7 +534,7 @@
     EXPECT_EQ("/opt/sdk/platform0", TheDriver.SysRoot);
   }
   {
-    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
                      "clang LLVM compiler", FS);
     std::unique_ptr<Compilation> C(
       TheDriver.BuildCompilation({ "/home/test/bin/clang",
@@ -544,4 +547,129 @@
   }
 }
 
+TEST(ToolChainTest, ConfigFileSearch2) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+  DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS(
+      new llvm::vfs::InMemoryFileSystem);
+
+#ifdef _WIN32
+  const char *TestRoot = "C:\\";
+#else
+  const char *TestRoot = "/";
+#endif
+  FS->setCurrentWorkingDirectory(TestRoot);
+
+  FS->addFile("/opt/sdk/root.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("@platform.cfg\n"));
+  FS->addFile("/opt/sdk/root2.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("@platform.cfg\n"
+                                               "--search-config-dirs\n"));
+  FS->addFile("/opt/sdk/platform.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-sys\n"));
+  FS->addFile("/home/test/sdk/platform.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-user\n"));
+  FS->addFile("/home/test/bin/platform.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-bin\n"));
+
+  SmallString<128> ClangExecutable("/home/test/bin/clang");
+  FS->makeAbsolute(ClangExecutable);
+
+  {
+    // Without '--search-config-dirs' included file is searched for in the same
+    // directory where including file is resided.
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+        {"/home/test/bin/clang", "--config", "root.cfg",
+         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));
+    ASSERT_TRUE(C);
+    ASSERT_FALSE(C->containsError());
+    EXPECT_EQ("/platform-sys", TheDriver.SysRoot);
+  }
+
+  {
+    // With '--search-config-dirs' included file is searched for in the same
+    // directories as config files, so the file in user directory is found.
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+        {"/home/test/bin/clang", "--config", "root.cfg",
+         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk",
+         "--search-config-dirs"}));
+    ASSERT_TRUE(C);
+    ASSERT_FALSE(C->containsError());
+    EXPECT_EQ("/platform-user", TheDriver.SysRoot);
+  }
+
+  {
+    // The option '--search-config-dirs' can be specified inside configuration
+    // file.
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+        {"/home/test/bin/clang", "--config", "root2.cfg",
+         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));
+    ASSERT_TRUE(C);
+    ASSERT_FALSE(C->containsError());
+    EXPECT_EQ("/platform-user", TheDriver.SysRoot);
+  }
+}
+
+TEST(ToolChainTest, ConfigFileSearch3) {
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+  DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS(
+      new llvm::vfs::InMemoryFileSystem);
+
+#ifdef _WIN32
+  const char *TestRoot = "C:\\";
+#else
+  const char *TestRoot = "/";
+#endif
+  FS->setCurrentWorkingDirectory(TestRoot);
+
+  SmallString<128> ClangExecutable("/opt/sdk/bin/clang");
+  FS->makeAbsolute(ClangExecutable);
+
+  // Configuration file is loaded from system directory, it includes file
+  // from binary one.
+  FS->addFile("/opt/sdk/root.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--search-config-dirs\n"
+                                               "@workspace.cfg\n"));
+  FS->addFile("/opt/sdk/bin/workspace.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--sysroot=/settings-bin\n"));
+
+  {
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+        {ClangExecutable.c_str(), "--config", "root.cfg",
+         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));
+    ASSERT_TRUE(C);
+    ASSERT_FALSE(C->containsError());
+    EXPECT_EQ("/settings-bin", TheDriver.SysRoot);
+  }
+
+  // User can override included file by providing file with the same name in
+  // the user directory.
+  FS->addFile("/home/test/sdk/workspace.cfg", 0,
+              llvm::MemoryBuffer::getMemBuffer("--sysroot=/settings-user\n"));
+
+  {
+    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,
+                     "clang LLVM compiler", FS);
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+        {ClangExecutable.c_str(), "--config", "root.cfg",
+         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));
+    ASSERT_TRUE(C);
+    ASSERT_FALSE(C->containsError());
+    EXPECT_EQ("/settings-user", TheDriver.SysRoot);
+  }
+}
+
 } // end anonymous namespace.
Index: clang/test/Driver/config-file.c
===================================================================
--- clang/test/Driver/config-file.c
+++ clang/test/Driver/config-file.c
@@ -39,14 +39,14 @@
 
 //--- Nested config files
 //
-// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir=%S/Inputs/config --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
 // CHECK-NESTED: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
 // CHECK-NESTED: -Wundefined-func-template
 
-// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2
+// RUN: %clang --config-system-dir=%S/Inputs --config-user-dir=%S/Inputs/config --config config-2.cfg -S --search-config-dirs %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2
 // CHECK-NESTED2: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
-// CHECK-NESTED2: -Wundefined-func-template
-
+// CHECK-NESTED2: -isysroot
+// CHECK-NESTED2-SAME: /opt/sdk/user
 
 // RUN: %clang --config %S/Inputs/config-2a.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTEDa
 // CHECK-NESTEDa: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
Index: clang/test/Driver/Inputs/config/config-3.cfg
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/config/config-3.cfg
@@ -0,0 +1 @@
+-isysroot /opt/sdk/user
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -900,40 +900,11 @@
   //
 }
 
-/// Looks the given directories for the specified file.
-///
-/// \param[out] FilePath File path, if the file was found.
-/// \param[in]  Dirs Directories used for the search.
-/// \param[in]  FileName Name of the file to search for.
-/// \return True if file was found.
-///
-/// Looks for file specified by FileName sequentially in directories specified
-/// by Dirs.
-///
-static bool searchForFile(SmallVectorImpl<char> &FilePath,
-                          ArrayRef<StringRef> Dirs, StringRef FileName,
-                          llvm::vfs::FileSystem &FS) {
-  SmallString<128> WPath;
-  for (const StringRef &Dir : Dirs) {
-    if (Dir.empty())
-      continue;
-    WPath.clear();
-    llvm::sys::path::append(WPath, Dir, FileName);
-    llvm::sys::path::native(WPath);
-    auto Status = FS.status(WPath);
-    if (Status && Status->getType() == llvm::sys::fs::file_type::regular_file) {
-      FilePath = std::move(WPath);
-      return true;
-    }
-  }
-  return false;
-}
-
-bool Driver::readConfigFile(StringRef FileName) {
+bool Driver::readConfigFile(StringRef FileName,
+                            llvm::cl::ExpansionContext &ECtx) {
   // Try reading the given file.
   SmallVector<const char *, 32> NewCfgArgs;
-  llvm::cl::ExpansionContext ExpCtx(Saver, llvm::cl::tokenizeConfigFile, &getVFS());
-  if (!ExpCtx.readConfigFile(FileName, NewCfgArgs)) {
+  if (!ECtx.readConfigFile(FileName, NewCfgArgs)) {
     Diag(diag::err_drv_cannot_read_config_file) << FileName;
     return true;
   }
@@ -966,6 +937,8 @@
 bool Driver::loadConfigFile() {
   std::string CfgFileName;
   bool FileSpecifiedExplicitly = false;
+  llvm::cl::ExpansionContext ExpCtx(Saver, llvm::cl::tokenizeConfigFile,
+                                    &getVFS());
 
   // Process options that change search path for config files.
   if (CLOptions) {
@@ -987,6 +960,8 @@
       else
         UserConfigDir = static_cast<std::string>(CfgDir);
     }
+    if (CLOptions->hasArg(options::OPT_search_config_dirs))
+      ExpCtx.setSearchAsConfig(true);
   }
 
   // First try to find config file specified in command line.
@@ -1018,7 +993,7 @@
             return true;
           }
         }
-        return readConfigFile(CfgFilePath);
+        return readConfigFile(CfgFilePath, ExpCtx);
       }
 
       FileSpecifiedExplicitly = true;
@@ -1071,30 +1046,31 @@
 
   // Prepare list of directories where config file is searched for.
   StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir};
+  ExpCtx.setSearchDirs(CfgFileSearchDirs);
 
   // Try to find config file. First try file with corrected architecture.
-  llvm::SmallString<128> CfgFilePath;
+  std::string CfgFilePath;
   if (!FixedConfigFile.empty()) {
-    if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile, getVFS()))
-      return readConfigFile(CfgFilePath);
+    if (ExpCtx.findConfigFile(FixedConfigFile, CfgFilePath))
+      return readConfigFile(CfgFilePath, ExpCtx);
     // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
     FixedConfigFile.resize(FixedArchPrefixLen);
     FixedConfigFile.append(".cfg");
-    if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile, getVFS()))
-      return readConfigFile(CfgFilePath);
+    if (ExpCtx.findConfigFile(FixedConfigFile, CfgFilePath))
+      return readConfigFile(CfgFilePath, ExpCtx);
   }
 
   // Then try original file name.
-  if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
-    return readConfigFile(CfgFilePath);
+  if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
+    return readConfigFile(CfgFilePath, ExpCtx);
 
   // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
   if (!ClangNameParts.ModeSuffix.empty() &&
       !ClangNameParts.TargetPrefix.empty()) {
     CfgFileName.assign(ClangNameParts.TargetPrefix);
     CfgFileName.append(".cfg");
-    if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
-      return readConfigFile(CfgFilePath);
+    if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
+      return readConfigFile(CfgFilePath, ExpCtx);
   }
 
   // Report error but only if config file was specified explicitly, by option
@@ -1156,7 +1132,8 @@
 
   if (HasConfigFile)
     for (auto *Opt : *CLOptions) {
-      if (Opt->getOption().matches(options::OPT_config))
+      if (Opt->getOption().matches(options::OPT_config) ||
+          Opt->getOption().matches(options::OPT_search_config_dirs))
         continue;
       const Arg *BaseArg = &Opt->getBaseArg();
       if (BaseArg == Opt)
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -905,6 +905,8 @@
   HelpText<"System directory for configuration files">;
 def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[NoXarchOption, HelpHidden]>,
   HelpText<"User directory for configuration files">;
+def search_config_dirs : Flag<["--"], "search-config-dirs">, Flags<[NoXarchOption]>,
+  HelpText<"Search for file included by '@file' in configuration file in search directories">;
 def coverage : Flag<["-", "--"], "coverage">, Group<Link_Group>, Flags<[CoreOption]>;
 def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
 def current__version : JoinedOrSeparate<["-"], "current_version">;
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -34,6 +34,9 @@
 namespace vfs {
 class FileSystem;
 }
+namespace cl {
+class ExpansionContext;
+}
 } // namespace llvm
 
 namespace clang {
@@ -673,7 +676,7 @@
   ///
   /// \param [in] FileName File to read.
   /// \returns true, if error occurred while reading.
-  bool readConfigFile(StringRef FileName);
+  bool readConfigFile(StringRef FileName, llvm::cl::ExpansionContext &ECtx);
 
   /// Set the driver mode (cl, gcc, etc) from the value of the `--driver-mode`
   /// option.
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -940,10 +940,14 @@
     @linux.options
 
 Files included by `@file` directives in configuration files are resolved
-relative to the including file. For example, if a configuration file
+relative to the including file by default. For example, if a configuration file
 `~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
 `linux.opts` is searched for in the directory `~/.llvm/os`.
 
+Option `--search-config-dirs` changes the search algorith if the included
+file is specified without a directory separator. In this case the file is looked
+for in the same directories as configuration files.
+
 To generate paths relative to the configuration file, the `<CFGDIR>` token may
 be used. This will expand to the absolute path of the directory containing the
 configuration file.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to