// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package ctrlflow is an analysis that provides a syntactic
// control-flow graph (CFG) for the body of a function.
// It records whether a function cannot return.
// By itself, it does not report any diagnostics.
package ctrlflow

import (
	"go/ast"
	"go/types"
	"log"
	"reflect"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/passes/inspect"
	"golang.org/x/tools/go/ast/inspector"
	"golang.org/x/tools/go/cfg"
	"golang.org/x/tools/go/types/typeutil"
)

var Analyzer = &analysis.Analyzer{
	Name:       "ctrlflow",
	Doc:        "build a control-flow graph",
	URL:        "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ctrlflow",
	Run:        run,
	ResultType: reflect.TypeOf(new(CFGs)),
	FactTypes:  []analysis.Fact{new(noReturn)},
	Requires:   []*analysis.Analyzer{inspect.Analyzer},
}

// noReturn is a fact indicating that a function does not return.
type noReturn struct{}

func (*noReturn) AFact() {}

func (*noReturn) String() string { return "noReturn" }

// A CFGs holds the control-flow graphs
// for all the functions of the current package.
type CFGs struct {
	defs      map[*ast.Ident]types.Object // from Pass.TypesInfo.Defs
	funcDecls map[*types.Func]*declInfo
	funcLits  map[*ast.FuncLit]*litInfo
	pass      *analysis.Pass // transient; nil after construction
}

// CFGs has two maps: funcDecls for named functions and funcLits for
// unnamed ones. Unlike funcLits, the funcDecls map is not keyed by its
// syntax node, *ast.FuncDecl, because callMayReturn needs to do a
// look-up by *types.Func, and you can get from an *ast.FuncDecl to a
// *types.Func but not the other way.

type declInfo struct {
	decl     *ast.FuncDecl
	cfg      *cfg.CFG // iff decl.Body != nil
	started  bool     // to break cycles
	noReturn bool
}

type litInfo struct {
	cfg      *cfg.CFG
	noReturn bool
}

// FuncDecl returns the control-flow graph for a named function.
// It returns nil if decl.Body==nil.
func (c *CFGs) FuncDecl(decl *ast.FuncDecl) *cfg.CFG {
	if decl.Body == nil {
		return nil
	}
	fn := c.defs[decl.Name].(*types.Func)
	return c.funcDecls[fn].cfg
}

// FuncLit returns the control-flow graph for a literal function.
func (c *CFGs) FuncLit(lit *ast.FuncLit) *cfg.CFG {
	return c.funcLits[lit].cfg
}

func run(pass *analysis.Pass) (interface{}, error) {
	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

	// Because CFG construction consumes and produces noReturn
	// facts, CFGs for exported FuncDecls must be built before 'run'
	// returns; we cannot construct them lazily.
	// (We could build CFGs for FuncLits lazily,
	// but the benefit is marginal.)

	// Pass 1. Map types.Funcs to ast.FuncDecls in this package.
	funcDecls := make(map[*types.Func]*declInfo) // functions and methods
	funcLits := make(map[*ast.FuncLit]*litInfo)

	var decls []*types.Func // keys(funcDecls), in order
	var lits []*ast.FuncLit // keys(funcLits), in order

	nodeFilter := []ast.Node{
		(*ast.FuncDecl)(nil),
		(*ast.FuncLit)(nil),
	}
	inspect.Preorder(nodeFilter, func(n ast.Node) {
		switch n := n.(type) {
		case *ast.FuncDecl:
			// Type information may be incomplete.
			if fn, ok := pass.TypesInfo.Defs[n.Name].(*types.Func); ok {
				funcDecls[fn] = &declInfo{decl: n}
				decls = append(decls, fn)
			}
		case *ast.FuncLit:
			funcLits[n] = new(litInfo)
			lits = append(lits, n)
		}
	})

	c := &CFGs{
		defs:      pass.TypesInfo.Defs,
		funcDecls: funcDecls,
		funcLits:  funcLits,
		pass:      pass,
	}

	// Pass 2. Build CFGs.

	// Build CFGs for named functions.
	// Cycles in the static call graph are broken
	// arbitrarily but deterministically.
	// We create noReturn facts as discovered.
	for _, fn := range decls {
		c.buildDecl(fn, funcDecls[fn])
	}

	// Build CFGs for literal functions.
	// These aren't relevant to facts (since they aren't named)
	// but are required for the CFGs.FuncLit API.
	for _, lit := range lits {
		li := funcLits[lit]
		if li.cfg == nil {
			li.cfg = cfg.New(lit.Body, c.callMayReturn)
			if !hasReachableReturn(li.cfg) {
				li.noReturn = true
			}
		}
	}

	// All CFGs are now built.
	c.pass = nil

	return c, nil
}

// di.cfg may be nil on return.
func (c *CFGs) buildDecl(fn *types.Func, di *declInfo) {
	// buildDecl may call itself recursively for the same function,
	// because cfg.New is passed the callMayReturn method, which
	// builds the CFG of the callee, leading to recursion.
	// The buildDecl call tree thus resembles the static call graph.
	// We mark each node when we start working on it to break cycles.

	if !di.started { // break cycle
		di.started = true

		if isIntrinsicNoReturn(fn) {
			di.noReturn = true
		}
		if di.decl.Body != nil {
			di.cfg = cfg.New(di.decl.Body, c.callMayReturn)
			if !hasReachableReturn(di.cfg) {
				di.noReturn = true
			}
		}
		if di.noReturn {
			c.pass.ExportObjectFact(fn, new(noReturn))
		}

		// debugging
		if false {
			log.Printf("CFG for %s:\n%s (noreturn=%t)\n", fn, di.cfg.Format(c.pass.Fset), di.noReturn)
		}
	}
}

// callMayReturn reports whether the called function may return.
// It is passed to the CFG builder.
func (c *CFGs) callMayReturn(call *ast.CallExpr) (r bool) {
	if id, ok := call.Fun.(*ast.Ident); ok && c.pass.TypesInfo.Uses[id] == panicBuiltin {
		return false // panic never returns
	}

	// Is this a static call? Also includes static functions
	// parameterized by a type. Such functions may or may not
	// return depending on the parameter type, but in some
	// cases the answer is definite. We let ctrlflow figure
	// that out.
	fn := typeutil.StaticCallee(c.pass.TypesInfo, call)
	if fn == nil {
		return true // callee not statically known; be conservative
	}

	// Function or method declared in this package?
	if di, ok := c.funcDecls[fn]; ok {
		c.buildDecl(fn, di)
		return !di.noReturn
	}

	// Not declared in this package.
	// Is there a fact from another package?
	return !c.pass.ImportObjectFact(fn, new(noReturn))
}

var panicBuiltin = types.Universe.Lookup("panic").(*types.Builtin)

func hasReachableReturn(g *cfg.CFG) bool {
	for _, b := range g.Blocks {
		if b.Live && b.Return() != nil {
			return true
		}
	}
	return false
}

// isIntrinsicNoReturn reports whether a function intrinsically never
// returns because it stops execution of the calling thread.
// It is the base case in the recursion.
func isIntrinsicNoReturn(fn *types.Func) bool {
	// Add functions here as the need arises, but don't allocate memory.
	path, name := fn.Pkg().Path(), fn.Name()
	return path == "syscall" && (name == "Exit" || name == "ExitProcess" || name == "ExitThread") ||
		path == "runtime" && name == "Goexit"
}
