func (check *Checker) use(arg ...ast.Expr) {
var x operand
for _, e := range arg {
- check.rawExpr(&x, e, nil)
+ if e != nil { // be safe
+ check.rawExpr(&x, e, nil)
+ }
}
}
}
default:
+ // when "using" all elements unpack KeyValueExpr
+ // explicitly because check.use doesn't accept them
+ for _, e := range e.Elts {
+ if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+ // Ideally, we should also "use" kv.Key but we can't know
+ // if it's an externally defined struct key or not. Going
+ // forward anyway can lead to other errors. Give up instead.
+ e = kv.Value
+ }
+ check.use(e)
+ }
// if utyp is invalid, an error was reported before
if utyp != Typ[Invalid] {
check.errorf(e.Pos(), "invalid composite literal type %s", typ)
case *ast.IndexExpr:
check.expr(x, e.X)
if x.mode == invalid {
+ check.use(e.Index)
goto Error
}
case *ast.SliceExpr:
check.expr(x, e.X)
if x.mode == invalid {
+ check.use(e.Low, e.High, e.Max)
goto Error
}
_ = u
_ = v
}
+
+// Test that we don't get "declared but not used"
+// errors in the context of invalid/C objects.
+func issue20358() {
+ var F C /* ERROR "undeclared" */ .F
+ var A C /* ERROR "undeclared" */ .A
+ var S C /* ERROR "undeclared" */ .S
+ type T C /* ERROR "undeclared" */ .T
+ type P C /* ERROR "undeclared" */ .P
+
+ // these variables must be "used" even though
+ // the LHS expressions/types below in which
+ // context they are used are unknown/invalid
+ var f, a, s1, s2, s3, t, p int
+
+ _ = F(f)
+ _ = A[a]
+ _ = S[s1:s2:s3]
+ _ = T{t}
+ _ = P{f: p}
+}