Skip to content

Commit 6c2392e

Browse files
authored
Merge pull request #6647 from Michael137/bugfix/lldb-frame-func-ptr-format
2 parents 837311c + 4aeda9f commit 6c2392e

File tree

9 files changed

+440
-145
lines changed

9 files changed

+440
-145
lines changed

lldb/include/lldb/Core/FormatEntity.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,17 @@ class FormatEntity {
241241
llvm::StringRef elements,
242242
llvm::StringRef element_format);
243243

244+
/// For each variable in 'args' this function writes the variable
245+
/// name and it's pretty-printed value representation to 'out_stream'
246+
/// in following format:
247+
///
248+
/// \verbatim
249+
/// name_1=repr_1, name_2=repr_2 ...
250+
/// \endverbatim
251+
static void PrettyPrintFunctionArguments(Stream &out_stream,
252+
VariableList const &args,
253+
ExecutionContextScope *exe_scope);
254+
244255
protected:
245256
static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
246257
uint32_t depth);

lldb/source/Core/FormatEntity.cpp

Lines changed: 118 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,71 @@ static inline bool IsToken(const char *var_name_begin, const char *var) {
10391039
return (::strncmp(var_name_begin, var, strlen(var)) == 0);
10401040
}
10411041

1042+
/// Parses the basename out of a demangled function name
1043+
/// that may include function arguments. Supports
1044+
/// template functions.
1045+
///
1046+
/// Returns pointers to the opening and closing parenthesis of
1047+
/// `full_name`. Can return nullptr for either parenthesis if
1048+
/// none is exists.
1049+
static std::pair<char const *, char const *>
1050+
ParseBaseName(char const *full_name) {
1051+
const char *open_paren = strchr(full_name, '(');
1052+
const char *close_paren = nullptr;
1053+
const char *generic = strchr(full_name, '<');
1054+
// if before the arguments list begins there is a template sign
1055+
// then scan to the end of the generic args before you try to find
1056+
// the arguments list
1057+
if (generic && open_paren && generic < open_paren) {
1058+
int generic_depth = 1;
1059+
++generic;
1060+
for (; *generic && generic_depth > 0; generic++) {
1061+
if (*generic == '<')
1062+
generic_depth++;
1063+
if (*generic == '>')
1064+
generic_depth--;
1065+
}
1066+
if (*generic)
1067+
open_paren = strchr(generic, '(');
1068+
else
1069+
open_paren = nullptr;
1070+
}
1071+
1072+
if (open_paren) {
1073+
if (IsToken(open_paren, "(anonymous namespace)")) {
1074+
open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1075+
if (open_paren)
1076+
close_paren = strchr(open_paren, ')');
1077+
} else
1078+
close_paren = strchr(open_paren, ')');
1079+
}
1080+
1081+
return {open_paren, close_paren};
1082+
}
1083+
1084+
/// Writes out the function name in 'full_name' to 'out_stream'
1085+
/// but replaces each argument type with the variable name
1086+
/// and the corresponding pretty-printed value
1087+
static void PrettyPrintFunctionNameWithArgs(Stream &out_stream,
1088+
char const *full_name,
1089+
ExecutionContextScope *exe_scope,
1090+
VariableList const &args) {
1091+
auto [open_paren, close_paren] = ParseBaseName(full_name);
1092+
if (open_paren)
1093+
out_stream.Write(full_name, open_paren - full_name + 1);
1094+
else {
1095+
out_stream.PutCString(full_name);
1096+
out_stream.PutChar('(');
1097+
}
1098+
1099+
FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1100+
1101+
if (close_paren)
1102+
out_stream.PutCString(close_paren);
1103+
else
1104+
out_stream.PutChar(')');
1105+
}
1106+
10421107
bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
10431108
const SymbolContext *sc,
10441109
const ExecutionContext *exe_ctx,
@@ -1656,100 +1721,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16561721
variable_list_sp->AppendVariablesWithScope(
16571722
eValueTypeVariableArgument, args);
16581723
if (args.GetSize() > 0) {
1659-
const char *open_paren = strchr(cstr, '(');
1660-
const char *close_paren = nullptr;
1661-
const char *generic = strchr(cstr, '<');
1662-
// if before the arguments list begins there is a template sign
1663-
// then scan to the end of the generic args before you try to find
1664-
// the arguments list
1665-
if (generic && open_paren && generic < open_paren) {
1666-
int generic_depth = 1;
1667-
++generic;
1668-
for (; *generic && generic_depth > 0; generic++) {
1669-
if (*generic == '<')
1670-
generic_depth++;
1671-
if (*generic == '>')
1672-
generic_depth--;
1673-
}
1674-
if (*generic)
1675-
open_paren = strchr(generic, '(');
1676-
else
1677-
open_paren = nullptr;
1678-
}
1679-
if (open_paren) {
1680-
if (IsToken(open_paren, "(anonymous namespace)")) {
1681-
open_paren =
1682-
strchr(open_paren + strlen("(anonymous namespace)"), '(');
1683-
if (open_paren)
1684-
close_paren = strchr(open_paren, ')');
1685-
} else
1686-
close_paren = strchr(open_paren, ')');
1687-
}
1688-
1689-
if (open_paren)
1690-
s.Write(cstr, open_paren - cstr + 1);
1691-
else {
1692-
s.PutCString(cstr);
1693-
s.PutChar('(');
1694-
}
1695-
const size_t num_args = args.GetSize();
1696-
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1697-
std::string buffer;
1698-
1699-
VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1700-
ValueObjectSP var_value_sp(
1701-
ValueObjectVariable::Create(exe_scope, var_sp));
1702-
StreamString ss;
1703-
llvm::StringRef var_representation;
1704-
const char *var_name = var_value_sp->GetName().GetCString();
1705-
if (var_value_sp->GetCompilerType().IsValid()) {
1706-
if (exe_scope && exe_scope->CalculateTarget())
1707-
var_value_sp =
1708-
var_value_sp->GetQualifiedRepresentationIfAvailable(
1709-
exe_scope->CalculateTarget()
1710-
->TargetProperties::GetPreferDynamicValue(),
1711-
exe_scope->CalculateTarget()
1712-
->TargetProperties::GetEnableSyntheticValue());
1713-
if (var_value_sp->GetCompilerType().IsAggregateType() &&
1714-
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
1715-
static StringSummaryFormat format(
1716-
TypeSummaryImpl::Flags()
1717-
.SetHideItemNames(false)
1718-
.SetShowMembersOneLiner(true),
1719-
"");
1720-
format.FormatObject(var_value_sp.get(), buffer,
1721-
TypeSummaryOptions());
1722-
var_representation = buffer;
1723-
} else
1724-
var_value_sp->DumpPrintableRepresentation(
1725-
ss,
1726-
ValueObject::ValueObjectRepresentationStyle::
1727-
eValueObjectRepresentationStyleSummary,
1728-
eFormatDefault,
1729-
ValueObject::PrintableRepresentationSpecialCases::eAllow,
1730-
false);
1731-
}
1732-
1733-
if (!ss.GetString().empty())
1734-
var_representation = ss.GetString();
1735-
if (arg_idx > 0)
1736-
s.PutCString(", ");
1737-
if (var_value_sp->GetError().Success()) {
1738-
if (!var_representation.empty())
1739-
s.Printf("%s=%s", var_name, var_representation.str().c_str());
1740-
else
1741-
s.Printf("%s=%s at %s", var_name,
1742-
var_value_sp->GetTypeName().GetCString(),
1743-
var_value_sp->GetLocationAsCString());
1744-
} else
1745-
s.Printf("%s=<unavailable>", var_name);
1746-
}
1747-
1748-
if (close_paren)
1749-
s.PutCString(close_paren);
1750-
else
1751-
s.PutChar(')');
1752-
1724+
PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
17531725
} else {
17541726
s.PutCString(cstr);
17551727
}
@@ -2458,3 +2430,55 @@ void FormatEntity::AutoComplete(CompletionRequest &request) {
24582430
request.AddCompletions(new_matches);
24592431
}
24602432
}
2433+
2434+
void FormatEntity::PrettyPrintFunctionArguments(
2435+
Stream &out_stream, VariableList const &args,
2436+
ExecutionContextScope *exe_scope) {
2437+
const size_t num_args = args.GetSize();
2438+
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2439+
std::string buffer;
2440+
2441+
VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2442+
ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2443+
StreamString ss;
2444+
llvm::StringRef var_representation;
2445+
const char *var_name = var_value_sp->GetName().GetCString();
2446+
if (var_value_sp->GetCompilerType().IsValid()) {
2447+
if (exe_scope && exe_scope->CalculateTarget())
2448+
var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2449+
exe_scope->CalculateTarget()
2450+
->TargetProperties::GetPreferDynamicValue(),
2451+
exe_scope->CalculateTarget()
2452+
->TargetProperties::GetEnableSyntheticValue());
2453+
if (var_value_sp->GetCompilerType().IsAggregateType() &&
2454+
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
2455+
static StringSummaryFormat format(TypeSummaryImpl::Flags()
2456+
.SetHideItemNames(false)
2457+
.SetShowMembersOneLiner(true),
2458+
"");
2459+
format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2460+
var_representation = buffer;
2461+
} else
2462+
var_value_sp->DumpPrintableRepresentation(
2463+
ss,
2464+
ValueObject::ValueObjectRepresentationStyle::
2465+
eValueObjectRepresentationStyleSummary,
2466+
eFormatDefault,
2467+
ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
2468+
}
2469+
2470+
if (!ss.GetString().empty())
2471+
var_representation = ss.GetString();
2472+
if (arg_idx > 0)
2473+
out_stream.PutCString(", ");
2474+
if (var_value_sp->GetError().Success()) {
2475+
if (!var_representation.empty())
2476+
out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2477+
else
2478+
out_stream.Printf("%s=%s at %s", var_name,
2479+
var_value_sp->GetTypeName().GetCString(),
2480+
var_value_sp->GetLocationAsCString());
2481+
} else
2482+
out_stream.Printf("%s=<unavailable>", var_name);
2483+
}
2484+
}

0 commit comments

Comments
 (0)