r311981 - Use class to pass information about executable name

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 28 22:22:26 PDT 2017


Author: sepavloff
Date: Mon Aug 28 22:22:26 2017
New Revision: 311981

URL: http://llvm.org/viewvc/llvm-project?rev=311981&view=rev
Log:
Use class to pass information about executable name

Information about clang executable name components, such as target and
driver mode, was passes in std::pair. With this change it is passed in
a special structure. It improves readability and makes access to this
information more convenient.

NFC.

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

Modified:
    cfe/trunk/include/clang/Driver/Driver.h
    cfe/trunk/include/clang/Driver/ToolChain.h
    cfe/trunk/lib/Driver/Driver.cpp
    cfe/trunk/lib/Driver/ToolChain.cpp
    cfe/trunk/lib/Tooling/Tooling.cpp
    cfe/trunk/tools/driver/driver.cpp
    cfe/trunk/unittests/Driver/CMakeLists.txt
    cfe/trunk/unittests/Driver/ToolChainTest.cpp

Modified: cfe/trunk/include/clang/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Driver.h?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Driver.h (original)
+++ cfe/trunk/include/clang/Driver/Driver.h Mon Aug 28 22:22:26 2017
@@ -129,6 +129,9 @@ public:
   /// The original path to the clang executable.
   std::string ClangExecutable;
 
+  /// Target and driver mode components extracted from clang executable name.
+  ParsedClangName ClangNameParts;
+
   /// The path to the installed clang directory, if any.
   std::string InstalledDir;
 
@@ -284,6 +287,8 @@ public:
 
   void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }
 
+  void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; }
+
   const std::string &getTitle() { return DriverTitle; }
   void setTitle(std::string Value) { DriverTitle = std::move(Value); }
 

Modified: cfe/trunk/include/clang/Driver/ToolChain.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/ToolChain.h?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/ToolChain.h (original)
+++ cfe/trunk/include/clang/Driver/ToolChain.h Mon Aug 28 22:22:26 2017
@@ -46,6 +46,28 @@ namespace driver {
   class Tool;
   class XRayArgs;
 
+/// Helper structure used to pass information extracted from clang executable
+/// name such as `i686-linux-android-g++`.
+///
+struct ParsedClangName {
+  /// Target part of the executable name, as `i686-linux-android`.
+  std::string TargetPrefix;
+  /// Driver mode part of the executable name, as `g++`.
+  std::string ModeSuffix;
+  /// Corresponding driver mode argument, as '--driver-mode=g++'
+  const char *DriverMode;
+  /// True if TargetPrefix is recognized as a registered target name.
+  bool TargetIsValid;
+
+  ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {}
+  ParsedClangName(std::string Suffix, const char *Mode)
+      : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {}
+  ParsedClangName(std::string Target, std::string Suffix, const char *Mode,
+                  bool IsRegistered)
+      : TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode),
+        TargetIsValid(IsRegistered) {}
+};
+
 /// ToolChain - Access to tools for a single platform.
 class ToolChain {
 public:
@@ -193,13 +215,16 @@ public:
   /// For example, when called with i686-linux-android-g++, the first element
   /// of the return value will be set to `"i686-linux-android"` and the second
   /// will be set to "--driver-mode=g++"`.
+  /// It is OK if the target name is not registered. In this case the return
+  /// value contains false in the field TargetIsValid.
   ///
   /// \pre `llvm::InitializeAllTargets()` has been called.
   /// \param ProgName The name the Clang driver was invoked with (from,
-  /// e.g., argv[0])
-  /// \return A pair of (`target`, `mode-flag`), where one or both may be empty.
-  static std::pair<std::string, std::string>
-  getTargetAndModeFromProgramName(StringRef ProgName);
+  /// e.g., argv[0]).
+  /// \return A structure of type ParsedClangName that contains the executable
+  /// name parts.
+  ///
+  static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName);
 
   // Tool access.
 

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Mon Aug 28 22:22:26 2017
@@ -119,9 +119,8 @@ Driver::Driver(StringRef ClangExecutable
 
 void Driver::ParseDriverMode(StringRef ProgramName,
                              ArrayRef<const char *> Args) {
-  auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName);
-  StringRef DefaultMode(Default.second);
-  setDriverModeFromOption(DefaultMode);
+  ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
+  setDriverModeFromOption(ClangNameParts.DriverMode);
 
   for (const char *ArgPtr : Args) {
     // Ingore nullptrs, they are response file's EOL markers

Modified: cfe/trunk/lib/Driver/ToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChain.cpp?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChain.cpp Mon Aug 28 22:22:26 2017
@@ -113,7 +113,7 @@ struct DriverSuffix {
   const char *ModeFlag;
 };
 
-const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
+const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
   // A list of known driver suffixes. Suffixes are compared against the
   // program name in order. If there is a match, the frontend type is updated as
   // necessary by applying the ModeFlag.
@@ -132,9 +132,13 @@ const DriverSuffix *FindDriverSuffix(Str
       {"++", "--driver-mode=g++"},
   };
 
-  for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
-    if (ProgName.endswith(DriverSuffixes[i].Suffix))
+  for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
+    StringRef Suffix(DriverSuffixes[i].Suffix);
+    if (ProgName.endswith(Suffix)) {
+      Pos = ProgName.size() - Suffix.size();
       return &DriverSuffixes[i];
+    }
+  }
   return nullptr;
 }
 
@@ -149,7 +153,7 @@ std::string normalizeProgramName(llvm::S
   return ProgName;
 }
 
-const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
+const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
   // Try to infer frontend type and default target from the program name by
   // comparing it against DriverSuffixes in order.
 
@@ -157,47 +161,46 @@ const DriverSuffix *parseDriverSuffix(St
   // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
   // prefix "x86_64-linux". If such a target prefix is found, it may be
   // added via -target as implicit first argument.
-  const DriverSuffix *DS = FindDriverSuffix(ProgName);
+  const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
 
   if (!DS) {
     // Try again after stripping any trailing version number:
     // clang++3.5 -> clang++
     ProgName = ProgName.rtrim("0123456789.");
-    DS = FindDriverSuffix(ProgName);
+    DS = FindDriverSuffix(ProgName, Pos);
   }
 
   if (!DS) {
     // Try again after stripping trailing -component.
     // clang++-tot -> clang++
     ProgName = ProgName.slice(0, ProgName.rfind('-'));
-    DS = FindDriverSuffix(ProgName);
+    DS = FindDriverSuffix(ProgName, Pos);
   }
   return DS;
 }
 } // anonymous namespace
 
-std::pair<std::string, std::string>
+ParsedClangName
 ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
   std::string ProgName = normalizeProgramName(PN);
-  const DriverSuffix *DS = parseDriverSuffix(ProgName);
+  size_t SuffixPos;
+  const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
   if (!DS)
-    return std::make_pair("", "");
-  std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag;
+    return ParsedClangName();
+  size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
 
-  std::string::size_type LastComponent =
-      ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix));
+  size_t LastComponent = ProgName.rfind('-', SuffixPos);
   if (LastComponent == std::string::npos)
-    return std::make_pair("", ModeFlag);
+    return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
+  std::string ModeSuffix = ProgName.substr(LastComponent + 1,
+                                           SuffixEnd - LastComponent - 1);
 
   // Infer target from the prefix.
   StringRef Prefix(ProgName);
   Prefix = Prefix.slice(0, LastComponent);
   std::string IgnoredError;
-  std::string Target;
-  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
-    Target = Prefix;
-  }
-  return std::make_pair(Target, ModeFlag);
+  bool IsRegistered = llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError);
+  return ParsedClangName{Prefix, ModeSuffix, DS->ModeFlag, IsRegistered};
 }
 
 StringRef ToolChain::getDefaultUniversalArchName() const {

Modified: cfe/trunk/lib/Tooling/Tooling.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Tooling.cpp (original)
+++ cfe/trunk/lib/Tooling/Tooling.cpp Mon Aug 28 22:22:26 2017
@@ -190,11 +190,12 @@ void addTargetAndModeForProgramName(std:
     }
     auto TargetMode =
         clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
-    if (!AlreadyHasMode && !TargetMode.second.empty()) {
-      CommandLine.insert(++CommandLine.begin(), TargetMode.second);
+    if (!AlreadyHasMode && TargetMode.DriverMode) {
+      CommandLine.insert(++CommandLine.begin(), TargetMode.DriverMode);
     }
-    if (!AlreadyHasTarget && !TargetMode.first.empty()) {
-      CommandLine.insert(++CommandLine.begin(), {"-target", TargetMode.first});
+    if (!AlreadyHasTarget && TargetMode.TargetIsValid) {
+      CommandLine.insert(++CommandLine.begin(), {"-target",
+                                                 TargetMode.TargetPrefix});
     }
   }
 }

Modified: cfe/trunk/tools/driver/driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/driver.cpp?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/tools/driver/driver.cpp (original)
+++ cfe/trunk/tools/driver/driver.cpp Mon Aug 28 22:22:26 2017
@@ -206,23 +206,19 @@ extern int cc1_main(ArrayRef<const char
 extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
                       void *MainAddr);
 
-static void insertTargetAndModeArgs(StringRef Target, StringRef Mode,
+static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
                                     SmallVectorImpl<const char *> &ArgVector,
                                     std::set<std::string> &SavedStrings) {
-  if (!Mode.empty()) {
+  if (NameParts.DriverMode) {
     // Add the mode flag to the arguments.
-    auto it = ArgVector.begin();
-    if (it != ArgVector.end())
-      ++it;
-    ArgVector.insert(it, GetStableCStr(SavedStrings, Mode));
+    ArgVector.insert(ArgVector.end(),
+                     GetStableCStr(SavedStrings, NameParts.DriverMode));
   }
 
-  if (!Target.empty()) {
-    auto it = ArgVector.begin();
-    if (it != ArgVector.end())
-      ++it;
-    const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)};
-    ArgVector.insert(it, std::begin(arr), std::end(arr));
+  if (NameParts.TargetIsValid) {
+    const char *arr[] = {"-target", GetStableCStr(SavedStrings,
+                                                  NameParts.TargetPrefix)};
+    ArgVector.insert(ArgVector.end(), std::begin(arr), std::end(arr));
   }
 }
 
@@ -330,9 +326,7 @@ int main(int argc_, const char **argv_)
   }
 
   llvm::InitializeAllTargets();
-  std::string ProgName = argv[0];
-  std::pair<std::string, std::string> TargetAndMode =
-      ToolChain::getTargetAndModeFromProgramName(ProgName);
+  auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]);
 
   llvm::BumpPtrAllocator A;
   llvm::StringSaver Saver(A);
@@ -345,7 +339,7 @@ int main(int argc_, const char **argv_)
   // Finally, our -cc1 tools don't care which tokenization mode we use because
   // response files written by clang will tokenize the same way in either mode.
   bool ClangCLMode = false;
-  if (TargetAndMode.second == "--driver-mode=cl" ||
+  if (StringRef(TargetAndMode.DriverMode).equals("--driver-mode=cl") ||
       std::find_if(argv.begin(), argv.end(), [](const char *F) {
         return F && strcmp(F, "--driver-mode=cl") == 0;
       }) != argv.end()) {
@@ -454,9 +448,9 @@ int main(int argc_, const char **argv_)
 
   Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
   SetInstallDir(argv, TheDriver, CanonicalPrefixes);
+  TheDriver.setTargetAndMode(TargetAndMode);
 
-  insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv,
-                          SavedStrings);
+  insertTargetAndModeArgs(TargetAndMode, argv, SavedStrings);
 
   SetBackdoorDriverOutputsFromEnvVars(TheDriver);
 

Modified: cfe/trunk/unittests/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Driver/CMakeLists.txt?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/unittests/Driver/CMakeLists.txt (original)
+++ cfe/trunk/unittests/Driver/CMakeLists.txt Mon Aug 28 22:22:26 2017
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  ${LLVM_TARGETS_TO_BUILD}
   Support
   Option
   )

Modified: cfe/trunk/unittests/Driver/ToolChainTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Driver/ToolChainTest.cpp?rev=311981&r1=311980&r2=311981&view=diff
==============================================================================
--- cfe/trunk/unittests/Driver/ToolChainTest.cpp (original)
+++ cfe/trunk/unittests/Driver/ToolChainTest.cpp Mon Aug 28 22:22:26 2017
@@ -18,6 +18,8 @@
 #include "clang/Basic/VirtualFileSystem.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Driver.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 #include "gtest/gtest.h"
 using namespace clang;
@@ -164,4 +166,98 @@ TEST(ToolChainTest, InvalidArgument) {
   EXPECT_TRUE(C->containsError());
 }
 
+TEST(ToolChainTest, ParsedClangName) {
+  ParsedClangName Empty;
+  EXPECT_TRUE(Empty.TargetPrefix.empty());
+  EXPECT_TRUE(Empty.ModeSuffix.empty());
+  EXPECT_TRUE(Empty.DriverMode == nullptr);
+  EXPECT_FALSE(Empty.TargetIsValid);
+
+  ParsedClangName DriverOnly("clang", nullptr);
+  EXPECT_TRUE(DriverOnly.TargetPrefix.empty());
+  EXPECT_TRUE(DriverOnly.ModeSuffix == "clang");
+  EXPECT_TRUE(DriverOnly.DriverMode == nullptr);
+  EXPECT_FALSE(DriverOnly.TargetIsValid);
+
+  ParsedClangName DriverOnly2("clang++", "--driver-mode=g++");
+  EXPECT_TRUE(DriverOnly2.TargetPrefix.empty());
+  EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++");
+  EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++");
+  EXPECT_FALSE(DriverOnly2.TargetIsValid);
+
+  ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true);
+  EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386");
+  EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++");
+  EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++");
+  EXPECT_TRUE(TargetAndMode.TargetIsValid);
+}
+
+TEST(ToolChainTest, GetTargetAndMode) {
+  llvm::InitializeAllTargets();
+  std::string IgnoredError;
+  if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError))
+    return;
+
+  ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix == "clang");
+  EXPECT_TRUE(Res.DriverMode == nullptr);
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("clang++");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix == "clang++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix == "clang++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("clang++-release");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix == "clang++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++");
+  EXPECT_TRUE(Res.TargetPrefix == "x86_64");
+  EXPECT_TRUE(Res.ModeSuffix == "clang++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_TRUE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName(
+      "x86_64-linux-gnu-clang-c++");
+  EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");
+  EXPECT_TRUE(Res.ModeSuffix == "clang-c++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_TRUE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName(
+      "x86_64-linux-gnu-clang-c++-tot");
+  EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");
+  EXPECT_TRUE(Res.ModeSuffix == "clang-c++");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
+  EXPECT_TRUE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("qqq");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix.empty());
+  EXPECT_TRUE(Res.DriverMode == nullptr);
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix.empty());
+  EXPECT_TRUE(Res.DriverMode == nullptr);
+  EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl");
+  EXPECT_TRUE(Res.TargetPrefix == "qqq");
+  EXPECT_TRUE(Res.ModeSuffix == "clang-cl");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl");
+  EXPECT_FALSE(Res.TargetIsValid);
+}
 } // end anonymous namespace.




More information about the cfe-commits mailing list