Browse Source

Merge topic 'cmCMakePath-SunPro-sparc-workaround'

945b9b8132 cmCMakePath: workarounds for Sunpro/sparc compiler

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Acked-by: Robert Maynard <[email protected]>
Merge-request: !8633
Brad King 2 years ago
parent
commit
e921566142
4 changed files with 650 additions and 7 deletions
  1. 2 0
      Source/cmCMakePath.cxx
  2. 206 7
      Source/cmCMakePath.h
  3. 1 0
      Tests/CMakeLib/CMakeLists.txt
  4. 441 0
      Tests/CMakeLib/testCMakePath.cxx

+ 2 - 0
Source/cmCMakePath.cxx

@@ -15,6 +15,8 @@
 #include <cm/string_view>
 
 #if defined(_WIN32)
+#  include <cmext/string_view>
+
 #  include "cmStringAlgorithms.h"
 #endif
 

+ 206 - 7
Source/cmCMakePath.h

@@ -12,7 +12,10 @@
 #include <cm/filesystem>
 #include <cm/string_view>
 #include <cm/type_traits>
-#include <cmext/string_view>
+
+namespace cm {
+class static_string_view;
+}
 
 namespace detail {
 #if defined(__SUNPRO_CC) && defined(__sparc)
@@ -123,11 +126,29 @@ public:
     : Path(FormatPath(source, fmt))
   {
   }
+  cmCMakePath(const char* source, format fmt = generic_format) noexcept
+    : Path(FormatPath(cm::string_view{ source }, fmt))
+  {
+  }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath(const std::string& source, format fmt = generic_format)
+    : Path(FormatPath(source, fmt))
+  {
+  }
+  cmCMakePath(std::string&& source, format fmt = generic_format)
+    : Path(FormatPath(std::move(source), fmt))
+  {
+  }
+#else
   template <typename Source, typename = enable_if_move_pathable<Source>>
   cmCMakePath(Source source, format fmt = generic_format)
     : Path(FormatPath(std::move(source), fmt))
   {
   }
+#endif
 
   template <typename Source, typename = enable_if_move_pathable<Source>>
   cmCMakePath& Assign(Source&& source)
@@ -156,6 +177,41 @@ public:
     }
     return *this;
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& operator=(cm::filesystem::path&& source)
+  {
+    this->Assign(std::forward<cm::filesystem::path>(source));
+    return *this;
+  }
+  cmCMakePath& operator=(std::string&& source)
+  {
+    this->Assign(std::forward<std::string>(source));
+    return *this;
+  }
+  cmCMakePath& operator=(const cm::filesystem::path& source)
+  {
+    this->Assign(source);
+    return *this;
+  }
+  cmCMakePath& operator=(const std::string& source)
+  {
+    this->Assign(source);
+    return *this;
+  }
+  cmCMakePath& operator=(const cm::string_view source)
+  {
+    this->Assign(source);
+    return *this;
+  }
+  cmCMakePath& operator=(const char* source)
+  {
+    this->Assign(cm::string_view{ source });
+    return *this;
+  }
+#else
   template <typename Source, typename = enable_if_move_pathable<Source>>
   cmCMakePath& operator=(Source&& source)
   {
@@ -168,6 +224,7 @@ public:
     this->Assign(source);
     return *this;
   }
+#endif
 
   // Concatenation
   cmCMakePath& Append(const cmCMakePath& path)
@@ -182,12 +239,29 @@ public:
     this->Path = this->Path.generic_string();
     return *this;
   }
-
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& Append(const std::string& source)
+  {
+    return this->Append(cm::filesystem::path(source));
+  }
+  cmCMakePath& Append(cm::string_view source)
+  {
+    return this->Append(cm::filesystem::path(source));
+  }
+  cmCMakePath& Append(const char* source)
+  {
+    return this->Append(cm::filesystem::path(cm::string_view{ source }));
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath& Append(const Source& source)
   {
     return this->Append(cm::filesystem::path(source));
   }
+#endif
 
   cmCMakePath& operator/=(const cmCMakePath& path)
   {
@@ -204,17 +278,38 @@ public:
     this->Path += path.Path;
     return *this;
   }
-  cmCMakePath& Concat(cm::static_string_view source)
+  cmCMakePath& Concat(cm::string_view source)
   {
-    this->Path.concat(std::string(source));
+    this->Path.operator+=(std::string(source));
     return *this;
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& Concat(const cm::filesystem::path& source)
+  {
+    this->Path.operator+=(source);
+    return *this;
+  }
+  cmCMakePath& Concat(const std::string& source)
+  {
+    this->Path.operator+=(source);
+    return *this;
+  }
+  cmCMakePath& Concat(const char* source)
+  {
+    this->Path.operator+=(source);
+    return *this;
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath& Concat(const Source& source)
   {
-    this->Path.concat(source);
+    this->Path.operator+=(source);
     return *this;
   }
+#endif
 
   cmCMakePath& operator+=(const cmCMakePath& path)
   {
@@ -242,6 +337,32 @@ public:
     }
     return *this;
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& ReplaceFileName(const cm::filesystem::path& filename)
+  {
+    if (this->Path.has_filename()) {
+      this->Path.replace_filename(filename);
+    }
+    return *this;
+  }
+  cmCMakePath& ReplaceFileName(const std::string& filename)
+  {
+    if (this->Path.has_filename()) {
+      this->Path.replace_filename(filename);
+    }
+    return *this;
+  }
+  cmCMakePath& ReplaceFileName(cm::string_view filename)
+  {
+    if (this->Path.has_filename()) {
+      this->Path.replace_filename(filename);
+    }
+    return *this;
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath& ReplaceFileName(const Source& filename)
   {
@@ -250,18 +371,40 @@ public:
     }
     return *this;
   }
+#endif
 
   cmCMakePath& ReplaceExtension(const cmCMakePath& extension = cmCMakePath())
   {
     this->Path.replace_extension(extension.Path);
     return *this;
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& ReplaceExtension(const cm::filesystem::path& extension)
+  {
+    this->Path.replace_extension(extension);
+    return *this;
+  }
+  cmCMakePath& ReplaceExtension(const std::string& extension)
+  {
+    this->Path.replace_extension(extension);
+    return *this;
+  }
+  cmCMakePath& ReplaceExtension(const cm::string_view extension)
+  {
+    this->Path.replace_extension(extension);
+    return *this;
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath& ReplaceExtension(const Source& extension)
   {
     this->Path.replace_extension(extension);
     return *this;
   }
+#endif
 
   cmCMakePath& ReplaceWideExtension(
     const cmCMakePath& extension = cmCMakePath())
@@ -269,11 +412,26 @@ public:
     return this->ReplaceWideExtension(
       static_cast<cm::string_view>(extension.Path.string()));
   }
+  cmCMakePath& ReplaceWideExtension(const cm::filesystem::path& extension)
+  {
+    return this->ReplaceWideExtension(
+      static_cast<cm::string_view>(extension.string()));
+  }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath& ReplaceWideExtension(const std::string& extension)
+  {
+    return this->ReplaceWideExtension(cm::string_view{ extension });
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath& ReplaceWideExtension(const Source& extension)
   {
-    return this->ReplaceWideExtension(cm::string_view(extension));
+    return this->ReplaceWideExtension(extension);
   }
+#endif
   cmCMakePath& ReplaceWideExtension(cm::string_view extension);
 
   cmCMakePath& RemoveExtension()
@@ -355,12 +513,25 @@ public:
     // Windows) so convert back to '/'
     return path.generic_string();
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath Relative(const std::string& base) const
+  {
+    return this->Relative(cm::filesystem::path(base));
+  }
+  cmCMakePath Relative(cm::string_view base) const
+  {
+    return this->Relative(cm::filesystem::path(base));
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath Relative(const Source& base) const
   {
     return this->Relative(cm::filesystem::path(base));
   }
-
+#endif
   cmCMakePath Proximate(const cmCMakePath& base) const
   {
     return this->Proximate(base.Path);
@@ -372,21 +543,49 @@ public:
     // Windows) so convert back to '/'
     return path.generic_string();
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath Proximate(const std::string& base) const
+  {
+    return this->Proximate(cm::filesystem::path(base));
+  }
+  cmCMakePath Proximate(cm::string_view base) const
+  {
+    return this->Proximate(cm::filesystem::path(base));
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath Proximate(const Source& base) const
   {
     return this->Proximate(cm::filesystem::path(base));
   }
+#endif
 
   cmCMakePath Absolute(const cmCMakePath& base) const
   {
     return this->Absolute(base.Path);
   }
+#if defined(__SUNPRO_CC) && defined(__sparc)
+  // Oracle DeveloperStudio C++ compiler on Solaris/Sparc is confused when
+  // standard methods and templates use the same name. The template is selected
+  // rather than the standard one regardless the arguments of the method.
+  cmCMakePath Absolute(const std::string& base) const
+  {
+    return this->Absolute(cm::filesystem::path(base));
+  }
+  cmCMakePath Absolute(cm::string_view base) const
+  {
+    return this->Absolute(cm::filesystem::path(base));
+  }
+#else
   template <typename Source, typename = enable_if_pathable<Source>>
   cmCMakePath Absolute(const Source& base) const
   {
     return this->Absolute(cm::filesystem::path(base));
   }
+#endif
   cmCMakePath Absolute(const cm::filesystem::path& base) const;
 
   // Comparison

+ 1 - 0
Tests/CMakeLib/CMakeLists.txt

@@ -31,6 +31,7 @@ set(CMakeLib_TESTS
   testCMExtAlgorithm.cxx
   testCMExtEnumSet.cxx
   testList.cxx
+  testCMakePath.cxx
   )
 if(CMake_ENABLE_DEBUGGER)
   list(APPEND CMakeLib_TESTS

+ 441 - 0
Tests/CMakeLib/testCMakePath.cxx

@@ -0,0 +1,441 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iostream>
+#include <string>
+#include <utility>
+
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmCMakePath.h"
+
+namespace {
+
+void checkResult(bool success)
+{
+  if (!success) {
+    std::cout << " => failed";
+  }
+  std::cout << std::endl;
+}
+
+bool testConstructors()
+{
+  std::cout << "testConstructors()";
+
+  bool result = true;
+
+  {
+    cmCMakePath path;
+    if (!path.String().empty() || path != cmCMakePath{}) {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path{ "aa/bb" };
+    if (path.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string s{ "aa/bb" };
+    cmCMakePath path{ s };
+    if (path.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path{ "aa/bb"_s };
+    if (path.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2("aa/bb"_s);
+
+    if (path1 != path2) {
+      result = false;
+    }
+    if (path1.String() != "aa/bb") {
+      result = false;
+    }
+    if (path1.String() != path2.String()) {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ path1 };
+
+    if (path1 != path2) {
+      result = false;
+    }
+    if (path1.String() != "aa/bb") {
+      result = false;
+    }
+    if (path1.String() != path2.String()) {
+      result = false;
+    }
+  }
+
+  checkResult(result);
+
+  return result;
+}
+
+bool testAssign()
+{
+  std::cout << "testAssign()";
+
+  bool result = true;
+
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = path1;
+    if (path1 != path2) {
+      result = false;
+    }
+    if (path1.String() != "aa/bb") {
+      result = false;
+    }
+    if (path1.String() != path2.String()) {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = std::move(path1);
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = path1;
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = std::move(path1);
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = path1;
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 = path1;
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Assign(path1);
+    if (path2.String() != path1) {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Assign(std::move(path1));
+    if (path2.String() != "aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Assign(path1);
+    if (path2.String() != path1) {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Assign(path1);
+    if (path2.String() != path1) {
+      result = false;
+    }
+  }
+
+  checkResult(result);
+
+  return result;
+}
+
+bool testConcat()
+{
+  std::cout << "testConcat()";
+
+  bool result = true;
+
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += path1;
+
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += std::move(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += path1;
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += std::move(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += path1;
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 += path1;
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Concat(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Concat(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Concat(std::move(path1));
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Concat(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Concat(path1);
+    if (path2.String() != "cc/ddaa/bb") {
+      result = false;
+    }
+  }
+
+  checkResult(result);
+
+  return result;
+}
+
+bool testAppend()
+{
+  std::cout << "testAppend()";
+
+  bool result = true;
+
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= path1;
+
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= std::move(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= path1;
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= std::move(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= path1;
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2 /= path1;
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cmCMakePath path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Append(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Append(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    std::string path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Append(std::move(path1));
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    cm::string_view path1{ "aa/bb" };
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Append(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+  {
+    char path1[] = "aa/bb";
+    cmCMakePath path2{ "cc/dd" };
+
+    path2.Append(path1);
+    if (path2.String() != "cc/dd/aa/bb") {
+      result = false;
+    }
+  }
+
+  checkResult(result);
+
+  return result;
+}
+}
+
+int testCMakePath(int /*unused*/, char* /*unused*/[])
+{
+  int result = 0;
+
+  if (!testConstructors()) {
+    result = 1;
+  }
+  if (!testAssign()) {
+    result = 1;
+  }
+  if (!testConcat()) {
+    result = 1;
+  }
+  if (!testAppend()) {
+    result = 1;
+  }
+
+  return result;
+}