Skip to content

x/tools/go/analysis/passes/shift: allow full-width integer shifts #58030

@rsc

Description

@rsc

The shift pass rejects a uint64 shifted by a constant 64, and on 32 bit platforms a uint shifted by 32, both of which come up in correct code. Here are two examples:

From a recent x/sys/unix CL:

func offs2lohi(offs int64) (lo, hi uintptr) {
	const longBits = SizeofLong * 8
	return uintptr(offs), uintptr(uint64(offs) >> longBits)
}

On a 64-bit system, the goal is to return offs, 0, and that expression does that, using a uint64 >> 64 in the second expression. I am going to send a CL out replacing >> longBits with >> (longBits - 1) >> 1, to make older vets happy with this code.

From a recent math/big CL:

// bits.Len uses a lookup table for the low-order bits on some
// architectures. Neutralize any input-dependent behavior by setting all
// bits after the first one bit.
top := uint(x[i])
top |= top >> 1
top |= top >> 2
top |= top >> 4
top |= top >> 8
top |= top >> 16
top |= top >> 16 >> 16 // ">> 32" doesn't compile on 32-bit architectures
return i*_W + bits.Len(top)

Note the comment says "doesn't compile" but really the problem is that it doesn't vet.

Vet should not be redefining what is permitted in the language for valid code. Because these programs are valid, we should loosen the check in passes/shift/shift.go to be amt > maxSize, not amt >= maxSize.

Metadata

Metadata

Assignees

No one assigned

    Labels

    AnalysisIssues related to static analysis (vet, x/tools/go/analysis)NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions