+// mayModifyPkgVar reports whether expression n may modify any
+// package-scope variables declared within the current package.
+func mayModifyPkgVar(n ir.Node) bool {
+ // safeLHS reports whether the assigned-to variable lhs is either a
+ // local variable or a global from another package.
+ safeLHS := func(lhs ir.Node) bool {
+ v, ok := ir.OuterValue(lhs).(*ir.Name)
+ return ok && v.Op() == ir.ONAME && !(v.Class == ir.PEXTERN && v.Sym().Pkg == types.LocalPkg)
+ }
+
+ return ir.Any(n, func(n ir.Node) bool {
+ switch n.Op() {
+ case ir.OCALLFUNC, ir.OCALLINTER:
+ return !ir.IsFuncPCIntrinsic(n.(*ir.CallExpr))
+
+ case ir.OAPPEND, ir.OCLEAR, ir.OCOPY:
+ return true // could mutate a global array
+
+ case ir.OAS:
+ n := n.(*ir.AssignStmt)
+ if !safeLHS(n.X) {
+ return true
+ }
+
+ case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
+ n := n.(*ir.AssignListStmt)
+ for _, lhs := range n.Lhs {
+ if !safeLHS(lhs) {
+ return true
+ }
+ }
+ }
+
+ return false
+ })
+}
+