Skip to content

Commit 3ad0a46

Browse files
make parts of GetFunctionDisplayName's logic reusable
1 parent 720d1c7 commit 3ad0a46

File tree

3 files changed

+199
-101
lines changed

3 files changed

+199
-101
lines changed

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 116 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,17 +1719,10 @@ bool SwiftLanguage::GetFunctionDisplayName(
17191719
return true;
17201720
}
17211721
case Language::FunctionNameRepresentation::eNameWithArgs: {
1722-
if (!sc.function)
1723-
return false;
1724-
if (sc.function->GetLanguage() != eLanguageTypeSwift)
1725-
return false;
1726-
std::string display_name = SwiftLanguageRuntime::DemangleSymbolAsString(
1727-
sc.function->GetMangled().GetMangledName().GetStringRef(),
1728-
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
1722+
std::string display_name = GetFunctionName(sc, exe_ctx);
17291723
if (display_name.empty())
17301724
return false;
1731-
ExecutionContextScope *exe_scope =
1732-
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
1725+
s << display_name;
17331726
const InlineFunctionInfo *inline_info = NULL;
17341727
VariableListSP variable_list_sp;
17351728
bool get_function_vars = true;
@@ -1749,109 +1742,131 @@ bool SwiftLanguage::GetFunctionDisplayName(
17491742
sc.function->GetBlock(true).GetBlockVariableList(true);
17501743
}
17511744

1752-
if (inline_info) {
1753-
s << display_name;
1754-
s.PutCString(" [inlined] ");
1755-
display_name = inline_info->GetName().GetString();
1756-
}
1757-
17581745
VariableList args;
17591746
if (variable_list_sp)
17601747
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
17611748
args);
1762-
if (args.GetSize() == 0) {
1763-
s << display_name;
1764-
return true;
1765-
}
1766-
const char *cstr = display_name.data();
1767-
const char *open_paren = strchr(cstr, '(');
1768-
const char *close_paren = nullptr;
1769-
const char *generic = strchr(cstr, '<');
1770-
// If before the arguments list begins there is a template sign
1771-
// then scan to the end of the generic args before you try to find
1772-
// the arguments list.
1773-
if (generic && open_paren && generic < open_paren) {
1774-
int generic_depth = 1;
1775-
++generic;
1776-
for (; *generic && generic_depth > 0; generic++) {
1777-
if (*generic == '<')
1778-
generic_depth++;
1779-
if (*generic == '>')
1780-
generic_depth--;
1781-
}
1782-
if (*generic)
1783-
open_paren = strchr(generic, '(');
1784-
else
1785-
open_paren = nullptr;
1749+
1750+
s << GetFunctionDisplayArgs(sc, args, exe_ctx);
1751+
return true;
17861752
}
1787-
if (open_paren) {
1788-
close_paren = strchr(open_paren, ')');
17891753
}
1754+
return false;
1755+
}
17901756

