EwanCrawford updated this revision to Diff 51182.
EwanCrawford added a comment.
Rebased on tip
Repository:
rL LLVM
http://reviews.llvm.org/D17957
Files:
packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/Makefile
packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/TestCallOverloadedCFunction.py
packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/main.c
source/Expression/IRExecutionUnit.cpp
source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
===================================================================
--- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -174,6 +174,11 @@
static uint32_t
FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents);
+ // Given a mangled function name, calculates some alternative manglings
+ // since the compiler mangling may not line up with the symbol we are expecting
+ static uint32_t
+ FindAlternateFunctionMangling(ConstString mangled_name, std::vector<ConstString>& alternates);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -482,6 +482,85 @@
return count;
}
+// Given a mangled function, replaces all the function parameters of mangled type
+// 'search', with parameters of type 'replace'.
+static ConstString
+SubstituteMangledParameters(const llvm::StringRef& mangled, const llvm::StringRef& search, const llvm::StringRef& replace)
+{
+ // Find length of function name, already encoded in mangled symbol
+ static const llvm::StringRef numeric_digits("0123456789");
+ const size_t encoded_length_start = mangled.find_first_of(numeric_digits);
+ if (encoded_length_start == llvm::StringRef::npos)
+ return ConstString();
+
+ const size_t encoded_length_end = mangled.find_first_not_of(numeric_digits, encoded_length_start);
+ if (encoded_length_end == llvm::StringRef::npos || encoded_length_end <= encoded_length_start)
+ return ConstString();
+
+ // Parse encoded length into name_length
+ int name_length;
+ const llvm::StringRef encoded_length_str = mangled.substr(encoded_length_start, encoded_length_end - encoded_length_start);
+ if (encoded_length_str.getAsInteger(10, name_length) || name_length == 0)
+ return ConstString();
+
+ // Position in 'mangled' string of first function parameter
+ size_t param_pos = encoded_length_end + name_length;
+
+ // Iterate over all matching parameters, replacing them with string 'replace'
+ std::string modified_str = mangled.str();
+ while ((param_pos = modified_str.find(search, param_pos)) != std::string::npos)
+ {
+ modified_str.replace(param_pos, search.size(), replace);
+ param_pos += replace.size();
+ }
+
+ return ConstString(modified_str);
+}
+
+uint32_t
+CPlusPlusLanguage::FindAlternateFunctionMangling(ConstString mangled_name, std::vector<ConstString>& alternates)
+{
+ const uint32_t start_size = alternates.size();
+
+ // Maybe we're looking for a const symbol but the debug info told us it was const...
+ if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
+ strncmp(mangled_name.GetCString(), "_ZNK", 4))
+ {
+ std::string fixed_scratch("_ZNK");
+ fixed_scratch.append(mangled_name.GetCString() + 3);
+ alternates.push_back(ConstString(fixed_scratch.c_str()));
+ }
+
+ // Maybe we're looking for a static symbol but we thought it was global...
+ if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
+ strncmp(mangled_name.GetCString(), "_ZL", 3))
+ {
+ std::string fixed_scratch("_ZL");
+ fixed_scratch.append(mangled_name.GetCString() + 2);
+ alternates.push_back(ConstString(fixed_scratch.c_str()));
+ }
+
+ // Char is implementation defined as either signed or unsigned.
+ // As a result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed char, 'h'-unsigned char.
+ // If we're looking for symbols with a signed char parameter,
+ // try finding matches which have the general case 'c'.
+ ConstString char_fixup = SubstituteMangledParameters(mangled_name.GetStringRef(), llvm::StringRef("a"), llvm::StringRef("c"));
+ if (!char_fixup.IsEmpty())
+ alternates.push_back(char_fixup);
+
+ // long long parameter mangling 'x', may actually just be a long 'l' argument
+ ConstString long_fixup = SubstituteMangledParameters(mangled_name.GetStringRef(), llvm::StringRef("x"), llvm::StringRef("l"));
+ if (!long_fixup.IsEmpty())
+ alternates.push_back(long_fixup);
+
+ // unsigned long long parameter mangling 'y', may actually just be unsigned long 'm' argument
+ ConstString ulong_fixup = SubstituteMangledParameters(mangled_name.AsCString(), llvm::StringRef("y"), llvm::StringRef("m"));
+ if (!ulong_fixup.IsEmpty())
+ alternates.push_back(ulong_fixup);
+
+ return alternates.size() - start_size;
+}
+
static void
LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp)
{
Index: source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
===================================================================
--- source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -2045,7 +2045,8 @@
Type *function_type = function->GetType();
const lldb::LanguageType comp_unit_language = function->GetCompileUnit()->GetLanguage();
- const bool extern_c = Language::LanguageIsC(comp_unit_language) ||
+ const bool extern_c = (Language::LanguageIsC(comp_unit_language) &&
+ !CPlusPlusLanguage::IsCPPMangledName(function->GetMangled().GetMangledName().AsCString())) ||
(Language::LanguageIsObjC(comp_unit_language) &&
!Language::LanguageIsCPlusPlus(comp_unit_language));
Index: source/Expression/IRExecutionUnit.cpp
===================================================================
--- source/Expression/IRExecutionUnit.cpp
+++ source/Expression/IRExecutionUnit.cpp
@@ -743,24 +743,10 @@
CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull));
}
- }
- // Maybe we're looking for a const symbol but the debug info told us it was const...
- if (!strncmp(name.GetCString(), "_ZN", 3) &&
- strncmp(name.GetCString(), "_ZNK", 4))
- {
- std::string fixed_scratch("_ZNK");
- fixed_scratch.append(name.GetCString() + 3);
- CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
- }
-
- // Maybe we're looking for a static symbol but we thought it was global...
- if (!strncmp(name.GetCString(), "_Z", 2) &&
- strncmp(name.GetCString(), "_ZL", 3))
- {
- std::string fixed_scratch("_ZL");
- fixed_scratch.append(name.GetCString() + 2);
- CPP_specs.push_back(ConstString(fixed_scratch.c_str()));
+ std::vector<ConstString> alternates;
+ CPlusPlusLanguage::FindAlternateFunctionMangling(name, alternates);
+ CPP_specs.insert(CPP_specs.end(), alternates.begin(), alternates.end());
}
}
Index: packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/main.c
===================================================================
--- packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/main.c
+++ packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/main.c
@@ -0,0 +1,17 @@
+char __attribute__((overloadable)) get_arg_type(float x)
+{
+ return 'F'; // 'F' for float
+}
+
+char __attribute__((overloadable)) get_arg_type(int x)
+{
+ return 'I'; // 'I' for int
+}
+
+int main()
+{
+ char float_result = get_arg_type(0.1f);
+ char int_result = get_arg_type(2);
+
+ return 0; // break here
+}
Index: packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/TestCallOverloadedCFunction.py
===================================================================
--- packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/TestCallOverloadedCFunction.py
+++ packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/TestCallOverloadedCFunction.py
@@ -0,0 +1,50 @@
+"""
+Test calling user defined C functions using expression evaluation.
+This test checks that expression evaluation works correctly for
+functions defined with __attribute__((overloadable)).
+
+Ticket: https://llvm.org/bugs/show_bug.cgi?id=26694
+"""
+
+from __future__ import print_function
+
+import lldb
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestExprCallOverloadedCFunction(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ TestBase.setUp(self)
+ # Find the line number to break for main.c.
+ self.line = line_number('main.c',
+ '// break here')
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
+ @expectedFailureAll(compiler='gcc') # attribute overloadable only supported by clang
+ def test(self):
+ """Test calling overloaded C functions."""
+ self.build()
+
+ # Set breakpoint in main and run exe
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+ lldbutil.run_break_set_by_file_and_line(
+ self,
+ "main.c",
+ self.line,
+ num_expected_locations=-1,
+ loc_exact=True
+ )
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # Test floating point type overload.
+ self.expect("expr get_arg_type(0.5f)", substrs=["$0 = 'F'"])
+
+ # Test integer type overload
+ self.expect("expr get_arg_type(8)", substrs=["$1 = 'I'"])
Index: packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/Makefile
===================================================================
--- packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/Makefile
+++ packages/Python/lldbsuite/test/expression_command/call-overloaded-c-fuction/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits