Skip to content

bug(instrument): Compiler directives misplaced after instrumentation #32

@kolkov

Description

@kolkov

Description

When instrumenting files that contain compiler directives like //go:noinline, //go:nosplit, etc., the directive gets incorrectly moved to the import block instead of staying before the function declaration.

Reproduction

Input:

package main

//go:noinline
func update(x *int) {
    *x++
}

Expected output:

package main

import (
    race "github.com/kolkov/racedetector/race"
    "unsafe"
)

//go:noinline
func update(x *int) {
    race.RaceRead(uintptr(unsafe.Pointer(x)))
    race.RaceWrite(uintptr(unsafe.Pointer(x)))
    *x++
}

Actual output:

package main

import (
    race "github.com/kolkov/racedetector/race"

    //go:noinline   // <-- WRONG! Directive moved here!
    "unsafe"
)

func update(x *int) {
    race.RaceRead(uintptr(unsafe.Pointer(x)))
    race.RaceWrite(uintptr(unsafe.Pointer(x)))
    *x++
}

Error

When compiling the instrumented code:

./file.go:8:4: misplaced compiler directive

Root Cause

The go/printer package moves comments incorrectly when injectImports() modifies the import declarations. The directive comment gets associated with the wrong AST node.

Affected Directives

  • //go:noinline
  • //go:nosplit
  • //go:linkname
  • //go:norace
  • Other compiler directives before function declarations

Workaround

Currently, users must remove compiler directives from their code before using racedetector, or avoid using racedetector on files with such directives.

Proposed Fix

  1. Before calling injectImports(), scan for compiler directive comments
  2. Preserve their positions relative to function declarations
  3. After import injection, restore directive comments to correct positions

Or alternatively:

  • Use go/ast comment manipulation to explicitly attach directives to their target functions

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions