Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / ssa / source.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package ssa
6
7 // This file defines utilities for working with source positions
8 // or source-level named entities ("objects").
9
10 // TODO(adonovan): test that {Value,Instruction}.Pos() positions match
11 // the originating syntax, as specified.
12
13 import (
14         "go/ast"
15         "go/token"
16         "go/types"
17 )
18
19 // EnclosingFunction returns the function that contains the syntax
20 // node denoted by path.
21 //
22 // Syntax associated with package-level variable specifications is
23 // enclosed by the package's init() function.
24 //
25 // Returns nil if not found; reasons might include:
26 //    - the node is not enclosed by any function.
27 //    - the node is within an anonymous function (FuncLit) and
28 //      its SSA function has not been created yet
29 //      (pkg.Build() has not yet been called).
30 //
31 func EnclosingFunction(pkg *Package, path []ast.Node) *Function {
32         // Start with package-level function...
33         fn := findEnclosingPackageLevelFunction(pkg, path)
34         if fn == nil {
35                 return nil // not in any function
36         }
37
38         // ...then walk down the nested anonymous functions.
39         n := len(path)
40 outer:
41         for i := range path {
42                 if lit, ok := path[n-1-i].(*ast.FuncLit); ok {
43                         for _, anon := range fn.AnonFuncs {
44                                 if anon.Pos() == lit.Type.Func {
45                                         fn = anon
46                                         continue outer
47                                 }
48                         }
49                         // SSA function not found:
50                         // - package not yet built, or maybe
51                         // - builder skipped FuncLit in dead block
52                         //   (in principle; but currently the Builder
53                         //   generates even dead FuncLits).
54                         return nil
55                 }
56         }
57         return fn
58 }
59
60 // HasEnclosingFunction returns true if the AST node denoted by path
61 // is contained within the declaration of some function or
62 // package-level variable.
63 //
64 // Unlike EnclosingFunction, the behaviour of this function does not
65 // depend on whether SSA code for pkg has been built, so it can be
66 // used to quickly reject check inputs that will cause
67 // EnclosingFunction to fail, prior to SSA building.
68 //
69 func HasEnclosingFunction(pkg *Package, path []ast.Node) bool {
70         return findEnclosingPackageLevelFunction(pkg, path) != nil
71 }
72
73 // findEnclosingPackageLevelFunction returns the Function
74 // corresponding to the package-level function enclosing path.
75 //
76 func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {
77         if n := len(path); n >= 2 { // [... {Gen,Func}Decl File]
78                 switch decl := path[n-2].(type) {
79                 case *ast.GenDecl:
80                         if decl.Tok == token.VAR && n >= 3 {
81                                 // Package-level 'var' initializer.
82                                 return pkg.init
83                         }
84
85                 case *ast.FuncDecl:
86                         if decl.Recv == nil && decl.Name.Name == "init" {
87                                 // Explicit init() function.
88                                 for _, b := range pkg.init.Blocks {
89                                         for _, instr := range b.Instrs {
90                                                 if instr, ok := instr.(*Call); ok {
91                                                         if callee, ok := instr.Call.Value.(*Function); ok && callee.Pkg == pkg && callee.Pos() == decl.Name.NamePos {
92                                                                 return callee
93                                                         }
94                                                 }
95                                         }
96                                 }
97                                 // Hack: return non-nil when SSA is not yet
98                                 // built so that HasEnclosingFunction works.
99                                 return pkg.init
100                         }
101                         // Declared function/method.
102                         return findNamedFunc(pkg, decl.Name.NamePos)
103                 }
104         }
105         return nil // not in any function
106 }
107
108 // findNamedFunc returns the named function whose FuncDecl.Ident is at
109 // position pos.
110 //
111 func findNamedFunc(pkg *Package, pos token.Pos) *Function {
112         // Look at all package members and method sets of named types.
113         // Not very efficient.
114         for _, mem := range pkg.Members {
115                 switch mem := mem.(type) {
116                 case *Function:
117                         if mem.Pos() == pos {
118                                 return mem
119                         }
120                 case *Type:
121                         mset := pkg.Prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
122                         for i, n := 0, mset.Len(); i < n; i++ {
123                                 // Don't call Program.Method: avoid creating wrappers.
124                                 obj := mset.At(i).Obj().(*types.Func)
125                                 if obj.Pos() == pos {
126                                         return pkg.values[obj].(*Function)
127                                 }
128                         }
129                 }
130         }
131         return nil
132 }
133
134 // ValueForExpr returns the SSA Value that corresponds to non-constant
135 // expression e.
136 //
137 // It returns nil if no value was found, e.g.
138 //    - the expression is not lexically contained within f;
139 //    - f was not built with debug information; or
140 //    - e is a constant expression.  (For efficiency, no debug
141 //      information is stored for constants. Use
142 //      go/types.Info.Types[e].Value instead.)
143 //    - e is a reference to nil or a built-in function.
144 //    - the value was optimised away.
145 //
146 // If e is an addressable expression used in an lvalue context,
147 // value is the address denoted by e, and isAddr is true.
148 //
149 // The types of e (or &e, if isAddr) and the result are equal
150 // (modulo "untyped" bools resulting from comparisons).
151 //
152 // (Tip: to find the ssa.Value given a source position, use
153 // astutil.PathEnclosingInterval to locate the ast.Node, then
154 // EnclosingFunction to locate the Function, then ValueForExpr to find
155 // the ssa.Value.)
156 //
157 func (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {
158         if f.debugInfo() { // (opt)
159                 e = unparen(e)
160                 for _, b := range f.Blocks {
161                         for _, instr := range b.Instrs {
162                                 if ref, ok := instr.(*DebugRef); ok {
163                                         if ref.Expr == e {
164                                                 return ref.X, ref.IsAddr
165                                         }
166                                 }
167                         }
168                 }
169         }
170         return
171 }
172
173 // --- Lookup functions for source-level named entities (types.Objects) ---
174
175 // Package returns the SSA Package corresponding to the specified
176 // type-checker package object.
177 // It returns nil if no such SSA package has been created.
178 //
179 func (prog *Program) Package(obj *types.Package) *Package {
180         return prog.packages[obj]
181 }
182
183 // packageLevelValue returns the package-level value corresponding to
184 // the specified named object, which may be a package-level const
185 // (*Const), var (*Global) or func (*Function) of some package in
186 // prog.  It returns nil if the object is not found.
187 //
188 func (prog *Program) packageLevelValue(obj types.Object) Value {
189         if pkg, ok := prog.packages[obj.Pkg()]; ok {
190                 return pkg.values[obj]
191         }
192         return nil
193 }
194
195 // FuncValue returns the concrete Function denoted by the source-level
196 // named function obj, or nil if obj denotes an interface method.
197 //
198 // TODO(adonovan): check the invariant that obj.Type() matches the
199 // result's Signature, both in the params/results and in the receiver.
200 //
201 func (prog *Program) FuncValue(obj *types.Func) *Function {
202         fn, _ := prog.packageLevelValue(obj).(*Function)
203         return fn
204 }
205
206 // ConstValue returns the SSA Value denoted by the source-level named
207 // constant obj.
208 //
209 func (prog *Program) ConstValue(obj *types.Const) *Const {
210         // TODO(adonovan): opt: share (don't reallocate)
211         // Consts for const objects and constant ast.Exprs.
212
213         // Universal constant? {true,false,nil}
214         if obj.Parent() == types.Universe {
215                 return NewConst(obj.Val(), obj.Type())
216         }
217         // Package-level named constant?
218         if v := prog.packageLevelValue(obj); v != nil {
219                 return v.(*Const)
220         }
221         return NewConst(obj.Val(), obj.Type())
222 }
223
224 // VarValue returns the SSA Value that corresponds to a specific
225 // identifier denoting the source-level named variable obj.
226 //
227 // VarValue returns nil if a local variable was not found, perhaps
228 // because its package was not built, the debug information was not
229 // requested during SSA construction, or the value was optimized away.
230 //
231 // ref is the path to an ast.Ident (e.g. from PathEnclosingInterval),
232 // and that ident must resolve to obj.
233 //
234 // pkg is the package enclosing the reference.  (A reference to a var
235 // always occurs within a function, so we need to know where to find it.)
236 //
237 // If the identifier is a field selector and its base expression is
238 // non-addressable, then VarValue returns the value of that field.
239 // For example:
240 //    func f() struct {x int}
241 //    f().x  // VarValue(x) returns a *Field instruction of type int
242 //
243 // All other identifiers denote addressable locations (variables).
244 // For them, VarValue may return either the variable's address or its
245 // value, even when the expression is evaluated only for its value; the
246 // situation is reported by isAddr, the second component of the result.
247 //
248 // If !isAddr, the returned value is the one associated with the
249 // specific identifier.  For example,
250 //       var x int    // VarValue(x) returns Const 0 here
251 //       x = 1        // VarValue(x) returns Const 1 here
252 //
253 // It is not specified whether the value or the address is returned in
254 // any particular case, as it may depend upon optimizations performed
255 // during SSA code generation, such as registerization, constant
256 // folding, avoidance of materialization of subexpressions, etc.
257 //
258 func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {
259         // All references to a var are local to some function, possibly init.
260         fn := EnclosingFunction(pkg, ref)
261         if fn == nil {
262                 return // e.g. def of struct field; SSA not built?
263         }
264
265         id := ref[0].(*ast.Ident)
266
267         // Defining ident of a parameter?
268         if id.Pos() == obj.Pos() {
269                 for _, param := range fn.Params {
270                         if param.Object() == obj {
271                                 return param, false
272                         }
273                 }
274         }
275
276         // Other ident?
277         for _, b := range fn.Blocks {
278                 for _, instr := range b.Instrs {
279                         if dr, ok := instr.(*DebugRef); ok {
280                                 if dr.Pos() == id.Pos() {
281                                         return dr.X, dr.IsAddr
282                                 }
283                         }
284                 }
285         }
286
287         // Defining ident of package-level var?
288         if v := prog.packageLevelValue(obj); v != nil {
289                 return v.(*Global), true
290         }
291
292         return // e.g. debug info not requested, or var optimized away
293 }