Skip to content

Commit 3f76748

Browse files
demangle: support closure template parameters
See itanium-cxx-abi/cxx-abi#85.
1 parent 7a0008c commit 3f76748

File tree

3 files changed

+470
-17
lines changed

3 files changed

+470
-17
lines changed

ast.go

Lines changed: 326 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,287 @@ func (sa *SizeofArgs) goString(indent int, field string) string {
19321932
return fmt.Sprintf("%*s%sSizeofArgs:\n%s", indent, "", field, args)
19331933
}
19341934

1935+
// TemplateParamName is the name of a template parameter that the
1936+
// demangler introduced for a lambda that has explicit template
1937+
// parameters. This is a prefix with an index.
1938+
type TemplateParamName struct {
1939+
Prefix string
1940+
Index int
1941+
}
1942+
1943+
func (tpn *TemplateParamName) print(ps *printState) {
1944+
ps.writeString(tpn.Prefix)
1945+
if tpn.Index > 0 {
1946+
ps.writeString(fmt.Sprintf("%d", tpn.Index - 1))
1947+
}
1948+
}
1949+
1950+
func (tpn *TemplateParamName) Traverse(fn func(AST) bool) {
1951+
fn(tpn)
1952+
}
1953+
1954+
func (tpn *TemplateParamName) Copy(fn func(AST) AST, skip func(AST) bool) AST {
1955+
if skip(tpn) {
1956+
return nil
1957+
}
1958+
return fn(tpn)
1959+
}
1960+
1961+
func (tpn *TemplateParamName) GoString() string {
1962+
return tpn.goString(0, "")
1963+
}
1964+
1965+
func (tpn *TemplateParamName) goString(indent int, field string) string {
1966+
name := tpn.Prefix
1967+
if tpn.Index > 0 {
1968+
name += fmt.Sprintf("%d", tpn.Index - 1)
1969+
}
1970+
return fmt.Sprintf("%*s%sTemplateParamName: %s", indent, "", field, name)
1971+
}
1972+
1973+
// TypeTemplateParam is a type template parameter that appears in a
1974+
// lambda with explicit template parameters.
1975+
type TypeTemplateParam struct {
1976+
Name AST
1977+
}
1978+
1979+
func (ttp *TypeTemplateParam) print(ps *printState) {
1980+
ps.writeString("typename ")
1981+
ps.printInner(false)
1982+
ps.print(ttp.Name)
1983+
}
1984+
1985+
func (ttp *TypeTemplateParam) Traverse(fn func(AST) bool) {
1986+
if fn(ttp) {
1987+
ttp.Name.Traverse(fn)
1988+
}
1989+
}
1990+
1991+
func (ttp *TypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST {
1992+
if skip(ttp) {
1993+
return nil
1994+
}
1995+
name := ttp.Name.Copy(fn, skip)
1996+
if name == nil {
1997+
return fn(ttp)
1998+
}
1999+
ttp = &TypeTemplateParam{Name: name}
2000+
if r := fn(ttp); r != nil {
2001+
return r
2002+
}
2003+
return ttp
2004+
}
2005+
2006+
func (ttp *TypeTemplateParam) GoString() string {
2007+
return ttp.goString(0, "")
2008+
}
2009+
2010+
func (ttp *TypeTemplateParam) goString(indent int, field string) string {
2011+
return fmt.Sprintf("%*s%sTypeTemplateParam:\n%s", indent, "", field,
2012+
ttp.Name.goString(indent+2, "Name"))
2013+
}
2014+
2015+
// NonTypeTemplateParam is a non-type template parameter that appears
2016+
// in a lambda with explicit template parameters.
2017+
type NonTypeTemplateParam struct {
2018+
Name AST
2019+
Type AST
2020+
}
2021+
2022+
func (nttp *NonTypeTemplateParam) print(ps *printState) {
2023+
ps.inner = append(ps.inner, nttp)
2024+
ps.print(nttp.Type)
2025+
if len(ps.inner) > 0 {
2026+
ps.writeByte(' ')
2027+
ps.print(nttp.Name)
2028+
ps.inner = ps.inner[:len(ps.inner)-1]
2029+
}
2030+
}
2031+
2032+
func (nttp *NonTypeTemplateParam) printInner(ps *printState) {
2033+
ps.print(nttp.Name)
2034+
}
2035+
2036+
func (nttp *NonTypeTemplateParam) Traverse(fn func(AST) bool) {
2037+
if fn(nttp) {
2038+
nttp.Name.Traverse(fn)
2039+
nttp.Type.Traverse(fn)
2040+
}
2041+
}
2042+
2043+
func (nttp *NonTypeTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST {
2044+
if skip(nttp) {
2045+
return nil
2046+
}
2047+
name := nttp.Name.Copy(fn, skip)
2048+
typ := nttp.Type.Copy(fn, skip)
2049+
if name == nil && typ == nil {
2050+
return fn(nttp)
2051+
}
2052+
if name == nil {
2053+
name = nttp.Name
2054+
}
2055+
if typ == nil {
2056+
typ = nttp.Type
2057+
}
2058+
nttp = &NonTypeTemplateParam{Name: name, Type: typ}
2059+
if r := fn(nttp); r != nil {
2060+
return r
2061+
}
2062+
return nttp
2063+
}
2064+
2065+
func (nttp *NonTypeTemplateParam) GoString() string {
2066+
return nttp.goString(0, "")
2067+
}
2068+
2069+
func (nttp *NonTypeTemplateParam) goString(indent int, field string) string {
2070+
return fmt.Sprintf("%*s%sNonTypeTemplateParam:\n%s\n%s", indent, "", field,
2071+
nttp.Name.goString(indent+2, "Name: "),
2072+
nttp.Type.goString(indent+2, "Type: "))
2073+
}
2074+
2075+
// TemplateTemplateParam is a template template parameter that appears
2076+
// in a lambda with explicit template parameters.
2077+
type TemplateTemplateParam struct {
2078+
Name AST
2079+
Params []AST
2080+
}
2081+
2082+
func (ttp *TemplateTemplateParam) print(ps *printState) {
2083+
ps.writeString("template<")
2084+
for i, param := range ttp.Params {
2085+
if i > 0 {
2086+
ps.writeString(", ")
2087+
}
2088+
ps.print(param)
2089+
}
2090+
ps.writeString("> typename ")
2091+
ps.print(ttp.Name)
2092+
}
2093+
2094+
func (ttp *TemplateTemplateParam) Traverse(fn func(AST) bool) {
2095+
if fn(ttp) {
2096+
ttp.Name.Traverse(fn)
2097+
for _, param := range ttp.Params {
2098+
param.Traverse(fn)
2099+
}
2100+
}
2101+
}
2102+
2103+
func (ttp *TemplateTemplateParam) Copy(fn func(AST) AST, skip func(AST) bool) AST {
2104+
if skip(ttp) {
2105+
return nil
2106+
}
2107+
2108+
changed := false
2109+
2110+
name := ttp.Name.Copy(fn, skip)
2111+
if name == nil {
2112+
name = ttp.Name
2113+
} else {
2114+
changed = true
2115+
}
2116+
2117+
params := make([]AST, len(ttp.Params))
2118+
for i, p := range ttp.Params {
2119+
pc := p.Copy(fn, skip)
2120+
if pc == nil {
2121+
params[i] = p
2122+
} else {
2123+
params[i] = pc
2124+
changed = true
2125+
}
2126+
}
2127+
2128+
if !changed {
2129+
return fn(ttp)
2130+
}
2131+
2132+
ttp = &TemplateTemplateParam{
2133+
Name: name,
2134+
Params: params,
2135+
}
2136+
if r := fn(ttp); r != nil {
2137+
return r
2138+
}
2139+
return ttp
2140+
}
2141+
2142+
func (ttp *TemplateTemplateParam) GoString() string {
2143+
return ttp.goString(0, "")
2144+
}
2145+
2146+
func (ttp *TemplateTemplateParam) goString(indent int, field string) string {
2147+
var params strings.Builder
2148+
fmt.Fprintf(&params, "%*sParams:", indent+2, "")
2149+
for i, p := range ttp.Params {
2150+
params.WriteByte('\n')
2151+
params.WriteString(p.goString(indent+4, fmt.Sprintf("%d: ", i)))
2152+
}
2153+
return fmt.Sprintf("%*s%sTemplateTemplateParam:\n%s\n%s", indent, "", field,
2154+
ttp.Name.goString(indent+2, "Name: "),
2155+
params.String())
2156+
}
2157+
2158+
// TemplateParamPack is a template parameter pack that appears in a
2159+
// lambda with explicit template parameters.
2160+
type TemplateParamPack struct {
2161+
Param AST
2162+
}
2163+
2164+
func (tpp *TemplateParamPack) print(ps *printState) {
2165+
holdInner := ps.inner
2166+
defer func() { ps.inner = holdInner }()
2167+
2168+
ps.inner = []AST{tpp}
2169+
if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok {
2170+
ps.print(nttp.Type)
2171+
} else {
2172+
ps.print(tpp.Param)
2173+
}
2174+
if len(ps.inner) > 0 {
2175+
ps.writeString("...")
2176+
}
2177+
}
2178+
2179+
func (tpp *TemplateParamPack) printInner(ps *printState) {
2180+
ps.writeString("...")
2181+
if nttp, ok := tpp.Param.(*NonTypeTemplateParam); ok {
2182+
ps.print(nttp.Name)
2183+
}
2184+
}
2185+
2186+
func (tpp *TemplateParamPack) Traverse(fn func(AST) bool) {
2187+
if fn(tpp) {
2188+
tpp.Param.Traverse(fn)
2189+
}
2190+
}
2191+
2192+
func (tpp *TemplateParamPack) Copy(fn func(AST) AST, skip func(AST) bool) AST {
2193+
if skip(tpp) {
2194+
return nil
2195+
}
2196+
param := tpp.Param.Copy(fn, skip)
2197+
if param == nil {
2198+
return fn(tpp)
2199+
}
2200+
tpp = &TemplateParamPack{Param: param}
2201+
if r := fn(tpp); r != nil {
2202+
return r
2203+
}
2204+
return tpp
2205+
}
2206+
2207+
func (tpp *TemplateParamPack) GoString() string {
2208+
return tpp.goString(0, "")
2209+
}
2210+
2211+
func (tpp *TemplateParamPack) goString(indent int, field string) string {
2212+
return fmt.Sprintf("%*s%sTemplateParamPack:\n%s", indent, "", field,
2213+
tpp.Param.goString(indent+2, "Param: "))
2214+
}
2215+
19352216
// Cast is a type cast.
19362217
type Cast struct {
19372218
To AST
@@ -2981,12 +3262,24 @@ func (da *DefaultArg) goString(indent int, field string) string {
29813262

29823263
// Closure is a closure, or lambda expression.
29833264
type Closure struct {
2984-
Types []AST
2985-
Num int
3265+
TemplateArgs []AST
3266+
Types []AST
3267+
Num int
29863268
}
29873269

29883270
func (cl *Closure) print(ps *printState) {
2989-
ps.writeString("{lambda(")
3271+
ps.writeString("{lambda")
3272+
if len(cl.TemplateArgs) > 0 {
3273+
ps.writeString("<")
3274+
for i, a := range cl.TemplateArgs {
3275+
if i > 0 {
3276+
ps.writeString(", ")
3277+
}
3278+
ps.print(a)
3279+
}
3280+
ps.writeString(">")
3281+
}
3282+
ps.writeString("(")
29903283
for i, t := range cl.Types {
29913284
if i > 0 {
29923285
ps.writeString(", ")
@@ -2998,6 +3291,9 @@ func (cl *Closure) print(ps *printState) {
29983291

29993292
func (cl *Closure) Traverse(fn func(AST) bool) {
30003293
if fn(cl) {
3294+
for _, a := range cl.TemplateArgs {
3295+
a.Traverse(fn)
3296+
}
30013297
for _, t := range cl.Types {
30023298
t.Traverse(fn)
30033299
}
@@ -3008,8 +3304,20 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST {
30083304
if skip(cl) {
30093305
return nil
30103306
}
3011-
types := make([]AST, len(cl.Types))
30123307
changed := false
3308+
3309+
args := make([]AST, len(cl.TemplateArgs))
3310+
for i, a := range cl.TemplateArgs {
3311+
ac := a.Copy(fn, skip)
3312+
if ac == nil {
3313+
args[i] = a
3314+
} else {
3315+
args[i] = ac
3316+
changed = true
3317+
}
3318+
}
3319+
3320+
types := make([]AST, len(cl.Types))
30133321
for i, t := range cl.Types {
30143322
tc := t.Copy(fn, skip)
30153323
if tc == nil {
@@ -3019,10 +3327,11 @@ func (cl *Closure) Copy(fn func(AST) AST, skip func(AST) bool) AST {
30193327
changed = true
30203328
}
30213329
}
3330+
30223331
if !changed {
30233332
return fn(cl)
30243333
}
3025-
cl = &Closure{Types: types, Num: cl.Num}
3334+
cl = &Closure{TemplateArgs: args, Types: types, Num: cl.Num}
30263335
if r := fn(cl); r != nil {
30273336
return r
30283337
}
@@ -3034,6 +3343,16 @@ func (cl *Closure) GoString() string {
30343343
}
30353344

30363345
func (cl *Closure) goString(indent int, field string) string {
3346+
var args string
3347+
if len(cl.TemplateArgs) == 0 {
3348+
args = fmt.Sprintf("%*sTemplateArgs: nil", indent+2, "")
3349+
} else {
3350+
args = fmt.Sprintf("%*sTemplateArgs:", indent+2, "")
3351+
for i, a := range cl.TemplateArgs {
3352+
args += "\n"
3353+
args += a.goString(indent+4, fmt.Sprintf("%d: ", i))
3354+
}
3355+
}
30373356
var types string
30383357
if len(cl.Types) == 0 {
30393358
types = fmt.Sprintf("%*sTypes: nil", indent+2, "")
@@ -3044,7 +3363,8 @@ func (cl *Closure) goString(indent int, field string) string {
30443363
types += t.goString(indent+4, fmt.Sprintf("%d: ", i))
30453364
}
30463365
}
3047-
return fmt.Sprintf("%*s%sClosure: Num: %d\n%s", indent, "", field, cl.Num, types)
3366+
return fmt.Sprintf("%*s%sClosure: Num: %d\n%s\n%s", indent, "", field,
3367+
cl.Num, args, types)
30483368
}
30493369

30503370
// UnnamedType is an unnamed type, that just has an index.

0 commit comments

Comments
 (0)