forked from OSchip/llvm-project
Modified the "breakpoint set --name NAME" to be the auto breakpoint set
function. It will inspect NAME and do the following: - if the name contains '(' or starts with "-[" or "+[" then a full name search will happen to match full function names with args (C++ demangled names) or full objective C method prototypes. - if the name contains "::" and no '(', then it is assumed to be a qualified function name that is in a namespace or class. For "foo::bar::baz" we will search for any functions with the basename or method name of "baz", then filter the results to only those that contain "foo::bar::baz". This allows setting breakpoint on C++ functions and methods without having to fully qualify all of the types that would appear in C++ mangled names. - if the name contains ":" (not "::"), then NAME is assumed to be an ObjC selector. _ otherwise, we assume just a plain function basename. Now that "--name" is our "auto" mode, I introduced the new "--basename" option ("breakpoint set --basename NAME") to allow for function names that aren't methods or selectors, just basenames. This can also be used to ignore C++ namespaces and class hierarchies for class methods. Fixed clang enumeration promotion types to be correct. llvm-svn: 116293
This commit is contained in:
parent
5627fd71c8
commit
e02b850483
|
@ -63,6 +63,14 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConstString m_func_name;
|
ConstString m_func_name;
|
||||||
|
// "m_basename_filter" is used to filter results after searching for
|
||||||
|
// "m_func_name" first. This is used when we are asked to set a breakpoint
|
||||||
|
// at "foo::bar::baz" (C++ function in namespace or in a class). For
|
||||||
|
// "foo::bar::baz" we will place "baz" into m_func_name and search for all
|
||||||
|
// matching basename and methods that match "baz", then we will filter the
|
||||||
|
// results by checking if the demangled name contains "m_basename_filter"
|
||||||
|
// which would be set to "foo::bar::baz".
|
||||||
|
std::string m_basename_filter;
|
||||||
uint32_t m_func_name_type_mask; // See FunctionNameType
|
uint32_t m_func_name_type_mask; // See FunctionNameType
|
||||||
ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class.
|
ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class.
|
||||||
RegularExpression m_regex;
|
RegularExpression m_regex;
|
||||||
|
|
|
@ -412,15 +412,17 @@ typedef enum ArchitectureType
|
||||||
typedef enum FunctionNameType
|
typedef enum FunctionNameType
|
||||||
{
|
{
|
||||||
eFunctionNameTypeNone = 0u,
|
eFunctionNameTypeNone = 0u,
|
||||||
eFunctionNameTypeFull = (1u << 1),// The function name.
|
eFunctionNameTypeAuto = (1u << 1), // Automatically figure out which FunctionNameType
|
||||||
// For C this is the same as just the name of the function
|
// bits to set based on the function name.
|
||||||
// For C++ this is the demangled version of the mangled name.
|
eFunctionNameTypeFull = (1u << 2), // The function name.
|
||||||
// For ObjC this is the full function signature with the + or
|
// For C this is the same as just the name of the function
|
||||||
// - and the square brackets and the class and selector
|
// For C++ this is the demangled version of the mangled name.
|
||||||
eFunctionNameTypeBase = (1u << 2),// The function name only, no namespaces or arguments and no class
|
// For ObjC this is the full function signature with the + or
|
||||||
// methods or selectors will be searched.
|
// - and the square brackets and the class and selector
|
||||||
eFunctionNameTypeMethod = (1u << 3),// Find function by method name (C++) with no namespace or arguments
|
eFunctionNameTypeBase = (1u << 3), // The function name only, no namespaces or arguments and no class
|
||||||
eFunctionNameTypeSelector = (1u << 4) // Find function by selector name (ObjC) names
|
// methods or selectors will be searched.
|
||||||
|
eFunctionNameTypeMethod = (1u << 4), // Find function by method name (C++) with no namespace or arguments
|
||||||
|
eFunctionNameTypeSelector = (1u << 5), // Find function by selector name (ObjC) names
|
||||||
} FunctionNameType;
|
} FunctionNameType;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2964,7 +2964,7 @@
|
||||||
"$(LLVM_BUILD_DIR)",
|
"$(LLVM_BUILD_DIR)",
|
||||||
);
|
);
|
||||||
LLVM_BUILD_DIR = "$(SRCROOT)/llvm";
|
LLVM_BUILD_DIR = "$(SRCROOT)/llvm";
|
||||||
LLVM_CONFIGURATION = Release;
|
LLVM_CONFIGURATION = "Debug+Asserts";
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"-DFOR_DYLD=0",
|
"-DFOR_DYLD=0",
|
||||||
"-DSUPPORT_REMOTE_UNWINDING",
|
"-DSUPPORT_REMOTE_UNWINDING",
|
||||||
|
|
|
@ -91,7 +91,7 @@ if (-l $llvm_dstroot)
|
||||||
# LLVM in the "lldb" root is a symlink which indicates we are using a
|
# LLVM in the "lldb" root is a symlink which indicates we are using a
|
||||||
# standard LLVM build directory where everything is built into the
|
# standard LLVM build directory where everything is built into the
|
||||||
# same folder
|
# same folder
|
||||||
create_single_llvm_arhive_for_arch ($llvm_dstroot, 0);
|
create_single_llvm_arhive_for_arch ($llvm_dstroot, 1);
|
||||||
my $llvm_dstroot_archive = "$llvm_dstroot/$llvm_clang_basename";
|
my $llvm_dstroot_archive = "$llvm_dstroot/$llvm_clang_basename";
|
||||||
push @llvm_clang_slices, $llvm_dstroot_archive;
|
push @llvm_clang_slices, $llvm_dstroot_archive;
|
||||||
create_dstroot_file ($llvm_clang_basename, $llvm_clang_dirname, \@llvm_clang_slices, $llvm_clang_basename);
|
create_dstroot_file ($llvm_clang_basename, $llvm_clang_dirname, \@llvm_clang_slices, $llvm_clang_basename);
|
||||||
|
|
|
@ -29,12 +29,54 @@ BreakpointResolverName::BreakpointResolverName
|
||||||
Breakpoint::MatchType type
|
Breakpoint::MatchType type
|
||||||
) :
|
) :
|
||||||
BreakpointResolver (bkpt),
|
BreakpointResolver (bkpt),
|
||||||
m_func_name (func_name),
|
m_func_name (),
|
||||||
|
m_basename_filter (),
|
||||||
m_func_name_type_mask (func_name_type_mask),
|
m_func_name_type_mask (func_name_type_mask),
|
||||||
m_class_name (),
|
m_class_name (),
|
||||||
m_regex (),
|
m_regex (),
|
||||||
m_match_type (type)
|
m_match_type (type)
|
||||||
{
|
{
|
||||||
|
if (func_name_type_mask == eFunctionNameTypeAuto)
|
||||||
|
{
|
||||||
|
if ((::strchr (func_name, '(' ) != NULL) ||
|
||||||
|
(::strstr (func_name, "-[") == func_name) ||
|
||||||
|
(::strstr (func_name, "+[") == func_name))
|
||||||
|
{
|
||||||
|
// We have a name that contains an open parens, or starts with
|
||||||
|
// "+[" or "-[", so this looks like a complete function prototype
|
||||||
|
m_func_name_type_mask = eFunctionNameTypeFull;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We don't have a full function name, but we might have a partial
|
||||||
|
// function basename with namespaces or classes
|
||||||
|
if (::strstr (func_name, "::") != NULL)
|
||||||
|
{
|
||||||
|
// Keep the full name in "m_basename_filter"
|
||||||
|
m_basename_filter = func_name;
|
||||||
|
// Now set "m_func_name" to just the function basename
|
||||||
|
m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2);
|
||||||
|
// We have a name with a double colon which means we have a
|
||||||
|
// function name that is a C++ method or a function in a C++
|
||||||
|
// namespace
|
||||||
|
m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod;
|
||||||
|
}
|
||||||
|
else if (::strstr (func_name, ":") != NULL)
|
||||||
|
{
|
||||||
|
// Single colon => selector
|
||||||
|
m_func_name_type_mask = eFunctionNameTypeSelector;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just a basename by default
|
||||||
|
m_func_name_type_mask = eFunctionNameTypeBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_func_name)
|
||||||
|
m_func_name.SetCString(func_name);
|
||||||
|
|
||||||
if (m_match_type == Breakpoint::Regexp)
|
if (m_match_type == Breakpoint::Regexp)
|
||||||
{
|
{
|
||||||
if (!m_regex.Compile (m_func_name.AsCString()))
|
if (!m_regex.Compile (m_func_name.AsCString()))
|
||||||
|
@ -137,6 +179,53 @@ BreakpointResolverName::SearchCallback
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_basename_filter.empty())
|
||||||
|
{
|
||||||
|
// Filter out any matches whose names don't contain the basename filter
|
||||||
|
const char *basename_filter = m_basename_filter.c_str();
|
||||||
|
if (func_list.GetSize())
|
||||||
|
{
|
||||||
|
bool remove = false;
|
||||||
|
for (i = 0; i < func_list.GetSize(); remove = false)
|
||||||
|
{
|
||||||
|
if (func_list.GetContextAtIndex(i, sc) == false)
|
||||||
|
remove = true;
|
||||||
|
else if (sc.function == NULL)
|
||||||
|
remove = true;
|
||||||
|
else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
|
||||||
|
remove = true;
|
||||||
|
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
func_list.RemoveContextAtIndex(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sym_list.GetSize())
|
||||||
|
{
|
||||||
|
bool remove = false;
|
||||||
|
for (i = 0; i < sym_list.GetSize(); remove = false)
|
||||||
|
{
|
||||||
|
if (sym_list.GetContextAtIndex(i, sc) == false)
|
||||||
|
remove = true;
|
||||||
|
else if (sc.symbol == NULL)
|
||||||
|
remove = true;
|
||||||
|
else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
|
||||||
|
remove = true;
|
||||||
|
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
sym_list.RemoveContextAtIndex(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove any duplicates between the funcion list and the symbol list
|
// Remove any duplicates between the funcion list and the symbol list
|
||||||
if (func_list.GetSize())
|
if (func_list.GetSize())
|
||||||
{
|
{
|
||||||
|
@ -242,8 +331,10 @@ BreakpointResolverName::GetDescription (Stream *s)
|
||||||
{
|
{
|
||||||
if (m_match_type == Breakpoint::Regexp)
|
if (m_match_type == Breakpoint::Regexp)
|
||||||
s->Printf("regex = '%s'", m_regex.GetText());
|
s->Printf("regex = '%s'", m_regex.GetText());
|
||||||
else
|
else if (m_basename_filter.empty())
|
||||||
s->Printf("name = '%s'", m_func_name.AsCString());
|
s->Printf("name = '%s'", m_func_name.AsCString());
|
||||||
|
else
|
||||||
|
s->Printf("name = '%s'", m_basename_filter.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -104,7 +104,7 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
|
||||||
"Set the breakpoint by address, at the specified address."},
|
"Set the breakpoint by address, at the specified address."},
|
||||||
|
|
||||||
{ LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
|
{ LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
|
||||||
"Set the breakpoint by function name - for C++ this means namespaces and arguments will be ignored." },
|
"Set the breakpoint by function name." },
|
||||||
|
|
||||||
{ LLDB_OPT_SET_4, true, "fullname", 'F', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
|
{ LLDB_OPT_SET_4, true, "fullname", 'F', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
|
||||||
"Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguemnts, and "
|
"Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguemnts, and "
|
||||||
|
@ -119,6 +119,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
|
||||||
{ LLDB_OPT_SET_7, true, "func-regex", 'r', required_argument, NULL, 0, eArgTypeRegularExpression,
|
{ LLDB_OPT_SET_7, true, "func-regex", 'r', required_argument, NULL, 0, eArgTypeRegularExpression,
|
||||||
"Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
|
"Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
|
||||||
|
|
||||||
|
{ LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
|
||||||
|
"Set the breakpoint by function basename (C++ namespaces and arguments will be ignored)." },
|
||||||
|
|
||||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -157,11 +160,16 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, cons
|
||||||
m_line_num = Args::StringToUInt32 (option_arg, 0);
|
m_line_num = Args::StringToUInt32 (option_arg, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'b':
|
||||||
m_func_name = option_arg;
|
m_func_name = option_arg;
|
||||||
m_func_name_type_mask |= eFunctionNameTypeBase;
|
m_func_name_type_mask |= eFunctionNameTypeBase;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
m_func_name = option_arg;
|
||||||
|
m_func_name_type_mask |= eFunctionNameTypeAuto;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
m_func_name = option_arg;
|
m_func_name = option_arg;
|
||||||
m_func_name_type_mask |= eFunctionNameTypeFull;
|
m_func_name_type_mask |= eFunctionNameTypeFull;
|
||||||
|
@ -391,17 +399,8 @@ CommandObjectBreakpointSet::Execute
|
||||||
uint32_t name_type_mask = m_options.m_func_name_type_mask;
|
uint32_t name_type_mask = m_options.m_func_name_type_mask;
|
||||||
|
|
||||||
if (name_type_mask == 0)
|
if (name_type_mask == 0)
|
||||||
{
|
name_type_mask = eFunctionNameTypeAuto;
|
||||||
|
|
||||||
if (m_options.m_func_name.find('(') != std::string::npos ||
|
|
||||||
m_options.m_func_name.find("-[") == 0 ||
|
|
||||||
m_options.m_func_name.find("+[") == 0)
|
|
||||||
name_type_mask |= eFunctionNameTypeFull;
|
|
||||||
else
|
|
||||||
name_type_mask |= eFunctionNameTypeBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (use_module)
|
if (use_module)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < num_modules; ++i)
|
for (int i = 0; i < num_modules; ++i)
|
||||||
|
|
|
@ -3099,7 +3099,22 @@ ClangASTContext::CompleteTagDeclarationDefinition (clang_type_t clang_type)
|
||||||
unsigned NumPositiveBits = 1;
|
unsigned NumPositiveBits = 1;
|
||||||
unsigned NumNegativeBits = 0;
|
unsigned NumNegativeBits = 0;
|
||||||
|
|
||||||
enum_decl->completeDefinition(enum_decl->getIntegerType(), enum_decl->getIntegerType(), NumPositiveBits, NumNegativeBits);
|
ASTContext *ast_context = getASTContext();
|
||||||
|
|
||||||
|
QualType promotion_qual_type;
|
||||||
|
// If the enum integer type is less than an integer in bit width,
|
||||||
|
// then we must promote it to an integer size.
|
||||||
|
if (ast_context->getTypeSize(enum_decl->getIntegerType()) < ast_context->getTypeSize(ast_context->IntTy))
|
||||||
|
{
|
||||||
|
if (enum_decl->getIntegerType()->isSignedIntegerType())
|
||||||
|
promotion_qual_type = ast_context->IntTy;
|
||||||
|
else
|
||||||
|
promotion_qual_type = ast_context->UnsignedIntTy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
promotion_qual_type = enum_decl->getIntegerType();
|
||||||
|
|
||||||
|
enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3117,12 +3132,17 @@ ClangASTContext::CreateEnumerationType (const Declaration &decl, const char *nam
|
||||||
// like maybe filling in the SourceLocation with it...
|
// like maybe filling in the SourceLocation with it...
|
||||||
ASTContext *ast_context = getASTContext();
|
ASTContext *ast_context = getASTContext();
|
||||||
assert (ast_context != NULL);
|
assert (ast_context != NULL);
|
||||||
EnumDecl *enum_decl = EnumDecl::Create(*ast_context,
|
|
||||||
ast_context->getTranslationUnitDecl(),
|
// TODO: ask about these...
|
||||||
SourceLocation(),
|
// const bool IsScoped = false;
|
||||||
name && name[0] ? &ast_context->Idents.get(name) : NULL,
|
// const bool IsFixed = false;
|
||||||
SourceLocation(),
|
|
||||||
NULL);
|
EnumDecl *enum_decl = EnumDecl::Create (*ast_context,
|
||||||
|
ast_context->getTranslationUnitDecl(),
|
||||||
|
SourceLocation(),
|
||||||
|
name && name[0] ? &ast_context->Idents.get(name) : NULL,
|
||||||
|
SourceLocation(),
|
||||||
|
NULL); //IsScoped, IsFixed);
|
||||||
if (enum_decl)
|
if (enum_decl)
|
||||||
{
|
{
|
||||||
// TODO: check if we should be setting the promotion type too?
|
// TODO: check if we should be setting the promotion type too?
|
||||||
|
|
Loading…
Reference in New Issue