Sensitivity to variable's name

I recently showed, through exhaustive testing, that a static
variable named 'hi' accessed only in a function read_system_clock
was getting changed outside the function!

I know what you're thinking..the variable must be aliased, that is,
there must be another reference to it somewhere in the module.
But since the variable is static, it can't be seen outside
its module. And assuming the search (/) operation of vi works,
there is no other reference to it inside the module.
I checked it several times, because I thought there must be one.

BUT when I changed the variable name from 'hi' to 'upper' it
worked!

On the face of it, this appears to show blatant sensitivity to
the variable's name, but I'm open to alternate explanations.
The code is below, and for context I'm attaching the entire
module in a zip file. (Please excuse the commented-out
passages, this is experimental code.)

This is the second really screwy error I've found lately
in the ARM toolchain under the Arduino IDE.

// read_system_clock
static Time upper = 0LL;
static uint32_t m0 = 0L;
static const Time hi_1 = 0x0000000100000000LL;
static const uint32_t half = 0x00010000UL;
Time read_system_clock() {
  Time s = 0;
  enter_critical();
alpha:
  uint32_t m = micros();
  if (m0 > m) {
    if ((m0 - m) > half) {
      // rollover
      upper = upper + hi_1;

    } else {
      // m is in past..
      goto alpha;
    }
  }
  //the above will work if there are never
  //two consecutive lagging m's.

  I64 t2;
  t2.halves.hi = upper;
  t2.halves.lo = m;
  Time t = t2.whole;
  m0 = m;

  leave_critical();
  return t;

}

hw.cpp (8.65 KB)

Instead of a useless snippet or a 8K+ file, post an MRE that completely and concisely demonstrates the problem. And, specify the board you're compiling for.

This can happen, for example, if data is written to an array but past the beginning or the end, and the compiler allocates memory based on sorting the variable names alphabetically (as well as by size, type, etc.).

As suggested already, it would be preferable to have a simple compileable example that demonstrates the issue.

Or if “hi” is defined as a macro in some .h file somewhere...

I'm confused. You seem to be saying that something in the function 'read_system_clock()' is not doing what you want but the only place in your sketch where 'read_system_clock()' is called (marked '// for testing') is commented out.

union I64 {
  int64_t whole;
  struct {
     uint32_t lo;
     int32_t hi;
  } halves;
};

// read_system_clock
static Time upper = 0LL;
static uint32_t m0 = 0L;
static const Time hi_1 = 0x0000000100000000LL;
static const uint32_t half = 0x00010000UL;
Time read_system_clock() {
  Time s = 0;
//if (upper != 0) s = s | 16;
  enter_critical();
alpha:
  uint32_t m = micros();
  if (m0 > m) {
    if ((m0 - m) > half) {
      // rollover
      upper = upper + hi_1;
//s = s + 65536;

    } else {
      // m is in past..
      goto alpha;
    }
  }
  //the above will work if there are never
  //two consecutive lagging m's.

  //Time t = hi | m;

  I64 t2;
  t2.halves.hi = upper;
  t2.halves.lo = m;
  Time t = t2.whole;
//if (upper != 0) s = s | 2;
//if (t2.halves.hi != 0) s = s | 4;
//if (t >= hi_1) s = s | 8 ;
  
  m0 = m;

  leave_critical();
//  return s;
  return t;

}
 
// for testing
/**
static const uint64_t upper = 0xffffffff00000000ULL;
static void clock_init() {
  while ((t0 & upper) == 0) t0 = read_system_clock(); 
}
**/