Fixed a problem where the expression parser would
not find multiple functions with the same name but different types. Now we keep track of what types we've already reported for a function and only elide functions if we've already reported a conflicting one. Also added a test case. <rdar://problem/11367837> llvm-svn: 180167
This commit is contained in:
parent
404028798f
commit
485f732b84
|
@ -17,6 +17,8 @@
|
|||
#include "lldb/Symbol/ClangASTImporter.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -427,11 +429,12 @@ protected:
|
|||
/// Decls given appropriate type information.
|
||||
//----------------------------------------------------------------------
|
||||
struct NameSearchContext {
|
||||
ClangASTSource &m_ast_source; ///< The AST source making the request
|
||||
llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed
|
||||
ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules
|
||||
const clang::DeclarationName &m_decl_name; ///< The name being looked for
|
||||
const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into
|
||||
ClangASTSource &m_ast_source; ///< The AST source making the request
|
||||
llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed
|
||||
ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules
|
||||
const clang::DeclarationName &m_decl_name; ///< The name being looked for
|
||||
const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into
|
||||
llvm::SmallSet <lldb::clang_type_t, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts
|
||||
|
||||
struct {
|
||||
bool variable : 1;
|
||||
|
|
|
@ -1724,6 +1724,11 @@ NameSearchContext::AddFunDecl (void *type)
|
|||
{
|
||||
assert (type && "Type for variable must be non-NULL!");
|
||||
|
||||
if (m_function_types.count(type))
|
||||
return NULL;
|
||||
|
||||
m_function_types.insert(type);
|
||||
|
||||
clang::FunctionDecl *func_decl = FunctionDecl::Create (*m_ast_source.m_ast_context,
|
||||
const_cast<DeclContext*>(m_decl_context),
|
||||
SourceLocation(),
|
||||
|
|
|
@ -1328,10 +1328,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
|
|||
if (dyn_cast<clang::CXXMethodDecl>(decl_ctx))
|
||||
continue;
|
||||
|
||||
// TODO only do this if it's a C function; C++ functions may be
|
||||
// overloaded
|
||||
if (!context.m_found.function_with_type_info)
|
||||
AddOneFunction(context, sym_ctx.function, NULL, current_id);
|
||||
AddOneFunction(context, sym_ctx.function, NULL, current_id);
|
||||
context.m_found.function_with_type_info = true;
|
||||
context.m_found.function = true;
|
||||
}
|
||||
|
@ -1859,6 +1856,18 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
|
|||
if (copied_type)
|
||||
{
|
||||
fun_decl = context.AddFunDecl(copied_type);
|
||||
|
||||
if (!fun_decl)
|
||||
{
|
||||
if (log)
|
||||
{
|
||||
log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}",
|
||||
fun_type->GetName().GetCString(),
|
||||
fun_type->GetID());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp static-a.cpp static-b.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,53 @@
|
|||
"""
|
||||
Tests that functions with the same name are resolved correctly.
|
||||
"""
|
||||
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
import lldbutil
|
||||
|
||||
class CPPStaticMethodsTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("lang", "cpp", "overloaded-functions")
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym_and_run_command(self):
|
||||
"""Test that functions with the same name are resolved correctly"""
|
||||
self.buildDsym()
|
||||
self.static_method_commands()
|
||||
|
||||
@dwarf_test
|
||||
def test_with_dwarf_and_run_command(self):
|
||||
"""Test that functions with the same name are resolved correctly"""
|
||||
self.buildDwarf()
|
||||
self.static_method_commands()
|
||||
|
||||
def setUp(self):
|
||||
TestBase.setUp(self)
|
||||
self.line = line_number('main.cpp', '// breakpoint')
|
||||
|
||||
def static_method_commands(self):
|
||||
"""Test that static methods are properly distinguished from regular methods"""
|
||||
self.runCmd("file a.out", 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("process launch", RUN_SUCCEEDED)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list",
|
||||
STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped', 'stop reason = breakpoint'])
|
||||
|
||||
self.expect("expression -- Dump(myB)",
|
||||
startstr = "(int) $0 = 2")
|
||||
|
||||
self.expect("expression -- Static()",
|
||||
startstr = "(int) $1 = 1")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,43 @@
|
|||
#include <stdio.h>
|
||||
|
||||
struct A {
|
||||
int aa;
|
||||
char ab;
|
||||
};
|
||||
|
||||
struct B {
|
||||
int ba;
|
||||
int bb;
|
||||
};
|
||||
|
||||
struct C {
|
||||
int ca;
|
||||
int cb;
|
||||
};
|
||||
|
||||
int Dump (A &a)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Dump (B &b)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int Dump (C &c)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
extern int CallStaticA();
|
||||
extern int CallStaticB();
|
||||
|
||||
int main()
|
||||
{
|
||||
A myA;
|
||||
B myB;
|
||||
C myC;
|
||||
|
||||
printf("%d\n", CallStaticA() + CallStaticB()); // breakpoint
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
static int Static()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CallStaticA()
|
||||
{
|
||||
return Static();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
static int Static()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CallStaticB()
|
||||
{
|
||||
return Static();
|
||||
}
|
Loading…
Reference in New Issue