Skip to content

Commit a6b8923

Browse files
committed
SA4006: Fix for compound operators, increment/decrement
In the case of compound operators such as +=, -=, etc we need to use the left-hand side to get the value. For IncDec we need a different codepath from AssignStmt altogether. Fixes #1329
1 parent 80d98d7 commit a6b8923

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

staticcheck/sa4006/sa4006.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sa4006
33
import (
44
"fmt"
55
"go/ast"
6+
"go/token"
67

78
"honnef.co/go/tools/analysis/code"
89
"honnef.co/go/tools/analysis/facts/generated"
@@ -31,7 +32,7 @@ var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
3132

3233
var Analyzer = SCAnalyzer.Analyzer
3334

34-
func run(pass *analysis.Pass) (interface{}, error) {
35+
func run(pass *analysis.Pass) (any, error) {
3536
for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3637
if irutil.IsExample(fn) {
3738
continue
@@ -99,6 +100,22 @@ func run(pass *analysis.Pass) (interface{}, error) {
99100
}
100101

101102
ast.Inspect(node, func(node ast.Node) bool {
103+
inc, ok := node.(*ast.IncDecStmt)
104+
if ok {
105+
val, _ := fn.ValueForExpr(inc.X)
106+
if val == nil {
107+
return true
108+
}
109+
if _, ok := val.(*ir.Const); ok {
110+
// a zero-valued constant, for example in 'foo := []string(nil)'
111+
return true
112+
}
113+
if !hasUse(val, nil) {
114+
report.Report(pass, inc, fmt.Sprintf("this value of %s is never used", inc.X))
115+
}
116+
return true
117+
}
118+
102119
assign, ok := node.(*ast.AssignStmt)
103120
if !ok {
104121
return true
@@ -137,7 +154,12 @@ func run(pass *analysis.Pass) (interface{}, error) {
137154
}
138155
val, _ := fn.ValueForExpr(rhs)
139156
if val == nil {
140-
continue
157+
if assign.Tok != token.ASSIGN { // +=, *=, etc.
158+
val, _ = fn.ValueForExpr(lhs)
159+
}
160+
if val == nil {
161+
continue
162+
}
141163
}
142164

143165
if _, ok := val.(*ir.Const); ok {

staticcheck/sa4006/testdata/src/example.com/CheckUnreadVariableValues/CheckUnreadVariableValues.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,43 @@ func fn10() {
142142
}
143143
fmt.Println(slice)
144144
}
145+
146+
func issue1329() {
147+
{
148+
n := 1
149+
n += 1 //@ diag(`this value of n is never used`)
150+
}
151+
{
152+
n := 1
153+
n ^= 1 //@ diag(`this value of n is never used`)
154+
}
155+
{
156+
n := ""
157+
n += "" //@ diag(`this value of n is never used`)
158+
}
159+
{
160+
n := 1
161+
n++ //@ diag(`this value of n is never used`)
162+
}
163+
164+
{
165+
n := 1
166+
n += 1
167+
fmt.Println(n)
168+
}
169+
{
170+
n := 1
171+
n ^= 1
172+
fmt.Println(n)
173+
}
174+
{
175+
n := ""
176+
n += ""
177+
fmt.Println(n)
178+
}
179+
{
180+
n := 1
181+
n++
182+
fmt.Println(n)
183+
}
184+
}

0 commit comments

Comments
 (0)