[Lldb-commits] [lldb] r291559 - Improve Type::GetTypeScopeAndBasenameHelper and add unit tests

Tamas Berghammer via lldb-commits lldb-commits at lists.llvm.org
Tue Jan 10 03:13:59 PST 2017


Author: tberghammer
Date: Tue Jan 10 05:13:59 2017
New Revision: 291559

URL: http://llvm.org/viewvc/llvm-project?rev=291559&view=rev
Log:
Improve Type::GetTypeScopeAndBasenameHelper and add unit tests

Previously it failed to handle nested types inside templated classes
making it impossible to look up these types using the fully qualified
name.

Differential revision: https://reviews.llvm.org/D28466

Added:
    lldb/trunk/unittests/Symbol/TestType.cpp
Modified:
    lldb/trunk/include/lldb/Symbol/Type.h
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Symbol/Type.cpp
    lldb/trunk/source/Symbol/TypeList.cpp
    lldb/trunk/source/Symbol/TypeMap.cpp
    lldb/trunk/unittests/Symbol/CMakeLists.txt

Modified: lldb/trunk/include/lldb/Symbol/Type.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Type.h?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Type.h (original)
+++ lldb/trunk/include/lldb/Symbol/Type.h Tue Jan 10 05:13:59 2017
@@ -201,8 +201,9 @@ public:
 
   // From a fully qualified typename, split the type into the type basename
   // and the remaining type scope (namespaces/classes).
