sivachandra created this revision.
sivachandra added reviewers: spyffe, clayborg.
sivachandra added a subscriber: lldb-commits.
This, in a way, extends the existing "workaroud" by matching function
argument type names individually [instead of just matching "(args1...)"
with "(args2...)"]. For type name matching, a new method
CPlusPlusLanguage::TypeNamesEqual has been added. For now, this method
can only handle variations like:
<typename> * vs <typename>*
const <typename> vs <typename> const
const <typename> * const vs <typename> const * const
We can extend it to handle more complex name formats as needed.
The immediate benefit of this change is with evaluating std::map's
subscript operator when producer is GCC. Consider the following:
std::map<std::string, std::string> m;
std::string s("1");
m[s] = "one";
... ; // Break here
The command "expr m[s]" fails without this change if the producer is
GCC.
http://reviews.llvm.org/D17618
Files:
include/lldb/Symbol/SymbolFile.h
packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp
source/Expression/IRExecutionUnit.cpp
source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
source/Symbol/SymbolFile.cpp
unittests/CMakeLists.txt
unittests/Language/CMakeLists.txt
unittests/Language/CPlusPlus/CMakeLists.txt
unittests/Language/CPlusPlus/TypeNamesEqualityTest.cpp
Index: unittests/Language/CPlusPlus/TypeNamesEqualityTest.cpp
===================================================================
--- /dev/null
+++ unittests/Language/CPlusPlus/TypeNamesEqualityTest.cpp
@@ -0,0 +1,32 @@
+//===-- ScalarTest.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 "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+
+using namespace lldb_private;
+
+TEST(TypeNamesEqualTest, Equality)
+{
+ ASSERT_TRUE(CPlusPlusLanguage::TypeNamesEqual("int *", "int*"));
+ ASSERT_TRUE(CPlusPlusLanguage::TypeNamesEqual("unsigned int *", "unsigned int*"));
+ ASSERT_TRUE(CPlusPlusLanguage::TypeNamesEqual("const unsigned int", "unsigned int const"));
+ ASSERT_TRUE(CPlusPlusLanguage::TypeNamesEqual("const unsigned int *", "unsigned int const *"));
+ ASSERT_TRUE(CPlusPlusLanguage::TypeNamesEqual("unsigned int * const", "unsigned int * const"));
+}
+
+TEST(TypeNamesEqualTest, InEquality)
+{
+ ASSERT_FALSE(CPlusPlusLanguage::TypeNamesEqual("int *", "short int*"));
+ ASSERT_FALSE(CPlusPlusLanguage::TypeNamesEqual("unsigned int *", "unsigned int"));
+ ASSERT_FALSE(CPlusPlusLanguage::TypeNamesEqual("const unsigned int", "int const"));
+ ASSERT_FALSE(CPlusPlusLanguage::TypeNamesEqual("const unsigned int *", "unsigned int * const"));
+ ASSERT_FALSE(CPlusPlusLanguage::TypeNamesEqual("unsigned int const *", "unsigned int * const"));
+}
Index: unittests/Language/CPlusPlus/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/Language/CPlusPlus/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_lldb_unittest(LLDBCPlusCPlusLanguageTests
+ TypeNamesEqualityTest.cpp
+ )
+
+ target_link_libraries(lldbPluginCPlusPlusLanguage)
Index: unittests/Language/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/Language/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(CPlusPlus)
Index: unittests/CMakeLists.txt
===================================================================
--- unittests/CMakeLists.txt
+++ unittests/CMakeLists.txt
@@ -28,5 +28,6 @@
add_subdirectory(Expression)
add_subdirectory(Host)
add_subdirectory(Interpreter)
+add_subdirectory(Language)
add_subdirectory(ScriptInterpreter)
add_subdirectory(Utility)
Index: source/Symbol/SymbolFile.cpp
===================================================================
--- source/Symbol/SymbolFile.cpp
+++ source/Symbol/SymbolFile.cpp
@@ -135,7 +135,10 @@
}
void
-SymbolFile::GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names)
+SymbolFile::GetMangledNamesForFunction(const SymbolContext &sc,
+ const std::string &scope_qualified_name,
+ const std::vector<std::string> &arguments,
+ std::vector<ConstString> &mangled_names)
{
return;
}
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -209,7 +209,9 @@
lldb_private::SymbolContextList& sc_list) override;
void
- GetMangledNamesForFunction (const std::string &scope_qualified_name,
+ GetMangledNamesForFunction (const lldb_private::SymbolContext& sc,
+ const std::string &scope_qualified_name,
+ const std::vector<std::string> &arguments,
std::vector<lldb_private::ConstString> &mangled_names) override;
uint32_t
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2966,7 +2966,9 @@
}
void
-SymbolFileDWARF::GetMangledNamesForFunction (const std::string &scope_qualified_name,
+SymbolFileDWARF::GetMangledNamesForFunction (const SymbolContext& sc,
+ const std::string &scope_qualified_name,
+ const std::vector<std::string> &arguments,
std::vector<ConstString> &mangled_names)
{
DWARFDebugInfo* info = DebugInfo();
@@ -2982,18 +2984,42 @@
SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
if (dwo)
- dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names);
+ dwo->GetMangledNamesForFunction(sc, scope_qualified_name, arguments, mangled_names);
}
NameToOffsetMap::iterator iter = m_function_scope_qualified_name_map.find(scope_qualified_name);
if (iter == m_function_scope_qualified_name_map.end())
return;
+ size_t arg_count = arguments.size();
DIERefSetSP set_sp = (*iter).second;
std::set<DIERef>::iterator set_iter;
for (set_iter = set_sp->begin(); set_iter != set_sp->end(); set_iter++)
{
DWARFDIE die = DebugInfo()->GetDIE (*set_iter);
+
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, NULL);
+ CompilerType compiler_type = type_sp->GetFullCompilerType();
+
+ if (compiler_type.GetNumberOfFunctionArguments() != arg_count)
+ continue;
+
+ size_t match_count = 0;
+ for (size_t i = 0; i < compiler_type.GetNumberOfFunctionArguments(); i++)
+ {
+ std::string arg_type = compiler_type.GetFunctionArgumentAtIndex(i).GetTypeName().AsCString();
+ if (CPlusPlusLanguage::TypeNamesEqual(llvm::StringRef(arguments[i]), llvm::StringRef(arg_type)))
+ match_count++;
+ else
+ break;
+ }
+
+ if (match_count != arg_count)
+ continue;
+
mangled_names.push_back(ConstString(die.GetMangledName()));
}
}
Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
===================================================================
--- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -99,20 +99,23 @@
llvm::StringRef
GetContext ();
- llvm::StringRef
+ const std::vector<std::string> &
GetArguments ();
llvm::StringRef
GetQualifiers ();
protected:
void
Parse();
+
+ void
+ SetArguments(const llvm::StringRef &arg_string);
ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
- llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ std::vector<std::string> m_arguments; // Arguments: "(unsigned int)"
llvm::StringRef m_qualifiers; // Qualifiers: "const"
Type m_type;
bool m_parsed;
@@ -137,7 +140,7 @@
HardcodedFormatters::HardcodedSyntheticFinder
GetHardcodedSynthetics () override;
-
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -165,6 +168,9 @@
static bool
ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier);
+
+ static bool
+ TypeNamesEqual(const llvm::StringRef &t1, const llvm::StringRef &t2);
// in some cases, compilers will output different names for one same type. when that happens, it might be impossible
// to construct SBType objects for a valid type, because the name that is available is not the same as the name that
Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -89,7 +89,7 @@
m_full.Clear();
m_basename = llvm::StringRef();
m_context = llvm::StringRef();
- m_arguments = llvm::StringRef();
+ m_arguments = std::vector<std::string>();
m_qualifiers = llvm::StringRef();
m_type = eTypeInvalid;
m_parsed = false;
@@ -195,7 +195,7 @@
llvm::StringRef parens("()", 2);
if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
{
- m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+ SetArguments(full.substr(arg_start, arg_end - arg_start + 1));
if (arg_end + 1 < full.size())
m_qualifiers = full.substr(arg_end + 1);
if (arg_start > 0)
@@ -253,7 +253,7 @@
// be a valid C++ method, clear everything out and indicate an error
m_context = llvm::StringRef();
m_basename = llvm::StringRef();
- m_arguments = llvm::StringRef();
+ m_arguments = std::vector<std::string>();
m_qualifiers = llvm::StringRef();
m_parse_error = true;
}
@@ -281,14 +281,61 @@
return m_context;
}
-llvm::StringRef
+const std::vector<std::string> &
CPlusPlusLanguage::MethodName::GetArguments ()
{
if (!m_parsed)
Parse();
return m_arguments;
}
+void
+CPlusPlusLanguage::MethodName::SetArguments(const llvm::StringRef &arg_str)
+{
+ // Remove the open and close parenthesis.
+ llvm::StringRef input = arg_str.substr(1, arg_str.size() - 2);
+ int paren_count = 0;
+ int angle_count = 0;
+
+ std::string arg;
+ for (size_t i = 0; i < input.size(); i++)
+ {
+ char c = input[i];
+ switch (c)
+ {
+ case ',':
+ if (paren_count == 0 && angle_count == 0)
+ {
+ m_arguments.push_back(arg.substr());
+ arg.erase();
+ continue;
+ }
+ case '(':
+ paren_count++;
+ break;
+ case '<':
+ angle_count++;
+ break;
+ case ')':
+ paren_count--;
+ break;
+ case '>':
+ angle_count--;
+ break;
+ case ' ':
+ if (arg.size() == 0)
+ continue;
+ default:
+ break;
+ }
+
+ arg.push_back(c);
+ }
+
+ if (arg.size() > 0)
+ m_arguments.push_back(arg);
+}
+
llvm::StringRef
CPlusPlusLanguage::MethodName::GetQualifiers ()
{
@@ -313,6 +360,54 @@
return res;
}
+bool CPlusPlusLanguage::TypeNamesEqual (const llvm::StringRef &t1, const llvm::StringRef &t2)
+{
+ llvm::StringRef r1 = t1.trim();
+ llvm::StringRef r2 = t2.trim();
+
+ if (r1 == r2)
+ return true;
+
+ char last = r1.back();
+ if (last == '&' || last == '*')
+ {
+ if (r2.back() != last)
+ return false;
+
+ return CPlusPlusLanguage::TypeNamesEqual(r1.drop_back(), r2.drop_back());
+ }
+
+ if (r1.endswith("const"))
+ {
+ // If both end with "const", drop strlen("const") from the back and compare.
+ if (r2.endswith("const"))
+ return CPlusPlusLanguage::TypeNamesEqual(r1.drop_back(5), r2.drop_back(5));
+
+ // If r2 starts with "const", then drop strlen("const") from its front and
+ // compare with r1 after dropping strlen("const") from its back.
+ if (r2.startswith("const"))
+ return CPlusPlusLanguage::TypeNamesEqual(r1.drop_back(5), r2.drop_front(5));
+
+ return false;
+ }
+
+ if (r1.startswith("const"))
+ {
+ // If both start with "const", drop strlen("const") from the front and compare.
+ if (r2.startswith("const"))
+ return CPlusPlusLanguage::TypeNamesEqual(r1.drop_front(5), r2.drop_front(5));
+
+ // If r2 ends with "const", then drop strlen("const") from its back and
+ // compare with r1 after dropping strlen("const") from its front.
+ if (r2.endswith("const"))
+ return CPlusPlusLanguage::TypeNamesEqual(r1.drop_front(5), r2.drop_back(5));
+
+ return false;
+ }
+
+ return false;
+}
+
bool
CPlusPlusLanguage::IsCPPMangledName (const char *name)
{
Index: source/Expression/IRExecutionUnit.cpp
===================================================================
--- source/Expression/IRExecutionUnit.cpp
+++ source/Expression/IRExecutionUnit.cpp
@@ -653,6 +653,7 @@
{
CPlusPlusLanguage::MethodName cpp_name(demangled);
std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
+ const std::vector<std::string> &arguments = cpp_name.GetArguments();
if (!scope_qualified_name.size())
return ConstString();
@@ -669,7 +670,7 @@
return ConstString();
std::vector<ConstString> alternates;
- sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);
+ sym_file->GetMangledNamesForFunction(sym_ctx, scope_qualified_name, arguments, alternates);
std::vector<ConstString> param_and_qual_matches;
std::vector<ConstString> param_matches;
@@ -683,13 +684,10 @@
if (!cpp_name.IsValid())
continue;
- if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments())
- {
if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
param_and_qual_matches.push_back(alternate_mangled_name);
else
param_matches.push_back(alternate_mangled_name);
- }
}
if (param_and_qual_matches.size())
Index: packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp
===================================================================
--- packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp
+++ packages/Python/lldbsuite/test/lang/cpp/stl/main.cpp
@@ -13,11 +13,14 @@
int main (int argc, char const *argv[])
{
std::string hello_world ("Hello World!");
+ std::string str("a_string");
std::cout << hello_world << std::endl;
std::cout << hello_world.length() << std::endl;
std::cout << hello_world[11] << std::endl;
std::map<std::string, int> associative_array;
+ std::map<std::string, std::string> ssmap;
+ ssmap[str] = hello_world;
std::cout << "size of upon construction associative_array: " << associative_array.size() << std::endl;
associative_array[hello_world] = 1;
associative_array["hello"] = 2;
Index: packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
===================================================================
--- packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
+++ packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
@@ -24,6 +24,23 @@
self.source = 'main.cpp'
self.line = line_number(self.source, '// Set break point at this line.')
+ def test_string_maps(self):
+ self.build()
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
+ self.runCmd("run", RUN_SUCCEEDED)
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs = ['main.cpp:%d' % self.line,
+ 'stop reason = breakpoint'])
+
+ self.expect('expr associative_array[hello_world]',
+ substrs = [' = 1'])
+ self.expect('expr ssmap[str]',
+ substrs = [' = "Hello World!"'])
+
# rdar://problem/10400981
@unittest2.expectedFailure
def test(self):
Index: include/lldb/Symbol/SymbolFile.h
===================================================================
--- include/lldb/Symbol/SymbolFile.h
+++ include/lldb/Symbol/SymbolFile.h
@@ -146,7 +146,7 @@
virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap& types);
virtual size_t FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
- virtual void GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names);
+ virtual void GetMangledNamesForFunction(const SymbolContext& sc, const std::string &scope_qualified_name, const std::vector<std::string> &arguments, std::vector<ConstString> &mangled_names);
// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
virtual TypeList * GetTypeList ();
virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits