Porting from MSVC to GCC, vague errors

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • qartar
    New Member
    • Nov 2008
    • 12

    Porting from MSVC to GCC, vague errors

    As the title says, I am porting some code from MSVC (not sure which version, using Visual Studio 2008), which compiles without errors or warnings, to GCC 4.0 which generates a large number of generic errors.

    The project uses a large header file 'precompiled.h' which includes two other header files, math/math.h and math/vector.h in that order. I've already disabled the ALWAYS_SEARCH_U SER_PATHS which was causing other errors.

    From math/math.h

    Code:
    class qMath {
    public:
    ...[INDENT]static float Fabs( float x );[/INDENT]
    ...
    };
    
    inline float qMath::Fabs( float x ) {
    ...[INDENT]return x;[/INDENT]
    }
    From math/vector.h

    Code:
    inline bool qVec2::Compare( const qVec2 &a, const float epsilon ) {
    // the following is line 106[INDENT]( qMath::Fabs( x - a.x ) > epsilon )[/INDENT]
    ...
    Which generates the following errors:

    ../math/Vector.h:106: error: 'qMath' has not been declared
    ../math/Vector.h:106: error: 'Fabs' was not declared in this scope

    And the same sort of errors wherever qMath is referenced.

    Been mucking around with this for awhile now and haven't gotten anywhere, any help would be appreciated.
  • boxfish
    Recognized Expert Contributor
    • Mar 2008
    • 469

    #2
    I doubt I can be of any help with this, but maybe you could post your makefile? It sounds like a problem with either your includes or your makefile.

    Comment

    • qartar
      New Member
      • Nov 2008
      • 12

      #3
      I'm using Xcode as my development environment and I'm not sure where exactly to view the makefile. It fails while trying to create the precompiled header object /precompiled.h.g ch, which is the first object being compiled.

      By using the -H compiler flag I can see that the headers are being added in the correct order, and errors are not generated until after all the headers have been included. Since this the code compiles without errors in MSVC I'm assuming it's something specific with GCC.

      Comment

      • boxfish
        Recognized Expert Contributor
        • Mar 2008
        • 469

        #4
        Okay, I see, sorry. I had thought you were just using a text editor, writing the makefiles by hand, and running gcc from the shell.

        Comment

        • Banfa
          Recognized Expert Expert
          • Feb 2006
          • 9067

          #5
          Is there a namespace declared in Math.h containing qMath? If so then

          qMath::Fabs

          needs to be

          <NameSpace>::qM ath::Fabs

          It is less likely to be something specific with GCC so much as some wired MS extension causing the code to compile when it shouldn't.

          Comment

          • qartar
            New Member
            • Nov 2008
            • 12

            #6
            Not using any namespace declarations.

            Comment

            • qartar
              New Member
              • Nov 2008
              • 12

              #7
              If it is because of MS specific extensions it is near impossible for me to tell which or why since disabling their extensions prevents even their standard header files from compiling.

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                Yes I know quite irritating isn't it :7

                Hmmm, given what we can see of your code all I can say is that for some reason (when using GCC) at the time that vector.h is parsed the declarations in Math.h have not been parsed so the compiler does not know about qMath (Vector.h isn't included into Math.h is it?).

                You can test this by forward declaring qMath
                class qMath;

                at the top of vector.h, this will not solve the problem but it should give different errors (incomplete type).

                Comment

                • qartar
                  New Member
                  • Nov 2008
                  • 12

                  #9
                  Originally posted by Banfa
                  Yes I know quite irritating isn't it :7

                  Hmmm, given what we can see of your code all I can say is that for some reason (when using GCC) at the time that vector.h is parsed the declarations in Math.h have not been parsed so the compiler does not know about qMath (Vector.h isn't included into Math.h is it?).

                  You can test this by forward declaring qMath
                  class qMath;

                  at the top of vector.h, this will not solve the problem but it should give different errors (incomplete type).
                  That is what I suspected even though, as I said, the headers are included in the correct order. I've actually already tried forward declaring qMath which generates the incomplete type errors you predicted. I'm about at wit's end trying to understand what could be wrong here.

                  I suppose it interesting that the error that I get about qMath is slightly different than those generated by other unrecognized symbols, I'm not sure if this is just because it is interpreted as a scoping symbol or what...

                  Compare:
                  /qlib/math/Vector.h:106: error: 'qMath' has not been declared
                  /qlib/Str.h:330: error: 'sprintf_s' was not declared in this scope

                  Second error is an easy fix, added just for reference here.

                  Edit: I forgot to mention that I've also tried to include math.h directly from vector.h which changes nothing from the original compilation routine. Can the qMath class be being ignored by gcc without generating warnings or errors or something of that nature?
                  Last edited by qartar; Nov 11 '08, 09:38 AM. Reason: Addendum.

                  Comment

                  • Banfa
                    Recognized Expert Expert
                    • Feb 2006
                    • 9067

                    #10
                    No GCC would not be ignoring qMath for no reason without a diagnostic.

                    Can you post the preprocessor commands from each file please (2 headers and a cpp I presume).

                    Comment

                    • qartar
                      New Member
                      • Nov 2008
                      • 12

                      #11
                      No .cpp file since it tries to compile object code for the precompiled header first. I hope you're prepared for quite a bit of code. I've included everything up to pertinent parts except for other headers.

                      Code:
                      //	qlib/precompiled.h
                      //
                      
                      #ifndef __PRECOMPILED_H__
                      #define __PRECOMPILED_H__
                      
                      //---------------------------------------------------------
                      
                      #if !defined( _DEBUG ) && !defined( NDEBUG )
                      	// dont generate asserts
                      	#define NDEBUG
                      #endif
                      
                      #if defined( _WIN32 )
                      
                      #define	WIN32_LEAN_AND_MEAN
                      
                      #include <winsock2.h>
                      #include <mmsystem.h>
                      
                      #define	DIRECTINPUT_VERSION	0x0700
                      #define	DIRECTSOUND_VERSION	0x0800
                      
                      #pragma warning (disable : 4244)		// conversion to smaller type, possible loss of data
                      
                      #include <malloc.h>
                      #include <windows.h>
                      #undef FindText
                      
                      #endif //_WIN32
                      
                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <stdarg.h>
                      #include <string.h>
                      #include <assert.h>
                      #include <math.h>
                      
                      #include "../sys/Public.h"
                      
                      //---------------------------------------------------------
                      
                      // qLib
                      #include "../qlib/Lib.h"
                      ...omitting rest of file.

                      Code:
                      //	Lib.h
                      //
                      
                      #ifndef __LIB_H__
                      #define __LIB_H__
                      
                      /*
                      ===============================================================================
                      
                      	Basic library interface
                      
                      ===============================================================================
                      */
                      
                      class qLib
                      {
                      public:
                      	static class qSys *			sys;
                      	static class qCommon *		common;
                      	static class qCVarSystem *	cvarSystem;
                      	static class qFileSystem *	fileSystem;
                      
                      	static void					Init( void );
                      	static void					Shutdown( void );
                      };
                      
                      /*
                      ===============================================================================
                      
                      	Types used throughout
                      
                      ===============================================================================
                      */
                      
                      typedef unsigned char	byte;
                      typedef unsigned short	word;
                      typedef unsigned long	dword;
                      
                      typedef int				qHandle_t;
                      
                      #define	INVALID_HANDLE	((qHandle_t)-1)
                      
                      #ifndef NULL
                      #define	NULL	((void *)0)
                      #endif
                      
                      #ifndef BIT
                      #define BIT(n)	( 1 << ( n ) )
                      #endif
                      
                      #define	MAX_STRING_CHARS	1024
                      
                      class qException {
                      public:
                      	char	error[MAX_STRING_CHARS];
                      
                      	qException( const char *text = "" ) { strcpy( error, text ); }
                      };
                      
                      /*
                      ===============================================================================
                      
                      	qLib headers
                      
                      ===============================================================================
                      */
                      
                      // memory allocation
                      #include "Heap.h"
                      #include "Swap.h"
                      #include "containers/List.h"
                      
                      // math
                      #include "math/SIMD.h"
                      #include "math/Math.h"
                      #include "math/Random.h"
                      #include "math/Vector.h"
                      #include "math/Matrix.h"
                      #include "math/Angles.h"
                      #include "math/Quat.h"
                      #include "math/Rotation.h"
                      #include "math/Plane.h"
                      #include "math/Pluecker.h"
                      #include "math/Integrator.h"
                      ...omitting rest of file.

                      Code:
                      //	Math.h
                      //
                      
                      #ifndef __MATH_H__
                      #define __MATH_H__
                      
                      /*
                      ===============================================================================
                      
                      	Math
                      
                      ===============================================================================
                      */
                      
                      #define	DEG2RAD(a)				( (a) * qMath::M_DEG2RAD )
                      #define	RAD2DEG(a)				( (a) * qMath::M_RAD2DEG )
                      
                      #define	SEC2MS(t)				( qMath::FtoiFast( (t) * qMath::M_SEC2MS ) )
                      #define MS2SEC(t)				( (t) * qMath::M_MS2SEC )
                      
                      #define FLOATSIGNBITSET(f)		((*(const unsigned long *)&(f)) >> 31)
                      #define FLOATSIGNBITNOTSET(f)	((~(*(const unsigned long *)&(f))) >> 31)
                      #define INTSIGNBITSET(i)		(((const unsigned long)(i)) >> 31)
                      #define INTSIGNBITNOTSET(i)		((~((const unsigned long)(i))) >> 31)
                      
                      #define FLOATSIGN(f)			( FLOATSIGNBITSET(f) ? -1 : 1 )
                      #define INTSIGN(i)				( INTSIGNBITSET(i) ? -1 : 1 )
                      
                      #define	FLOAT_IS_NAN(x)			(((*(const unsigned long *)&x) & 0x7f800000) == 0x7f800000)
                      #define FLOAT_IS_INF(x)			(((*(const unsigned long *)&x) & 0x7fffffff) == 0x7f800000)
                      #define FLOAT_IS_IND(x)			((*(const unsigned long *)&x) == 0xffc00000)
                      
                      template<class T> Q_INLINE T	Max( T x, T y ) { return ( x > y ) ? x : y; }
                      template<class T> Q_INLINE T	Min( T x, T y ) { return ( x < y ) ? x : y; }
                      template<class T> Q_INLINE T	Clamp( T x, T y, T z ) { return ( x < y ) ? y : ( x > z ) ? z : x; }
                      
                      template<class T> Q_INLINE T	Square( T x ) { return x * x; }
                      template<class T> Q_INLINE T	Cube( T x ) { return x * x * x; }
                      
                      class qMath {
                      public:
                      	static float			RSqrt( float x );
                      	static float			InvSqrt( float x );
                      
                      	static float			Sqrt( float x );
                      
                      	static void				SinCos( float a, float &s, float &c );
                      
                      	static float			ACos( float a );
                      
                      	static float			Tan( float a );
                      	static double			Tan64( float a );
                      
                      	static int				Abs( int x );
                      	static float			Fabs( float x );
                      
                      	static int				Ftoi( float f );
                      	static int				FtoiFast( float f );
                      	static unsigned long	Ftol( float f );
                      	static unsigned long	FtolFast( float f );
                      
                      	static int				FloatHash( const float *arr, const int count );
                      
                      	static const float		PI;				//	pi
                      	static const float		TWOPI;			//	pi * 2
                      	static const float		HALFPI;			//	pi / 2
                      	static const float		FOURTHPI;		//	pi / 4
                      	static const float		M_DEG2RAD;		//	degrees to radians multiplier
                      	static const float		M_RAD2DEG;		//	radians to degrees multiplier
                      	static const float		M_SEC2MS;		//	seconds to milliseconds multiplier
                      	static const float		M_MS2SEC;		//	milliseconds to seconds multiplier
                      	static const float		INFINITY;		//	huge number which should be larger than any valid number
                      };
                      
                      Q_INLINE float qMath::RSqrt( float x ) {
                      	int	i;
                      	float y, r;
                      
                      	y = x * 0.5f;
                      	i = *reinterpret_cast< int *>( &x );
                      	i = 0x5f3759df - ( i >> 1 );
                      	r = *reinterpret_cast< float *>( &i );
                      	r = r * ( 1.5f - r * r * y );
                      
                      	return r;
                      }
                      
                      Q_INLINE float qMath::InvSqrt( float x ) {
                      	int		i;
                      
                      	//	http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf suggests 0x5f375a86
                      	double y = x * 0.5f;
                      	i = *reinterpret_cast<int *>( &x );
                      	i = 0x5f3759df - ( i >> 1 );				//	initial guess
                      	double r = *reinterpret_cast<float *>( &i );
                      	r = r * ( 1.5f - r * r * y );				//	newtonian step
                      	r = r * ( 1.5f - r * r * y );
                      
                      	return (float )r;
                      }
                      
                      Q_INLINE float qMath::Sqrt( float x ) {
                      	return x * InvSqrt( x );
                      }
                      
                      Q_INLINE void qMath::SinCos( float a, float &s, float &c ) {
                      	s = sinf( a );
                      	c = cosf( a );
                      }
                      
                      Q_INLINE float qMath::Tan( float a ) {
                      	return tanf( a );
                      }
                      
                      Q_INLINE double qMath::Tan64( float a ) {
                      	return tan( a );
                      }
                      
                      Q_INLINE float qMath::ACos( float a ) {
                      	if ( a <= -1.0f ) {
                      		return PI;
                      	}
                      	if ( a >= 1.0f ) {
                      		return 0.0f;
                      	}
                      	return acosf( a );
                      }
                      
                      Q_INLINE int qMath::Abs( int x ) {
                      	int	y = x >> 31;
                      	return ( x ^ y ) - y;
                      }
                      
                      Q_INLINE float qMath::Fabs( float x ) {
                      	int	i = *reinterpret_cast<int *>( &x );
                      	i &= 0x7fffffff;
                      	return *reinterpret_cast<float *>( &i );
                      }
                      
                      Q_INLINE int qMath::Ftoi( float f ) {
                      	return (int )( f );
                      }
                      
                      Q_INLINE int qMath::FtoiFast( float f ) {
                      #ifdef _WIN32
                      	int	i;
                      	__asm fld	f
                      	__asm fistp	i
                      	return i;
                      #else
                      	return (int )f;
                      #endif
                      }
                      
                      Q_INLINE unsigned long qMath::Ftol( float f ) {
                      	return (unsigned long )( f );
                      }
                      
                      Q_INLINE unsigned long qMath::FtolFast( float f ) {
                      #ifdef _WIN32
                      	int	i;
                      	__asm fld	f
                      	__asm fistp	i
                      	return i;
                      #else
                      	return (unsigned long )( f );
                      #endif
                      }
                      
                      Q_INLINE int qMath::FloatHash( const float *arr, const int count ) {
                      	int i, hash = 0;
                      	const int *ptr;
                      
                      	ptr = reinterpret_cast<const int *>( arr );
                      	for ( i=0 ; i<count ; i++ ) {
                      		hash ^= ptr[ i ];
                      	}
                      	return hash;
                      }
                      
                      #endif //__MATH_H__
                      Code:
                      //	Vector.h
                      //
                      
                      #ifndef __MATH_VECTOR_H__
                      #define __MATH_VECTOR_H__
                      
                      /*
                      ===============================================================================
                      
                      	Vector classes
                      
                      ===============================================================================
                      */
                      
                      #define	VECTOR_EPSILON	0.001f
                      
                      class qAngles;
                      class qMat3;
                      
                      /*
                      ===================
                      qVec2
                      ===================
                      */
                      
                      class qVec2
                      {
                      public:
                      	float			x;
                      	float			y;
                      
                      					qVec2( void );
                      					qVec2( const float X, const float Y );
                      
                      	void			Set( const float X, const float Y );
                      	void			Clear( void );
                      	void			Zero( void );
                      
                      	float			operator[]( int index ) const;
                      	float &			operator[]( int index );
                      	qVec2			operator-() const;
                      	float			operator*( const qVec2 &a ) const;	// dot product
                      	float			operator^( const qVec2 &a ) const;	// cross product
                      	qVec2			operator*( const float a ) const;
                      	qVec2			operator/( const float a ) const;
                      	qVec2			operator+( const qVec2 &a ) const;
                      	qVec2			operator-( const qVec2 &a ) const;
                      	qVec2 &			operator+=( const qVec2 &a );
                      	qVec2 &			operator-=( const qVec2 &a );
                      	qVec2 &			operator*=( const float a );
                      	qVec2 &			operator/=( const float a );
                      
                      	friend qVec2	operator*( const float a, const qVec2 b );
                      
                      	bool			Compare( const qVec2 &a ) const;
                      	bool			Compare( const qVec2 &a, const float epsilon ) const;
                      	bool			operator==( const qVec2 &a ) const;
                      	bool			operator!=( const qVec2 &a ) const;
                      
                      	float			Dot( const qVec2 &a ) const;
                      	float			Cross( const qVec2 &a ) const;	// bi-linear anti-commutative
                      	qVec2			Cross( void ) const;			// orthogonal vector
                      	float			Length( void ) const;
                      	float			LengthSq( void ) const;
                      	float			Normalize( void );
                      
                      	const float *	ToFloatPtr( void ) const;
                      	float *			ToFloatPtr( void );
                      	const char *	ToString( int precision = 2 ) const;
                      
                      	void			Lerp( const qVec2 &v1, const qVec2 &v2, const float l );
                      };
                      
                      extern qVec2 vec2_origin;
                      #define vec2_zero vec2_origin
                      
                      Q_INLINE qVec2::qVec2( void ) {
                      }
                      
                      Q_INLINE qVec2::qVec2( const float X, const float Y ) {
                      	x = X;
                      	y = Y;
                      }
                      
                      Q_INLINE void qVec2::Set( const float X, const float Y ) {
                      	x = X;
                      	y = Y;
                      }
                      
                      Q_INLINE void qVec2::Clear( void ) {
                      	x = y = 0.0f;
                      }
                      
                      Q_INLINE void qVec2::Zero( void ) {
                      	x = y = 0.0f;
                      }
                      
                      Q_INLINE bool qVec2::Compare( const qVec2 &a ) const {
                      	return ( ( x == a.x ) && ( y == a.y ) );
                      }
                      
                      Q_INLINE bool qVec2::Compare( const qVec2 &a, const float epsilon ) const {
                      	if ( qMath::Fabs( x - a.x ) > epsilon )
                      		return false;
                      
                      	if ( qMath::Fabs( y - a.y ) > epsilon )
                      		return false;
                      	return true;
                      }
                      ...omitting rest of file.
                      This first reference and all subsequent references to qMath generate the errors.

                      Comment

                      • weaknessforcats
                        Recognized Expert Expert
                        • Mar 2007
                        • 9214

                        #12
                        I do not see the qMatch class or the inline function qMatch::Fabs in your vector.h.

                        Are you sure this class has been included before vector.h in your source file?

                        Comment

                        • qartar
                          New Member
                          • Nov 2008
                          • 12

                          #13
                          All source files include the precompiled header 'qlib/precompiled.h' which includes the header files in the order shown.

                          qMath::Fabs is declared and defined in qlib/math/Math.h which is included by qlib/Lib.h two lines before qlib/math/Vector.h which, as I understand it, means that qMath will always be declared when parsing Vector.h.

                          Comment

                          • donbock
                            Recognized Expert Top Contributor
                            • Mar 2008
                            • 2427

                            #14
                            I'm just an old C programmer, so this comment may not make sense in the brave new C++ world ...

                            Math.h doesn't include any files ... then how does it expect to reliably get a definition for Q_INLINE? Presumably that is supposed to be a macro that expands to "inline". Would a problem with that macro cause any of the symptoms you're seeing?

                            Comment

                            • qartar
                              New Member
                              • Nov 2008
                              • 12

                              #15
                              Originally posted by donbock
                              I'm just an old C programmer, so this comment may not make sense in the brave new C++ world ...

                              Math.h doesn't include any files ... then how does it expect to reliably get a definition for Q_INLINE? Presumably that is supposed to be a macro that expands to "inline". Would a problem with that macro cause any of the symptoms you're seeing?
                              Math.h is always included in sequence with other header files by the precompiled header. Q_INLINE is defined in ../sys/Public.h which is the first user file included by the precompiled header..

                              Your question definitely makes sense and is valid in C++, it's just the precompiled header strategy used in project that's throwing you off.

                              Comment

                              Working...