[Lldb-commits] [lldb] r359281 - Allow direct comparison of ConstString against StringRef

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Fri Apr 26 00:21:37 PDT 2019


Author: teemperor
Date: Fri Apr 26 00:21:36 2019
New Revision: 359281

URL: http://llvm.org/viewvc/llvm-project?rev=359281&view=rev
Log:
Allow direct comparison of ConstString against StringRef

Summary:
When we want to compare a ConstString against a string literal (or any other non-ConstString),
we currently have to explicitly turn the other string into a ConstString. This makes sense as
comparing ConstStrings against each other is only a fast pointer comparison.

However, currently we (rather incorrectly) use in several places in LLDB temporary ConstStrings when
we just want to compare a given ConstString against a hardcoded value, for example like this:
```
if (extension != ConstString(".oat") && extension != ConstString(".odex"))
```

Obviously this kind of defeats the point of ConstStrings. In the comparison above we would
construct two temporary ConstStrings every time we hit the given code. Constructing a
ConstString is relatively expensive: we need to go to the StringPool, take a read and possibly
an exclusive write-lock and then look up our temporary string in the string map of the pool.
So we do a lot of heavy work for essentially just comparing a <6 characters in two strings.

I initially wanted to just fix these issues by turning the temporary ConstString in static variables/
members, but that made the code much less readable. Instead I propose to add a new overload
for the ConstString comparison operator that takes a StringRef. This comparison operator directly
compares the ConstString content against the given StringRef without turning the StringRef into
a ConstString.

This means that the example above can look like this now:
```
if (extension != ".oat" && extension != ".odex")
```
It also no longer has to unlock/lock two locks and call multiple functions in other TUs for constructing
the temporary ConstString instances. Instead this should end up just being a direct string comparison
of the two given strings on most compilers.

This patch also directly updates all uses of temporary and short ConstStrings in LLDB to use this new
comparison operator. It also adds a some unit tests for the new and old comparison operator.

Reviewers: #lldb, JDevlieghere, espindola, amccarth

Reviewed By: JDevlieghere, amccarth

Subscribers: amccarth, clayborg, JDevlieghere, emaste, arichardson, MaskRay, lldb-commits

Tags: #lldb

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

Modified:
    lldb/trunk/include/lldb/Utility/ConstString.h
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxx.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
    lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
    lldb/trunk/source/Plugins/Language/ObjC/CF.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp
    lldb/trunk/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
    lldb/trunk/unittests/Utility/ConstStringTest.cpp

Modified: lldb/trunk/include/lldb/Utility/ConstString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/ConstString.h?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Utility/ConstString.h (original)
+++ lldb/trunk/include/lldb/Utility/ConstString.h Fri Apr 26 00:21:36 2019
@@ -154,6 +154,30 @@ public:
     return m_string == rhs.m_string;
   }
 
+  /// Equal to operator against a non-ConstString value.
+  ///
+  /// Returns true if this string is equal to the string in \a rhs. This
+  /// overload is usually slower than comparing against a ConstString value.
+  /// However, if the rhs string not already a ConstString and it is impractical
+  /// to turn it into a non-temporary variable, then this overload is faster.
+  ///
+  /// \param[in] rhs
+  ///     Another string object to compare this object to.
+  ///
+  /// \return
+  ///     \li \b true if this object is equal to \a rhs.
+  ///     \li \b false if this object is not equal to \a rhs.
+  bool operator==(const char *rhs) const {
+    // ConstString differentiates between empty strings and nullptr strings, but
+    // StringRef doesn't. Therefore we have to do this check manually now.
+    if (m_string == nullptr && rhs != nullptr)
+      return false;
+    if (m_string != nullptr && rhs == nullptr)
+      return false;
+
+    return GetStringRef() == rhs;
+  }
+
   /// Not equal to operator
   ///
   /// Returns true if this string is not equal to the string in \a rhs. This
@@ -170,6 +194,21 @@ public:
     return m_string != rhs.m_string;
   }
 
