Okay this is embarrassing.
There was no difference between C and C++ so I spent all morning slowly removing things from my (rather large) project, only to discover this little gem in some 'helper' code I hadn't looked at for a very long time:
float fabsf( float f ) {
if ( f >= 0 )
return f;
return f;
}
I don't recall making this, or why it was even necessary to make my own in the first place, or how I could have screwed it up and not suffered any problems until now, in over a year of working on this project.
But anyway, for some reason atanf finds it necessary to call fabsf (why??), but only in the case where the operand is a variable, not a literal, ie:
float a = atanf( -1.0f ); // does NOT call fabsf
float b = -1.0f;
float c = atanf( b ); // calls my broken fabsf
Thanks for the assistance Jan, sorry for the weird screwup.