-  static bool GetTypeScopeAndBasename(const char *&name_cstr,
-                                      std::string &scope, std::string &basename,
+  static bool GetTypeScopeAndBasename(const llvm::StringRef& name,
+                                      llvm::StringRef &scope,
+                                      llvm::StringRef &basename,
                                       lldb::TypeClass &type_class);
   void SetEncodingType(Type *encoding_type) { m_encoding_type = encoding_type; }
 

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Tue Jan 10 05:13:59 2017
@@ -995,8 +995,8 @@ size_t Module::FindTypes(
     TypeList &types) {
   size_t num_matches = 0;
   const char *type_name_cstr = name.GetCString();
-  std::string type_scope;
-  std::string type_basename;
+  llvm::StringRef type_scope;
+  llvm::StringRef type_basename;
   const bool append = true;
   TypeClass type_class = eTypeClassAny;
   TypeMap typesmap;
@@ -1006,13 +1006,9 @@ size_t Module::FindTypes(
     // from the root namespace and implies and exact match. The typenames we
     // get back from clang do not start with "::" so we need to strip this off
     // in order to get the qualified names to match
+    exact_match = type_scope.consume_front("::");
 
-    if (type_scope.size() >= 2 && type_scope[0] == ':' &&
-        type_scope[1] == ':') {
-      type_scope.erase(0, 2);
-      exact_match = true;
-    }
-    ConstString type_basename_const_str(type_basename.c_str());
+    ConstString type_basename_const_str(type_basename);
     if (FindTypes_Impl(sc, type_basename_const_str, nullptr, append,
                        max_matches, searched_symbol_files, typesmap)) {
       typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,

Modified: lldb/trunk/source/Symbol/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Type.cpp?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Type.cpp (original)
+++ lldb/trunk/source/Symbol/Type.cpp Tue Jan 10 05:13:59 2017
@@ -620,50 +620,59 @@ ConstString Type::GetQualifiedName() {
   return GetForwardCompilerType().GetConstTypeName();
 }
 
-bool Type::GetTypeScopeAndBasename(const char *&name_cstr, std::string &scope,
-                                   std::string &basename,
+bool Type::GetTypeScopeAndBasename(const llvm::StringRef& name,
+                                   llvm::StringRef &scope,
+                                   llvm::StringRef &basename,
                                    TypeClass &type_class) {
-  // Protect against null c string.
-
   type_class = eTypeClassAny;
 
-  if (name_cstr && name_cstr[0]) {
-    llvm::StringRef name_strref(name_cstr);
-    if (name_strref.startswith("struct ")) {
-      name_cstr += 7;
-      type_class = eTypeClassStruct;
-    } else if (name_strref.startswith("class ")) {
-      name_cstr += 6;
-      type_class = eTypeClassClass;
-    } else if (name_strref.startswith("union ")) {
-      name_cstr += 6;
-      type_class = eTypeClassUnion;
-    } else if (name_strref.startswith("enum ")) {
-      name_cstr += 5;
-      type_class = eTypeClassEnumeration;
-    } else if (name_strref.startswith("typedef ")) {
-      name_cstr += 8;
-      type_class = eTypeClassTypedef;
-    }
-    const char *basename_cstr = name_cstr;
-    const char *namespace_separator = ::strstr(basename_cstr, "::");
-    if (namespace_separator) {
-      const char *template_arg_char = ::strchr(basename_cstr, '<');
-      while (namespace_separator != nullptr) {
-        if (template_arg_char &&
-            namespace_separator > template_arg_char) // but namespace'd template
-                                                     // arguments are still good
-                                                     // to go
-          break;
-        basename_cstr = namespace_separator + 2;
-        namespace_separator = strstr(basename_cstr, "::");
-      }
-      if (basename_cstr > name_cstr) {
-        scope.assign(name_cstr, basename_cstr - name_cstr);
-        basename.assign(basename_cstr);
-        return true;
+  if (name.empty())
+    return false;
+
+  basename = name;
+  if (basename.consume_front("struct "))
+    type_class = eTypeClassStruct;
+  else if (basename.consume_front("class "))
+    type_class = eTypeClassClass;
+  else if (basename.consume_front("union "))
+    type_class = eTypeClassUnion;
+  else if (basename.consume_front("enum "))
+    type_class = eTypeClassEnumeration;
+  else if (basename.consume_front("typedef "))
+    type_class = eTypeClassTypedef;
+
+  size_t namespace_separator = basename.find("::");
+  if (namespace_separator == llvm::StringRef::npos)
+    return false;
+
+  size_t template_begin = basename.find('<');
+  while (namespace_separator != llvm::StringRef::npos) {
+    if (template_begin != llvm::StringRef::npos &&
+        namespace_separator > template_begin) {
+      size_t template_depth = 1;
+      llvm::StringRef template_arg =
+          basename.drop_front(template_begin + 1);
+      while (template_depth > 0 && !template_arg.empty()) {
+        if (template_arg.front() == '<')
+          template_depth++;
+        else if (template_arg.front() == '>')
+          template_depth--;
+        template_arg = template_arg.drop_front(1);
       }
+      if (template_depth != 0)
+        return false; // We have an invalid type name. Bail out.
+      if (template_arg.empty())
+        break; // The template ends at the end of the full name.
+      basename = template_arg;
+    } else {
+      basename = basename.drop_front(namespace_separator + 2);
     }
+    template_begin = basename.find('<');
+    namespace_separator = basename.find("::");
+  }
+  if (basename.size() < name.size()) {
+    scope = name.take_front(name.size() - basename.size());
+    return true;
   }
   return false;
 }

Modified: lldb/trunk/source/Symbol/TypeList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/TypeList.cpp?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/TypeList.cpp (original)
+++ lldb/trunk/source/Symbol/TypeList.cpp Tue Jan 10 05:13:59 2017
@@ -108,13 +108,13 @@ void TypeList::Dump(Stream *s, bool show
 
 void TypeList::RemoveMismatchedTypes(const char *qualified_typename,
                                      bool exact_match) {
-  std::string type_scope;
-  std::string type_basename;
+  llvm::StringRef type_scope;
+  llvm::StringRef type_basename;
   TypeClass type_class = eTypeClassAny;
   if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope,
                                      type_basename, type_class)) {
     type_basename = qualified_typename;
-    type_scope.clear();
+    type_scope = "";
   }
   return RemoveMismatchedTypes(type_scope, type_basename, type_class,
                                exact_match);
@@ -145,8 +145,8 @@ void TypeList::RemoveMismatchedTypes(con
     ConstString match_type_name_const_str(the_type->GetQualifiedName());
     if (match_type_name_const_str) {
       const char *match_type_name = match_type_name_const_str.GetCString();
-      std::string match_type_scope;
-      std::string match_type_basename;
+      llvm::StringRef match_type_scope;
+      llvm::StringRef match_type_basename;
       if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope,
                                         match_type_basename,
                                         match_type_class)) {

Modified: lldb/trunk/source/Symbol/TypeMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/TypeMap.cpp?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/TypeMap.cpp (original)
+++ lldb/trunk/source/Symbol/TypeMap.cpp Tue Jan 10 05:13:59 2017
@@ -152,13 +152,13 @@ void TypeMap::Dump(Stream *s, bool show_
 
 void TypeMap::RemoveMismatchedTypes(const char *qualified_typename,
                                     bool exact_match) {
-  std::string type_scope;
-  std::string type_basename;
+  llvm::StringRef type_scope;
+  llvm::StringRef type_basename;
   TypeClass type_class = eTypeClassAny;
   if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope,
                                      type_basename, type_class)) {
     type_basename = qualified_typename;
-    type_scope.clear();
+    type_scope = "";
   }
   return RemoveMismatchedTypes(type_scope, type_basename, type_class,
                                exact_match);
@@ -189,8 +189,8 @@ void TypeMap::RemoveMismatchedTypes(cons
     ConstString match_type_name_const_str(the_type->GetQualifiedName());
     if (match_type_name_const_str) {
       const char *match_type_name = match_type_name_const_str.GetCString();
-      std::string match_type_scope;
-      std::string match_type_basename;
+      llvm::StringRef match_type_scope;
+      llvm::StringRef match_type_basename;
       if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope,
                                         match_type_basename,
                                         match_type_class)) {

Modified: lldb/trunk/unittests/Symbol/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Symbol/CMakeLists.txt?rev=291559&r1=291558&r2=291559&view=diff
==============================================================================
--- lldb/trunk/unittests/Symbol/CMakeLists.txt (original)
+++ lldb/trunk/unittests/Symbol/CMakeLists.txt Tue Jan 10 05:13:59 2017
@@ -1,3 +1,4 @@
 add_lldb_unittest(SymbolTests
   TestClangASTContext.cpp
+  TestType.cpp
   )

Added: lldb/trunk/unittests/Symbol/TestType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Symbol/TestType.cpp?rev=291559&view=auto
==============================================================================
--- lldb/trunk/unittests/Symbol/TestType.cpp (added)
+++ lldb/trunk/unittests/Symbol/TestType.cpp Tue Jan 10 05:13:59 2017
@@ -0,0 +1,51 @@
+//===-- TestType.cpp --------------------------------------------*- C++ -*-===//
+//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Symbol/Type.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+void TestGetTypeScopeAndBasenameHelper(const char *full_type,
+                                       bool expected_is_scoped,
+                                       const char *expected_scope,
+                                       const char *expected_name) {
+  llvm::StringRef scope, name;
+  lldb::TypeClass type_class;
+  bool is_scoped =
+      Type::GetTypeScopeAndBasename(full_type, scope, name, type_class);
+  EXPECT_EQ(is_scoped, expected_is_scoped);
+  if (expected_is_scoped) {
+    EXPECT_EQ(scope, expected_scope);
+    EXPECT_EQ(name, expected_name);
+  }
+}
+};
+
+TEST(Type, GetTypeScopeAndBasename) {
+  TestGetTypeScopeAndBasenameHelper("int", false, "", "");
+  TestGetTypeScopeAndBasenameHelper("std::string", true, "std::", "string");
+  TestGetTypeScopeAndBasenameHelper("std::set<int>", true, "std::", "set<int>");
+  TestGetTypeScopeAndBasenameHelper("std::set<int, std::less<int>>", true,
+                                    "std::", "set<int, std::less<int>>");
+  TestGetTypeScopeAndBasenameHelper("std::string::iterator", true,
+                                    "std::string::", "iterator");
+  TestGetTypeScopeAndBasenameHelper("std::set<int>::iterator", true,
+                                    "std::set<int>::", "iterator");
+  TestGetTypeScopeAndBasenameHelper(
+      "std::set<int, std::less<int>>::iterator", true,
+      "std::set<int, std::less<int>>::", "iterator");
+  TestGetTypeScopeAndBasenameHelper(
+      "std::set<int, std::less<int>>::iterator<bool>", true,
+      "std::set<int, std::less<int>>::", "iterator<bool>");
+}




More information about the lldb-commits mailing list