1791-
if (open_paren)
1792-
s.Write(cstr, open_paren - cstr + 1);
1793-
else {
1794-
s << display_name;
1795-
s.PutChar('(');
1757+
std::string SwiftLanguage::GetFunctionName(const SymbolContext &sc,
1758+
const ExecutionContext *exe_ctx) {
1759+
if (!sc.function)
1760+
return {};
1761+
if (sc.function->GetLanguage() != eLanguageTypeSwift)
1762+
return {};
1763+
std::string name = SwiftLanguageRuntime::DemangleSymbolAsString(
1764+
sc.function->GetMangled().GetMangledName().GetStringRef(),
1765+
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
1766+
if (name.empty())
1767+
return {};
1768+
size_t open_paren = name.find('(');
1769+
size_t generic = name.find('<');
1770+
size_t name_end = std::min(open_paren, generic);
1771+
if (name_end == std::string::npos)
1772+
return name;
1773+
return name.substr(0, name_end);
1774+
}
1775+
1776+
std::string SwiftLanguage::GetFunctionDisplayArgs(
1777+
const SymbolContext &sc, VariableList &args,
1778+
const lldb_private::ExecutionContext *exe_ctx) {
1779+
ExecutionContextScope *exe_scope =
1780+
exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
1781+
std::string name = SwiftLanguageRuntime::DemangleSymbolAsString(
1782+
sc.function->GetMangled().GetMangledName().GetStringRef(),
1783+
SwiftLanguageRuntime::eSimplified, &sc, exe_ctx);
1784+
lldb_private::StreamString s;
1785+
const char *cstr = name.data();
1786+
const char *open_paren = strchr(cstr, '(');
1787+
const char *close_paren = nullptr;
1788+
const char *generic = strchr(cstr, '<');
1789+
// If before the arguments list begins there is a template sign
1790+
// then scan to the end of the generic args before you try to find
1791+
// the arguments list.
1792+
const char *generic_start = generic;
1793+
if (generic && open_paren && generic < open_paren) {
1794+
int generic_depth = 1;
1795+
++generic;
1796+
for (; *generic && generic_depth > 0; generic++) {
1797+
if (*generic == '<')
1798+
generic_depth++;
1799+
if (*generic == '>')
1800+
generic_depth--;
17961801
}
1797-
const size_t num_args = args.GetSize();
1798-
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1799-
std::string buffer;
1800-
1801-
VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1802-
ValueObjectSP var_value_sp(
1803-
ValueObjectVariable::Create(exe_scope, var_sp));
1804-
if (!var_sp || !var_value_sp || var_sp->IsArtificial())
1805-
continue;
1806-
StreamString ss;
1807-
const char *var_representation = nullptr;
1808-
const char *var_name = var_value_sp->GetName().GetCString();
1809-
if (var_value_sp->GetCompilerType().IsValid()) {
1810-
if (var_value_sp && exe_scope->CalculateTarget())
1811-
var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
1812-
exe_scope->CalculateTarget()
1813-
->TargetProperties::GetPreferDynamicValue(),
1814-
exe_scope->CalculateTarget()
1815-
->TargetProperties::GetEnableSyntheticValue());
1816-
if (var_value_sp->GetCompilerType().IsAggregateType() &&
1817-
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) {
1818-
static StringSummaryFormat format(TypeSummaryImpl::Flags()
1819-
.SetHideItemNames(false)
1820-
.SetShowMembersOneLiner(true),
1821-
"");
1822-
format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
1823-
var_representation = buffer.c_str();
1824-
} else
1825-
var_value_sp->DumpPrintableRepresentation(
1826-
ss,
1827-
ValueObject::ValueObjectRepresentationStyle::
1828-
eValueObjectRepresentationStyleSummary,
1829-
eFormatDefault,
1830-
ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
1831-
}
1832-
if (ss.GetData() && ss.GetSize())
1833-
var_representation = ss.GetData();
1834-
if (arg_idx > 0)
1835-
s.PutCString(", ");
1836-
if (var_value_sp->GetError().Success()) {
1837-
if (var_representation)
1838-
s.Printf("%s=%s", var_name, var_representation);
1839-
else
1840-
s.Printf("%s=%s at %s", var_name,
1841-
var_value_sp->GetTypeName().GetCString(),
1842-
var_value_sp->GetLocationAsCString());
1802+
if (*generic)
1803+
open_paren = strchr(generic, '(');
1804+
else
1805+
open_paren = nullptr;
1806+
}
1807+
if (open_paren) {
1808+
close_paren = strchr(open_paren, ')');
1809+
}
1810+
1811+
if (generic_start && generic_start < open_paren)
1812+
s.Write(generic_start, open_paren - generic_start);
1813+
s.PutChar('(');
1814+
1815+
const size_t num_args = args.GetSize();
1816+
for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
1817+
std::string buffer;
1818+
1819+
VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
1820+
ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
1821+
if (!var_sp || !var_value_sp || var_sp->IsArtificial())
1822+
continue;
1823+
StreamString ss;
1824+
const char *var_representation = nullptr;
1825+
const char *var_name = var_value_sp->GetName().GetCString();
1826+
if (var_value_sp->GetCompilerType().IsValid()) {
1827+
if (var_value_sp && exe_scope->CalculateTarget())
1828+
var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
1829+
exe_scope->CalculateTarget()
1830+
->TargetProperties::GetPreferDynamicValue(),
1831+
exe_scope->CalculateTarget()
1832+
->TargetProperties::GetEnableSyntheticValue());
1833+
if (var_value_sp->GetCompilerType().IsAggregateType() &&
1834+
DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) {
1835+
static StringSummaryFormat format(TypeSummaryImpl::Flags()
1836+
.SetHideItemNames(false)
1837+
.SetShowMembersOneLiner(true),
1838+
"");
1839+
format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
1840+
var_representation = buffer.c_str();
18431841
} else
1844-
s.Printf("%s=<unavailable>", var_name);
1842+
var_value_sp->DumpPrintableRepresentation(
1843+
ss,
1844+
ValueObject::ValueObjectRepresentationStyle::
1845+
eValueObjectRepresentationStyleSummary,
1846+
eFormatDefault,
1847+
ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
18451848
}
1846-
1847-
if (close_paren)
1848-
s.PutCString(close_paren);
1849-
else
1850-
s.PutChar(')');
1851-
}
1852-
return true;
1849+
if (ss.GetData() && ss.GetSize())
1850+
var_representation = ss.GetData();
1851+
if (arg_idx > 0)
1852+
s.PutCString(", ");
1853+
if (var_value_sp->GetError().Success()) {
1854+
if (var_representation)
1855+
s.Printf("%s=%s", var_name, var_representation);
1856+
else
1857+
s.Printf("%s=%s at %s", var_name,
1858+
var_value_sp->GetTypeName().GetCString(),
1859+
var_value_sp->GetLocationAsCString());
1860+
} else
1861+
s.Printf("%s=<unavailable>", var_name);
18531862
}
1854-
return false;
1863+
1864+
if (close_paren)
1865+
s.PutCString(close_paren);
1866+
else
1867+
s.PutChar(')');
1868+
1869+
return s.GetString().str();
18551870
}
18561871

18571872
void SwiftLanguage::GetExceptionResolverDescription(bool catch_on,

lldb/source/Plugins/Language/Swift/SwiftLanguage.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,37 @@ class SwiftLanguage : public Language {
6969
FunctionNameRepresentation representation,
7070
Stream &s) override;
7171

72+
/// Returns the name of function up to the first generic or opening
73+
/// parenthesis.
74+
///
75+
/// The following function will have the name "foo":
76+
/// \code{.swift}
77+
/// func foo<T>(bar: T) {}
78+
/// \endcode
79+
///
80+
/// \param sc The associated SymbolContext.
81+
/// \param exe_ctx The associated ExecutionContext.
82+
/// \returns The name of a function as an std::string.
83+
std::string GetFunctionName(const SymbolContext &sc,
84+
const ExecutionContext *exe_ctx);
85+
86+
/// Returns the arguments of a function call with its generics if any.
87+
///
88+
/// Calling GetFunctionDisplayArgs on the following function call will return
89+
/// "<Int>(bar=1)"
90+
/// \code{.swift}
91+
/// func foo<T>(bar: T) {}
92+
/// foo(1)
93+
/// \endcode
94+
///
95+
/// \param sc The associated SymbolContext.
96+
/// \param args The VariableList that are passed to the function.
97+
/// \param exe_ctx The associated ExecutionContext.
98+
/// \returns The generics and arguments of a function call as an std::string.
99+
std::string
100+
GetFunctionDisplayArgs(const SymbolContext &sc, VariableList &args,
101+
const lldb_private::ExecutionContext *exe_ctx);
102+
72103
void GetExceptionResolverDescription(bool catch_on, bool throw_on,
73104
Stream &s) override;
74105

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# XFAIL: target-windows
2+
3+
# Test Swift function name printing in backtraces.
4+
5+
# RUN: split-file %s %t
6+
# RUN: %target-swiftc -g %t/main.swift -o %t.out
7+
# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
8+
# RUN: | FileCheck %s
9+
10+
#--- main.swift
11+
func foo() async -> Int {
12+
return await try! bar(a: 1, b: 1)
13+
}
14+
15+
var res = {
16+
(index: Int) -> Int in
17+
return index + 10
18+
}(1)
19+
20+
fileprivate func bar(a: Int, b: Int) async throws -> Int {
21+
var baz = Baz(baz: 1)
22+
return res + a + b + Foo.foo_(a: baz)
23+
}
24+
25+
struct Foo {
26+
let foo: Int
27+
static func foo_<T>(a: T) -> Int {
28+
var a_ = a as! Baz
29+
return a_.qux(a: 1)
30+
}
31+
}
32+
33+
struct Baz {
34+
var baz: Int
35+
mutating func qux<T>(a: T) -> Int {
36+
baz += 1
37+
return baz
38+
}
39+
}
40+
41+
await foo()
42+
43+
#--- commands.input
44+
b qux
45+
46+
run
47+
bt
48+
49+
# CHECK: `Baz.qux<Int>(a=1)
50+
# CHECK: `static Foo.foo_<main.Baz>(a=(baz = 1))
51+
# CHECK: `bar(a=1, b=1)
52+
# CHECK: `foo()

0 commit comments

Comments
 (0)