demangle.go
func (st *state) demangleCastTemplateArgs(tp AST, addSubst bool) AST {
	save := st.copy()

	var args []AST
	failed := false
	func() {
		defer func() {
			if r := recover(); r != nil {
				if _, ok := r.(demangleErr); ok {
					failed = true
				} else {
					panic(r)
				}
			}
		}()

		args = st.templateArgs()
	}()

	if !failed && len(st.str) > 0 && st.str[0] == 'I' {
		if addSubst {
			st.subs.add(tp)
		}
		return &Template{Name: tp, Args: args}
	}
	// Reset back to before we started reading the template arguments.
	// They will be read again by st.prefix.
	*st = *save
	return tp
}
func (st *state) demangleCastTemplateArgs(tp AST, addSubst bool) AST {
	save := st.copy()

	var args []AST
	failed := false
	func() {
		defer func() {
			if r := recover(); r != nil {
				if _, ok := r.(demangleErr); ok {
					failed = true
				} else {
					panic(r)
				}
			}
		}()

		args = st.templateArgs()
	}()

	if !failed && len(st.str) > 0 && st.str[0] == 'I' {
		if addSubst {
			st.subs.add(tp)
		}
		return &Template{Name: tp, Args: args}
	}
	// Reset back to before we started reading the template arguments.
	// They will be read again by st.prefix.
	*st = *save
	return tp
}
// demangleCastTemplateArgs is for a rather hideous parse.  When we
// see a template-param followed by a template-args, we need to decide
// whether we have a template-param or a template-template-param.
// Normally it is template-template-param, meaning that we pick up the
// template arguments here.  But, if we are parsing the type for a
// cast operator, then the only way this can be template-template-param
// is if there is another set of template-args immediately after this
// set.  That would look like this:
//
// <nested-name>
// -> <template-prefix> <template-args>
// -> <prefix> <template-unqualified-name> <template-args>
// -> <unqualified-name> <template-unqualified-name> <template-args>
// -> <source-name> <template-unqualified-name> <template-args>
// -> <source-name> <operator-name> <template-args>
// -> <source-name> cv <type> <template-args>
// -> <source-name> cv <template-template-param> <template-args> <template-args>
//
// Otherwise, we have this derivation:
//
// <nested-name>
// -> <template-prefix> <template-args>
// -> <prefix> <template-unqualified-name> <template-args>
// -> <unqualified-name> <template-unqualified-name> <template-args>
// -> <source-name> <template-unqualified-name> <template-args>
// -> <source-name> <operator-name> <template-args>
// -> <source-name> cv <type> <template-args>
// -> <source-name> cv <template-param> <template-args>
//
// in which the template-args are actually part of the prefix.  For
// the special case where this arises, demangleType is called with
// isCast as true.  This function is then responsible for checking
// whether we see <template-param> <template-args> but there is not
// another following <template-args>.  In that case, we reset the
// parse and just return the <template-param>.