+  /// Not equal to operator against a non-ConstString value.
+  ///
+  /// Returns true if this string is not equal to the string in \a rhs. This
+  /// overload is usually slower than comparing against a ConstString value.
+  /// However, if the rhs string not already a ConstString and it is impractical
+  /// to turn it into a non-temporary variable, then this overload is faster.
+  ///
+  /// \param[in] rhs
+  ///     Another string object to compare this object to.
+  ///
+  /// \return
+  ///     \li \b true if this object is not equal to \a rhs.
+  ///     \li \b false if this object is equal to \a rhs.
+  bool operator!=(const char *rhs) const { return !(*this == rhs); }
+
   bool operator<(ConstString rhs) const;
 
   /// Get the string value as a C string.

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp Fri Apr 26 00:21:36 2019
@@ -474,7 +474,7 @@ bool DynamicLoaderDarwin::JSONImageInfor
       // that starts of file offset zero and that has bytes in the file...
       if ((image_infos[i].segments[k].fileoff == 0 &&
            image_infos[i].segments[k].filesize > 0) ||
-          (image_infos[i].segments[k].name == ConstString("__TEXT"))) {
+          (image_infos[i].segments[k].name == "__TEXT")) {
         image_infos[i].slide =
             image_infos[i].address - image_infos[i].segments[k].vmaddr;
         // We have found the slide amount, so we can exit this for loop.

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp Fri Apr 26 00:21:36 2019
@@ -111,7 +111,7 @@ bool DynamicLoaderMacOS::ProcessDidExec(
             const Symbol *symbol =
                 frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
             if (symbol) {
-              if (symbol->GetName() == ConstString("_dyld_start"))
+              if (symbol->GetName() == "_dyld_start")
                 did_exec = true;
             }
           }

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Fri Apr 26 00:21:36 2019
@@ -136,7 +136,7 @@ bool DynamicLoaderMacOSXDYLD::ProcessDid
             const Symbol *symbol =
                 frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
             if (symbol) {
-              if (symbol->GetName() == ConstString("_dyld_start"))
+              if (symbol->GetName() == "_dyld_start")
                 did_exec = true;
             }
           }
@@ -898,7 +898,7 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseL
     // starts of file offset zero and that has bytes in the file...
     if ((dylib_info.segments[i].fileoff == 0 &&
          dylib_info.segments[i].filesize > 0) ||
-        (dylib_info.segments[i].name == ConstString("__TEXT"))) {
+        (dylib_info.segments[i].name == "__TEXT")) {
       dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
       // We have found the slide amount, so we can exit this for loop.
       break;

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp Fri Apr 26 00:21:36 2019
@@ -167,8 +167,7 @@ static void AddLocalVariableDecls(const
     lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
 
     ConstString var_name = var_sp->GetName();
-    if (!var_name || var_name == ConstString("this") ||
-        var_name == ConstString(".block_descriptor"))
+    if (!var_name || var_name == "this" || var_name == ".block_descriptor")
       continue;
 
     stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp Fri Apr 26 00:21:36 2019
@@ -488,7 +488,7 @@ ClangUserExpression::GetModulesToImport(
   // We currently don't support importing any other modules in the expression
   // parser.
   for (const SourceModule &m : sc.comp_unit->GetImportedModules())
-    if (!m.path.empty() && m.path.front() == ConstString("std"))
+    if (!m.path.empty() && m.path.front() == "std")
       return {"std"};
 
   return {};

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxx.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxx.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxx.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxx.cpp Fri Apr 26 00:21:36 2019
@@ -300,9 +300,9 @@ bool lldb_private::formatters::LibCxxMap
 
 size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
     GetIndexOfChildWithName(ConstString name) {
-  if (name == ConstString("first"))
+  if (name == "first")
     return 0;
-  if (name == ConstString("second"))
+  if (name == "second")
     return 1;
   return UINT32_MAX;
 }
@@ -430,11 +430,11 @@ bool lldb_private::formatters::LibcxxSha
 
 size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
     GetIndexOfChildWithName(ConstString name) {
-  if (name == ConstString("__ptr_"))
+  if (name == "__ptr_")
     return 0;
-  if (name == ConstString("count"))
+  if (name == "count")
     return 1;
-  if (name == ConstString("weak_count"))
+  if (name == "weak_count")
     return 2;
   return UINT32_MAX;
 }

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp Fri Apr 26 00:21:36 2019
@@ -290,7 +290,7 @@ lldb_private::formatters::LibcxxStdVecto
   if (!type.IsValid() || type.GetNumTemplateArguments() == 0)
     return nullptr;
   CompilerType arg_type = type.GetTypeTemplateArgument(0);
-  if (arg_type.GetTypeName() == ConstString("bool"))
+  if (arg_type.GetTypeName() == "bool")
     return new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp);
   return new LibcxxStdVectorSyntheticFrontEnd(valobj_sp);
 }

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp Fri Apr 26 00:21:36 2019
@@ -142,9 +142,9 @@ bool LibstdcppMapIteratorSyntheticFrontE
 
 size_t LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
     ConstString name) {
-  if (name == ConstString("first"))
+  if (name == "first")
     return 0;
-  if (name == ConstString("second"))
+  if (name == "second")
     return 1;
   return UINT32_MAX;
 }
