tberghammer created this revision.
tberghammer added a reviewer: clayborg.
tberghammer added a subscriber: lldb-commits.
Herald added a subscriber: mgorny.
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.
https://reviews.llvm.org/D28466
Files:
source/Symbol/Type.cpp
unittests/Symbol/CMakeLists.txt
unittests/Symbol/TestType.cpp
Index: unittests/Symbol/TestType.cpp
===================================================================
--- /dev/null
+++ unittests/Symbol/TestType.cpp
@@ -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) {
+ std::string 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>");
+}
Index: unittests/Symbol/CMakeLists.txt
===================================================================
--- unittests/Symbol/CMakeLists.txt
+++ unittests/Symbol/CMakeLists.txt
@@ -1,3 +1,4 @@
add_lldb_unittest(SymbolTests
TestClangASTContext.cpp
+ TestType.cpp
)
Index: source/Symbol/Type.cpp
===================================================================
--- source/Symbol/Type.cpp
+++ source/Symbol/Type.cpp
@@ -623,47 +623,62 @@
bool Type::GetTypeScopeAndBasename(const char *&name_cstr, std::string &scope,
std::string &basename,
TypeClass &type_class) {
+ type_class = eTypeClassAny;
+
// Protect against null c string.
+ if (!name_cstr || !name_cstr[0])
+ return false;
- type_class = eTypeClassAny;
+ 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;
+ }
- 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;
+ const char *basename_cstr = name_cstr;
+ const char *namespace_separator = ::strstr(basename_cstr, "::");
+ const char *template_arg_char = ::strchr(basename_cstr, '<');
+ if (!namespace_separator)
+ return false;
+
+ while (namespace_separator) {
+ if (template_arg_char && namespace_separator > template_arg_char) {
+ const char *template_end = template_arg_char + 1;
+ size_t template_depth = 1;
+ while (template_depth > 0 && *template_end) {
+ if (*template_end == '<')
+ template_depth++;
+ else if (*template_end == '>')
+ template_depth--;
+ template_end++;
}
+ if (template_depth != 0)
+ return false; // We have an invalid type name. Bail out.
+ if (!template_end[0])
+ break; // The template ends at the end of the full name.
+ basename_cstr = template_end;
+ } else {
+ basename_cstr = namespace_separator + 2;
}
+ namespace_separator = strstr(basename_cstr, "::");
+ template_arg_char = ::strchr(basename_cstr, '<');
+ }
+ if (basename_cstr > name_cstr) {
+ scope.assign(name_cstr, basename_cstr - name_cstr);
+ basename.assign(basename_cstr);
+ return true;
}
return false;
}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits