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
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to