@@ -224,7 +224,7 @@ bool VectorIteratorSyntheticFrontEnd::Mi
 
 size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
     ConstString name) {
-  if (name == ConstString("item"))
+  if (name == "item")
     return 0;
   return UINT32_MAX;
 }
@@ -374,7 +374,7 @@ bool LibStdcppSharedPtrSyntheticFrontEnd
 
 size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
     ConstString name) {
-  if (name == ConstString("_M_ptr"))
+  if (name == "_M_ptr")
     return 0;
   return UINT32_MAX;
 }

Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp Fri Apr 26 00:21:36 2019
@@ -130,12 +130,11 @@ size_t LibStdcppUniquePtrSyntheticFrontE
 
 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
     ConstString name) {
-  if (name == ConstString("ptr") || name == ConstString("pointer"))
+  if (name == "ptr" || name == "pointer")
     return 0;
-  if (name == ConstString("del") || name == ConstString("deleter"))
+  if (name == "del" || name == "deleter")
     return 1;
-  if (name == ConstString("obj") || name == ConstString("object") ||
-      name == ConstString("$$dereference$$"))
+  if (name == "obj" || name == "object" || name == "$$dereference$$")
     return 2;
   return UINT32_MAX;
 }

Modified: lldb/trunk/source/Plugins/Language/ObjC/CF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/CF.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/CF.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/CF.cpp Fri Apr 26 00:21:36 2019
@@ -139,10 +139,8 @@ bool lldb_private::formatters::CFBitVect
   bool is_type_ok = false; // check to see if this is a CFBag we know about
   if (descriptor->IsCFType()) {
     ConstString type_name(valobj.GetTypeName());
-    if (type_name == ConstString("__CFMutableBitVector") ||
-        type_name == ConstString("__CFBitVector") ||
-        type_name == ConstString("CFMutableBitVectorRef") ||
-        type_name == ConstString("CFBitVectorRef")) {
+    if (type_name == "__CFMutableBitVector" || type_name == "__CFBitVector" ||
+        type_name == "CFMutableBitVectorRef" || type_name == "CFBitVectorRef") {
       if (valobj.IsPointerType())
         is_type_ok = true;
     }

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Fri Apr 26 00:21:36 2019
@@ -472,7 +472,8 @@ ValueObjectSP AppleObjCRuntime::GetExcep
   
   while (descriptor) {
     ConstString class_name(descriptor->GetClassName());
-    if (class_name == ConstString("NSException")) return cpp_exception;
+    if (class_name == "NSException")
+      return cpp_exception;
     descriptor = descriptor->GetSuperclass();
   }
 

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Fri Apr 26 00:21:36 2019
@@ -1996,8 +1996,8 @@ unsigned ObjectFileELF::ParseSymbols(Sym
   // custom extension and file name makes it highly unlikely that this will
   // collide with anything else.
   ConstString file_extension = m_file.GetFileNameExtension();
-  bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
-                              file_extension == ConstString(".odex");
+  bool skip_oatdata_oatexec =
+      file_extension == ".oat" || file_extension == ".odex";
 
   ArchSpec arch = GetArchitecture();
   ModuleSP module_sp(GetModule());

Modified: lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp Fri Apr 26 00:21:36 2019
@@ -302,7 +302,7 @@ Status PlatformAndroid::DownloadSymbolFi
                                            const FileSpec &dst_file_spec) {
   // For oat file we can try to fetch additional debug info from the device
   ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
-  if (extension != ConstString(".oat") && extension != ConstString(".odex"))
+  if (extension != ".oat" && extension != ".odex")
     return Status(
         "Symbol file downloading only supported for oat and odex files");
 

Modified: lldb/trunk/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp (original)
+++ lldb/trunk/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp Fri Apr 26 00:21:36 2019
@@ -454,8 +454,7 @@ void SystemRuntimeMacOSX::ReadLibdispatc
 ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
                                                          ConstString type) {
   ThreadSP originating_thread_sp;
-  if (BacktraceRecordingHeadersInitialized() &&
-      type == ConstString("libdispatch")) {
+  if (BacktraceRecordingHeadersInitialized() && type == "libdispatch") {
     Status error;
 
     // real_thread is either an actual, live thread (in which case we need to
@@ -554,7 +553,7 @@ ThreadSP
 SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp,
                                                       ConstString type) {
   ThreadSP extended_thread_sp;
-  if (type != ConstString("libdispatch"))
+  if (type != "libdispatch")
     return extended_thread_sp;
 
   bool stop_id_is_valid = true;

Modified: lldb/trunk/unittests/Utility/ConstStringTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/ConstStringTest.cpp?rev=359281&r1=359280&r2=359281&view=diff
==============================================================================
--- lldb/trunk/unittests/Utility/ConstStringTest.cpp (original)
+++ lldb/trunk/unittests/Utility/ConstStringTest.cpp Fri Apr 26 00:21:36 2019
@@ -89,3 +89,51 @@ TEST(ConstStringTest, NullAndEmptyStates
   EXPECT_TRUE(null.IsEmpty());
   EXPECT_TRUE(null.IsNull());
 }
+
+TEST(ConstStringTest, CompareConstString) {
+  ConstString foo("foo");
+  ConstString foo2("foo");
+  ConstString bar("bar");
+
+  EXPECT_TRUE(foo == foo2);
+  EXPECT_TRUE(foo2 == foo);
+  EXPECT_TRUE(foo == ConstString("foo"));
+
+  EXPECT_FALSE(foo == bar);
+  EXPECT_FALSE(foo2 == bar);
+  EXPECT_FALSE(foo == ConstString("bar"));
+  EXPECT_FALSE(foo == ConstString("different"));
+  EXPECT_FALSE(foo == ConstString(""));
+  EXPECT_FALSE(foo == ConstString());
+
+  ConstString empty("");
+  EXPECT_FALSE(empty == ConstString("bar"));
+  EXPECT_FALSE(empty == ConstString());
+  EXPECT_TRUE(empty == ConstString(""));
+
+  ConstString null;
+  EXPECT_FALSE(null == ConstString("bar"));
+  EXPECT_TRUE(null == ConstString());
+  EXPECT_FALSE(null == ConstString(""));
+}
+
+TEST(ConstStringTest, CompareStringRef) {
+  ConstString foo("foo");
+
+  EXPECT_TRUE(foo == "foo");
+  EXPECT_TRUE(foo != "");
+  EXPECT_FALSE(foo == static_cast<const char *>(nullptr));
+  EXPECT_TRUE(foo != "bar");
+
+  ConstString empty("");
+  EXPECT_FALSE(empty == "foo");
+  EXPECT_FALSE(empty != "");
+  EXPECT_FALSE(empty == static_cast<const char *>(nullptr));
+  EXPECT_TRUE(empty != "bar");
+
+  ConstString null;
+  EXPECT_FALSE(null == "foo");
+  EXPECT_TRUE(null != "");
+  EXPECT_TRUE(null == static_cast<const char *>(nullptr));
+  EXPECT_TRUE(null != "bar");
+}




More information about the lldb-commits mailing list