Author: Alex Langford
Date: 2023-05-18T14:47:33-07:00
New Revision: 915256388f865a1a42808f168fc388fccff14eda

URL: 
https://github.com/llvm/llvm-project/commit/915256388f865a1a42808f168fc388fccff14eda
DIFF: 
https://github.com/llvm/llvm-project/commit/915256388f865a1a42808f168fc388fccff14eda.diff

LOG: [lldb] Refactor ObjCLanguage::MethodName

The goal of this patch is to make it easier to reason about the state of
ObjCLanguage::MethodName. I do that in several ways:
- Instead of using the constructor directly, you go through a factory
  method. It returns a std::optional<MethodName> so either you got an
  ObjCLanguage::MethodName or you didn't. No more checking if it's valid
  to know if you can use it or not.
- ObjCLanguage::MethodName is now immutable. You cannot change its
  internals once it is created.
- ObjCLanguage::MethodName::GetFullNameWithoutCategory previously had a
  parameter that let you get back an empty string if the method had no
  category. Every caller of this method was enabling this behavior so I
  dropped the parameter and made it the default behavior.
- No longer store all the various components of the method name as
  ConstStrings. The relevant `Get` methods now return llvm::StringRefs
  backed by the MethodName's internal storage. The lifetime of these
  StringRefs are tied to the MethodName itself, so if you need to
  persist these you need to create copies.

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

Added: 
    

Modified: 
    lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
    lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
    lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
    lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp 
b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 811654460afb7..fb87d5d80b96c 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -60,201 +60,152 @@ Language *ObjCLanguage::CreateInstance(lldb::LanguageType 
language) {
   }
 }
 
-void ObjCLanguage::MethodName::Clear() {
-  m_full.Clear();
-  m_class.Clear();
-  m_category.Clear();
-  m_selector.Clear();
-  m_type = eTypeUnspecified;
-  m_category_is_valid = false;
-}
-
-bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
-  Clear();
+std::optional<const ObjCLanguage::MethodName>
+ObjCLanguage::MethodName::Create(llvm::StringRef name, bool strict) {
   if (name.empty())
-    return IsValid(strict);
-
-  // If "strict" is true. then the method must be specified with a '+' or '-'
-  // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
-  bool valid_prefix = false;
-
-  if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
-    valid_prefix = name[1] == '[';
-    if (name[0] == '+')
-      m_type = eTypeClassMethod;
-    else
-      m_type = eTypeInstanceMethod;
-  } else if (!strict) {
-    // "strict" is false, the name just needs to start with '['
-    valid_prefix = name[0] == '[';
-  }
-
-  if (valid_prefix) {
-    int name_len = name.size();
-    // Objective-C methods must have at least:
-    //      "-[" or "+[" prefix
-    //      One character for a class name
-    //      One character for the space between the class name
-    //      One character for the method name
-    //      "]" suffix
-    if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') {
-      m_full.SetString(name);
-    }
-  }
-  return IsValid(strict);
+    return std::nullopt;
+
+  // Objective-C method minimum requirements:
+  //  - If `strict` is true, must start with '-' or '+' (1 char)
+  //  - Must be followed by '[' (1 char)
+  //  - Must have at least one character for class name (1 char)
+  //  - Must have a space between class name and method name (1 char)
+  //  - Must have at least one character for  method name (1 char)
+  //  - Must be end with ']' (1 char)
+  //  This means that the minimum size is 5 characters (6 if `strict`)
+  //  e.g. [a a] (-[a a] or +[a a] if `strict`)
+
+  // We can check length and ending invariants first
+  if (name.size() < (5 + (strict ? 1 : 0)) || name.back() != ']')
+    return std::nullopt;
+
+  // Figure out type
+  Type type = eTypeUnspecified;
+  if (name.startswith("+["))
+    type = eTypeClassMethod;
+  else if (name.startswith("-["))
+    type = eTypeInstanceMethod;
+
+  // If there's no type and it's strict, this is invalid
+  if (strict && type == eTypeUnspecified)
+    return std::nullopt;
+
+  // If not strict and type unspecified, make sure we start with '['
+  if (type == eTypeUnspecified && name.front() != '[')
+    return std::nullopt;
+
+  // If we've gotten here, we're confident that this looks enough like an
+  // Objective-C method to treat it like one.
+  ObjCLanguage::MethodName method_name(name, type);
+  return method_name;
 }
 
-bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) {
-  return SetName(llvm::StringRef(name), strict);
+llvm::StringRef ObjCLanguage::MethodName::GetClassName() const {
+  llvm::StringRef full = m_full;
+  const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
+  const size_t paren_pos = full.find('(', class_start_pos);
+  // If there's a category we want to stop there
+  if (paren_pos != llvm::StringRef::npos)
+    return full.substr(class_start_pos, paren_pos - class_start_pos);
+
+  // Otherwise we find the space separating the class and method
+  const size_t space_pos = full.find(' ', class_start_pos);
+  return full.substr(class_start_pos, space_pos - class_start_pos);
 }
 
-ConstString ObjCLanguage::MethodName::GetClassName() {
-  if (!m_class) {
-    if (IsValid(false)) {
-      const char *full = m_full.GetCString();
-      const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
-      const char *paren_pos = strchr(class_start, '(');
-      if (paren_pos) {
-        m_class.SetCStringWithLength(class_start, paren_pos - class_start);
-      } else {
-        // No '(' was found in the full name, we can definitively say that our
-        // category was valid (and empty).
-        m_category_is_valid = true;
-        const char *space_pos = strchr(full, ' ');
-        if (space_pos) {
-          m_class.SetCStringWithLength(class_start, space_pos - class_start);
-          if (!m_class_category) {
-            // No category in name, so we can also fill in the m_class_category
-            m_class_category = m_class;
-          }
-        }
-      }
-    }
-  }
-  return m_class;
+llvm::StringRef ObjCLanguage::MethodName::GetClassNameWithCategory() const {
+  llvm::StringRef full = m_full;
+  const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
+  const size_t space_pos = full.find(' ', class_start_pos);
+  return full.substr(class_start_pos, space_pos - class_start_pos);
 }
 
-ConstString ObjCLanguage::MethodName::GetClassNameWithCategory() {
-  if (!m_class_category) {
-    if (IsValid(false)) {
-      const char *full = m_full.GetCString();
-      const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
-      const char *space_pos = strchr(full, ' ');
-      if (space_pos) {
-        m_class_category.SetCStringWithLength(class_start,
-                                              space_pos - class_start);
-        // If m_class hasn't been filled in and the class with category doesn't
-        // contain a '(', then we can also fill in the m_class
-        if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) 
{
-          m_class = m_class_category;
-          // No '(' was found in the full name, we can definitively say that
-          // our category was valid (and empty).
-          m_category_is_valid = true;
-        }
-      }
-    }
-  }
-  return m_class_category;
+llvm::StringRef ObjCLanguage::MethodName::GetSelector() const {
+  llvm::StringRef full = m_full;
+  const size_t space_pos = full.find(' ');
+  if (space_pos == llvm::StringRef::npos)
+    return llvm::StringRef();
+  const size_t closing_bracket = full.find(']', space_pos);
+  return full.substr(space_pos + 1, closing_bracket - space_pos - 1);
 }
 
-ConstString ObjCLanguage::MethodName::GetSelector() {
-  if (!m_selector) {
-    if (IsValid(false)) {
-      const char *full = m_full.GetCString();
-      const char *space_pos = strchr(full, ' ');
-      if (space_pos) {
-        ++space_pos; // skip the space
-        m_selector.SetCStringWithLength(space_pos, m_full.GetLength() -
-                                                       (space_pos - full) - 1);
-      }
-    }
-  }
-  return m_selector;
-}
+llvm::StringRef ObjCLanguage::MethodName::GetCategory() const {
+  llvm::StringRef full = m_full;
+  const size_t open_paren_pos = full.find('(');
+  const size_t close_paren_pos = full.find(')');
 
-ConstString ObjCLanguage::MethodName::GetCategory() {
-  if (!m_category_is_valid && !m_category) {
-    if (IsValid(false)) {
-      m_category_is_valid = true;
-      const char *full = m_full.GetCString();
-      const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
-      const char *open_paren_pos = strchr(class_start, '(');
-      if (open_paren_pos) {
-        ++open_paren_pos; // Skip the open paren
-        const char *close_paren_pos = strchr(open_paren_pos, ')');
-        if (close_paren_pos)
-          m_category.SetCStringWithLength(open_paren_pos,
-                                          close_paren_pos - open_paren_pos);
-      }
-    }
-  }
-  return m_category;
-}
+  if (open_paren_pos == llvm::StringRef::npos ||
+      close_paren_pos == llvm::StringRef::npos)
+    return llvm::StringRef();
 
-ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory(
-    bool empty_if_no_category) {
-  if (IsValid(false)) {
-    if (HasCategory()) {
-      StreamString strm;
-      if (m_type == eTypeClassMethod)
-        strm.PutChar('+');
-      else if (m_type == eTypeInstanceMethod)
-        strm.PutChar('-');
-      strm.Printf("[%s %s]", GetClassName().GetCString(),
-                  GetSelector().GetCString());
-      return ConstString(strm.GetString());
-    }
+  return full.substr(open_paren_pos + 1,
+                     close_paren_pos - (open_paren_pos + 1));
+}
 
-    if (!empty_if_no_category) {
-      // Just return the full name since it doesn't have a category
-      return GetFullName();
-    }
-  }
-  return ConstString();
+std::string ObjCLanguage::MethodName::GetFullNameWithoutCategory() const {
+  llvm::StringRef full = m_full;
+  const size_t open_paren_pos = full.find('(');
+  const size_t close_paren_pos = full.find(')');
+  if (open_paren_pos == llvm::StringRef::npos ||
+      close_paren_pos == llvm::StringRef::npos)
+    return std::string();
+
+  llvm::StringRef class_name = GetClassName();
+  llvm::StringRef selector_name = GetSelector();
+  std::string name_sans_category;
+
+  if (m_type == eTypeClassMethod)
+    name_sans_category += '+';
+  else if (m_type == eTypeInstanceMethod)
+    name_sans_category += '-';
+
+  name_sans_category += '[';
+  name_sans_category.append(class_name.data(), class_name.size());
+  name_sans_category += ' ';
+  name_sans_category.append(selector_name.data(), selector_name.size());
+  name_sans_category += ']';
+
+  return name_sans_category;
 }
 
 std::vector<Language::MethodNameVariant>
 ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
   std::vector<Language::MethodNameVariant> variant_names;
-  ObjCLanguage::MethodName objc_method(method_name.GetCString(), false);
-  if (!objc_method.IsValid(false)) {
+  std::optional<const ObjCLanguage::MethodName> objc_method =
+      ObjCLanguage::MethodName::Create(method_name.GetStringRef(), false);
+  if (!objc_method)
     return variant_names;
-  }
 
-  variant_names.emplace_back(objc_method.GetSelector(),
+  variant_names.emplace_back(ConstString(objc_method->GetSelector()),
                              lldb::eFunctionNameTypeSelector);
 
-  const bool is_class_method =
-      objc_method.GetType() == MethodName::eTypeClassMethod;
-  const bool is_instance_method =
-      objc_method.GetType() == MethodName::eTypeInstanceMethod;
-  ConstString name_sans_category =
-      objc_method.GetFullNameWithoutCategory(/*empty_if_no_category*/ true);
+  const std::string name_sans_category =
+      objc_method->GetFullNameWithoutCategory();
 
-  if (is_class_method || is_instance_method) {
-    if (name_sans_category)
-      variant_names.emplace_back(name_sans_category,
+  if (objc_method->IsClassMethod() || objc_method->IsInstanceMethod()) {
+    if (!name_sans_category.empty())
+      variant_names.emplace_back(ConstString(name_sans_category.c_str()),
                                  lldb::eFunctionNameTypeFull);
   } else {
     StreamString strm;
 
-    strm.Printf("+%s", objc_method.GetFullName().GetCString());
+    strm.Printf("+%s", objc_method->GetFullName().c_str());
     variant_names.emplace_back(ConstString(strm.GetString()),
                                lldb::eFunctionNameTypeFull);
     strm.Clear();
 
-    strm.Printf("-%s", objc_method.GetFullName().GetCString());
+    strm.Printf("-%s", objc_method->GetFullName().c_str());
     variant_names.emplace_back(ConstString(strm.GetString()),
                                lldb::eFunctionNameTypeFull);
     strm.Clear();
 
-    if (name_sans_category) {
-      strm.Printf("+%s", name_sans_category.GetCString());
+    if (!name_sans_category.empty()) {
+      strm.Printf("+%s", name_sans_category.c_str());
       variant_names.emplace_back(ConstString(strm.GetString()),
                                  lldb::eFunctionNameTypeFull);
       strm.Clear();
 
-      strm.Printf("-%s", name_sans_category.GetCString());
+      strm.Printf("-%s", name_sans_category.c_str());
       variant_names.emplace_back(ConstString(strm.GetString()),
                                  lldb::eFunctionNameTypeFull);
     }
@@ -1020,7 +971,7 @@ std::unique_ptr<Language::TypeScavenger> 
ObjCLanguage::GetTypeScavenger() {
 
     friend class lldb_private::ObjCLanguage;
   };
-  
+
   class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
   public:
     CompilerType AdjustForInclusion(CompilerType &candidate) override {

diff  --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h 
b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 1344e97e469c6..c37fd3d2257bb 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -25,62 +25,98 @@ class ObjCLanguage : public Language {
 public:
   class MethodName {
   public:
-    enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
-
-    MethodName() : m_full(), m_class(), m_category(), m_selector() {}
-
-    MethodName(const char *name, bool strict)
-        : m_full(), m_class(), m_category(), m_selector(),
-          m_type(eTypeUnspecified), m_category_is_valid(false) {
-      SetName(name, strict);
-    }
-    MethodName(llvm::StringRef name, bool strict)
-        : m_full(), m_class(), m_category(), m_selector(),
-          m_type(eTypeUnspecified), m_category_is_valid(false) {
-      SetName(name, strict);
-    }
-
-    void Clear();
-
-    bool IsValid(bool strict) const {
-      // If "strict" is true, the name must have everything specified including
-      // the leading "+" or "-" on the method name
-      if (strict && m_type == eTypeUnspecified)
-        return false;
-      // Other than that, m_full will only be filled in if the objective C
-      // name is valid.
-      return (bool)m_full;
-    }
-
-    bool HasCategory() { return !GetCategory().IsEmpty(); }
-
-    Type GetType() const { return m_type; }
-
-    ConstString GetFullName() const { return m_full; }
+    /// The static factory method for creating a MethodName.
+    ///
+    /// \param[in] name
+    ///   The name of the method.
+    ///
+    /// \param[in] strict
+    ///   Control whether or not the name parser is strict about +/- in the
+    ///   front of the name.
+    ///
+    /// \return If the name failed to parse as a valid Objective-C method name,
+    /// returns std::nullopt. Otherwise returns a const MethodName.
+    static std::optional<const MethodName> Create(llvm::StringRef name,
+                                                  bool strict);
+
+    /// Determines if this method is a class method
+    ///
+    /// \return Returns true if the method is a class method. False otherwise.
+    bool IsClassMethod() const { return m_type == eTypeClassMethod; }
+
+    /// Determines if this method is an instance method
+    ///
+    /// \return Returns true if the method is an instance method. False
+    /// otherwise.
+    bool IsInstanceMethod() const { return m_type == eTypeInstanceMethod; }
+
+    /// Returns the full name of the method.
+    ///
+    /// This includes the class name, the category name (if applicable), and 
the
+    /// selector name.
+    ///
+    /// \return The name of the method in the form of a const std::string
+    /// reference.
+    const std::string &GetFullName() const { return m_full; }
+
+    /// Creates a variation of this method without the category.
+    /// If this method has no category, it returns an empty string.
+    ///
+    /// Example:
+    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
+    ///   becomes "+[NSString myStringWithCString:]"
+    ///
+    /// \return The method name without the category or an empty string if 
there
+    /// was no category to begin with.
+    std::string GetFullNameWithoutCategory() const;
+
+    /// Returns a reference to the class name.
+    ///
+    /// Example:
+    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
+    ///   will give you "NSString"
+    ///
+    /// \return A StringRef to the class name of this method.
+    llvm::StringRef GetClassName() const;
+
+    /// Returns a reference to the class name with the category.
+    ///
+    /// Example:
+    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
+    ///   will give you "NSString(my_additions)"
+    ///
+    /// Note: If your method has no category, this will give the same output as
+    /// `GetClassName`.
+    ///
+    /// \return A StringRef to the class name (including the category) of this
+    /// method. If there was no category, returns the same as `GetClassName`.
+    llvm::StringRef GetClassNameWithCategory() const;
+
+    /// Returns a reference to the category name.
+    ///
+    /// Example:
+    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
+    ///   will give you "my_additions"
+    /// \return A StringRef to the category name of this method. If no category
+    /// is present, the StringRef is empty.
+    llvm::StringRef GetCategory() const;
+
+    /// Returns a reference to the selector name.
+    ///
+    /// Example:
+    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
+    ///   will give you "myStringWithCString:"
+    /// \return A StringRef to the selector of this method.
+    llvm::StringRef GetSelector() const;
 
-    ConstString GetFullNameWithoutCategory(bool empty_if_no_category);
-
-    bool SetName(const char *name, bool strict);
-    bool SetName(llvm::StringRef name, bool strict);
-
-    ConstString GetClassName();
-
-    ConstString GetClassNameWithCategory();
-
-    ConstString GetCategory();
+  protected:
+    enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
 
-    ConstString GetSelector();
+    MethodName(llvm::StringRef name, Type type)
+        : m_full(name.str()), m_type(type) {}
 
-  protected:
-    ConstString
-        m_full; // Full name:   "+[NSString(my_additions) 
myStringWithCString:]"
-    ConstString m_class; // Class name:  "NSString"
-    ConstString
-        m_class_category;   // Class with category: "NSString(my_additions)"
-    ConstString m_category; // Category:    "my_additions"
-    ConstString m_selector; // Selector:    "myStringWithCString:"
-    Type m_type = eTypeUnspecified;
-    bool m_category_is_valid = false;
+    const std::string m_full;
+    Type m_type;
   };
 
   ObjCLanguage() = default;

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 922f50d33581e..a3ade51e1fe5b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -980,10 +980,11 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const 
DWARFDIE &die,
   if (attrs.name) {
     bool type_handled = false;
     if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
-      ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
-      if (objc_method.IsValid(true)) {
+      std::optional<const ObjCLanguage::MethodName> objc_method =
+          ObjCLanguage::MethodName::Create(attrs.name.GetStringRef(), true);
+      if (objc_method) {
         CompilerType class_opaque_type;
-        ConstString class_name(objc_method.GetClassName());
+        ConstString class_name(objc_method->GetClassName());
         if (class_name) {
           TypeSP complete_objc_class_type_sp(
               dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
@@ -2617,13 +2618,19 @@ PropertyAttributes::PropertyAttributes(const DWARFDIE 
&die) {
   // Check if the property getter/setter were provided as full names.
   // We want basenames, so we extract them.
   if (prop_getter_name && prop_getter_name[0] == '-') {
-    ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
-    prop_getter_name = prop_getter_method.GetSelector().GetCString();
+    std::optional<const ObjCLanguage::MethodName> prop_getter_method =
+        ObjCLanguage::MethodName::Create(prop_getter_name, true);
+    if (prop_getter_method)
+      prop_getter_name =
+          ConstString(prop_getter_method->GetSelector()).GetCString();
   }
 
   if (prop_setter_name && prop_setter_name[0] == '-') {
-    ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
-    prop_setter_name = prop_setter_method.GetSelector().GetCString();
+    std::optional<const ObjCLanguage::MethodName> prop_setter_method =
+        ObjCLanguage::MethodName::Create(prop_setter_name, true);
+    if (prop_setter_method)
+      prop_setter_name =
+          ConstString(prop_setter_method->GetSelector()).GetCString();
   }
 
   // If the names haven't been provided, they need to be filled in.

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 1aa83a42b6717..57b962ff60df0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -287,15 +287,16 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
           bool is_objc_method = false;
           if (cu_language == eLanguageTypeObjC ||
               cu_language == eLanguageTypeObjC_plus_plus) {
-            ObjCLanguage::MethodName objc_method(name, true);
-            if (objc_method.IsValid(true)) {
+            std::optional<const ObjCLanguage::MethodName> objc_method =
+                ObjCLanguage::MethodName::Create(name, true);
+            if (objc_method) {
               is_objc_method = true;
               ConstString class_name_with_category(
-                  objc_method.GetClassNameWithCategory());
-              ConstString objc_selector_name(objc_method.GetSelector());
+                  objc_method->GetClassNameWithCategory());
+              ConstString objc_selector_name(objc_method->GetSelector());
               ConstString objc_fullname_no_category_name(
-                  objc_method.GetFullNameWithoutCategory(true));
-              ConstString class_name_no_category(objc_method.GetClassName());
+                  objc_method->GetFullNameWithoutCategory().c_str());
+              ConstString class_name_no_category(objc_method->GetClassName());
               set.function_fullnames.Insert(ConstString(name), ref);
               if (class_name_with_category)
                 set.objc_class_selectors.Insert(class_name_with_category, ref);

diff  --git a/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp 
b/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp
index 683b16d5dcbed..59cc51b6ce08c 100644
--- a/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp
+++ b/lldb/unittests/Language/ObjC/ObjCLanguageTest.cpp
@@ -42,53 +42,51 @@ TEST(ObjCLanguage, MethodNameParsing) {
 
   // First, be strict
   for (const auto &test : strict_cases) {
-    ObjCLanguage::MethodName method(test.input, /*strict = */ true);
-    EXPECT_TRUE(method.IsValid(/*strict = */ true));
-    EXPECT_EQ(
-        test.full_name_sans_category,
-        method.GetFullNameWithoutCategory(/*empty_if_no_category = */ true)
-            .GetStringRef());
-    EXPECT_EQ(test.class_name, method.GetClassName().GetStringRef());
+    std::optional<const ObjCLanguage::MethodName> method =
+        ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
+    EXPECT_TRUE(method.has_value());
+    EXPECT_EQ(test.full_name_sans_category,
+              method->GetFullNameWithoutCategory());
+    EXPECT_EQ(test.class_name, method->GetClassName());
     EXPECT_EQ(test.class_name_with_category,
-              method.GetClassNameWithCategory().GetStringRef());
-    EXPECT_EQ(test.category, method.GetCategory().GetStringRef());
-    EXPECT_EQ(test.selector, method.GetSelector().GetStringRef());
+              method->GetClassNameWithCategory());
+    EXPECT_EQ(test.category, method->GetCategory());
+    EXPECT_EQ(test.selector, method->GetSelector());
   }
 
   // We should make sure strict parsing does not accept lax cases
   for (const auto &test : lax_cases) {
-    ObjCLanguage::MethodName method(test.input, /*strict = */ true);
-    EXPECT_FALSE(method.IsValid(/*strict = */ true));
+    std::optional<const ObjCLanguage::MethodName> method =
+        ObjCLanguage::MethodName::Create(test.input, /*strict = */ true);
+    EXPECT_FALSE(method.has_value());
   }
 
   // All strict cases should work when not lax
   for (const auto &test : strict_cases) {
-    ObjCLanguage::MethodName method(test.input, /*strict = */ false);
-    EXPECT_TRUE(method.IsValid(/*strict = */ false));
-    EXPECT_EQ(
-        test.full_name_sans_category,
-        method.GetFullNameWithoutCategory(/*empty_if_no_category = */ true)
-            .GetStringRef());
-    EXPECT_EQ(test.class_name, method.GetClassName().GetStringRef());
+    std::optional<const ObjCLanguage::MethodName> method =
+        ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
+    EXPECT_TRUE(method.has_value());
+    EXPECT_EQ(test.full_name_sans_category,
+              method->GetFullNameWithoutCategory());
+    EXPECT_EQ(test.class_name, method->GetClassName());
     EXPECT_EQ(test.class_name_with_category,
-              method.GetClassNameWithCategory().GetStringRef());
-    EXPECT_EQ(test.category, method.GetCategory().GetStringRef());
-    EXPECT_EQ(test.selector, method.GetSelector().GetStringRef());
+              method->GetClassNameWithCategory());
+    EXPECT_EQ(test.category, method->GetCategory());
+    EXPECT_EQ(test.selector, method->GetSelector());
   }
 
   // Make sure non-strict parsing works
   for (const auto &test : lax_cases) {
-    ObjCLanguage::MethodName method(test.input, /*strict = */ false);
-    EXPECT_TRUE(method.IsValid(/*strict = */ false));
-    EXPECT_EQ(
-        test.full_name_sans_category,
-        method.GetFullNameWithoutCategory(/*empty_if_no_category = */ true)
-            .GetStringRef());
-    EXPECT_EQ(test.class_name, method.GetClassName().GetStringRef());
+    std::optional<const ObjCLanguage::MethodName> method =
+        ObjCLanguage::MethodName::Create(test.input, /*strict = */ false);
+    EXPECT_TRUE(method.has_value());
+    EXPECT_EQ(test.full_name_sans_category,
+              method->GetFullNameWithoutCategory());
+    EXPECT_EQ(test.class_name, method->GetClassName());
     EXPECT_EQ(test.class_name_with_category,
-              method.GetClassNameWithCategory().GetStringRef());
-    EXPECT_EQ(test.category, method.GetCategory().GetStringRef());
-    EXPECT_EQ(test.selector, method.GetSelector().GetStringRef());
+              method->GetClassNameWithCategory());
+    EXPECT_EQ(test.category, method->GetCategory());
+    EXPECT_EQ(test.selector, method->GetSelector());
   }
 }
 
@@ -105,10 +103,12 @@ TEST(ObjCLanguage, InvalidMethodNameParsing) {
                                   "[]"};
 
   for (const auto &name : test_cases) {
-    ObjCLanguage::MethodName strict_method(name, /*strict = */ true);
-    EXPECT_FALSE(strict_method.IsValid(true));
+    std::optional<const ObjCLanguage::MethodName> strict_method =
+        ObjCLanguage::MethodName::Create(name, /*strict = */ false);
+    EXPECT_FALSE(strict_method.has_value());
 
-    ObjCLanguage::MethodName lax_method(name, /*strict = */ false);
-    EXPECT_FALSE(lax_method.IsValid(true));
+    std::optional<const ObjCLanguage::MethodName> lax_method =
+        ObjCLanguage::MethodName::Create(name, /*strict = */ false);
+    EXPECT_FALSE(lax_method.has_value());
   }
 }


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to