Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot compile in Visual Studio 2015 #31

Closed
CurtisHx opened this issue Feb 14, 2017 · 5 comments
Closed

Cannot compile in Visual Studio 2015 #31

CurtisHx opened this issue Feb 14, 2017 · 5 comments

Comments

@CurtisHx
Copy link

CurtisHx commented Feb 14, 2017

I'm trying to use FFF from within Visual Studio 2015 and VC++, and the example I tried (attached) does not want to compile. Here's the test file:


extern "C"
{
#include "driver.h"
#include "registers.h"
}
#include <stdint.h>
#include "CppUnitTest.h"
#include "fff.h"

DEFINE_FFF_GLOBALS;

FAKE_VOID_FUNC(IO_MEM_WR8, uint32_t, uint8_t);
FAKE_VALUE_FUNC(uint8_t, IO_MEM_RD8, uint32_t);

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace FFFTestProject
{		
	TEST_CLASS(UnitTest1)
	{
	public:
    TEST_METHOD_INITIALIZE(Init)
    {
      /*RESET_FAKE(IO_MEM_WR8);
      RESET_FAKE(IO_MEM_RD8);
      FFF_RESET_HISTORY();*/
    }
		
		TEST_METHOD(TestMethod1)
		{
			// TODO: Your test code here
		}

	};
}`

The FAKE_VOID_FUNC and FAKE_VALUE_FUNC macros are generating the following warning.

Warning C4003 not enough actual parameters for macro 'PP_ARG_MINUS1_N' FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12

Trying to compile generates the following errors, all stemming from the FAKE_VOID_FUNC and FAKE_VALUE_FUNC macros.

Error C2065 'IO_MEM_WR8': undeclared identifier FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2065 'IO_MEM_WR8': undeclared identifier FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2275 'uint32_t': illegal use of this type as an expression FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2275 'uint32_t': illegal use of this type as an expression FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2275 'uint8_t': illegal use of this type as an expression FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2275 'uint8_t': illegal use of this type as an expression FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2440 'initializing': cannot convert from 'initializer list' to 'int' FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12
Error C2440 'initializing': cannot convert from 'initializer list' to 'int' FFFTestProject c:\temp\projects\ffftestproject\ffftestproject\unittest1.cpp 12

FFFTestProject.zip

@CurtisHx
Copy link
Author

Tracking it down further (I don't have a solution yet...), it has to do with the way that the VC++ preprocessor expands (or lack thereof) of __VA_ARGS__. Of course Microsoft would have to do it differently from everyone else...

@CurtisHx
Copy link
Author

CurtisHx commented Feb 15, 2017

It looks like it's a difference in the way GCC and Visual Studio treat __VA_ARGS__. GCC expands __VA_ARGS___ before passing it into the macro. Visual Studio expands __VA_ARGS__ after passing it.

See this answer on Stack Overflow: http://stackoverflow.com/a/5530998

A fix is to force the macro expansion by wrapping macros taking in __VA_ARGS__ with this macro:

#define EXPAND (x) x

For example, the FAKE_VOID_FUNC call chain in fff.h goes from

#define FAKE_VOID_FUNC(...)     FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)

#define FUNC_VOID_(N,...)     FUNC_VOID_N(N,__VA_ARGS__)

#define FUNC_VOID_N(N,...)     FAKE_VOID_FUNC ## N(__VA_ARGS__)

to

#define FAKE_VOID_FUNC(...)     EXPAND(FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__))

#define FUNC_VOID_(N,...)     EXPAND(FUNC_VOID_N(N,__VA_ARGS__))

#define FUNC_VOID_N(N,...)     EXPAND(FAKE_VOID_FUNC ## N(__VA_ARGS__))

In addition, the PP_NARG_MINUS1 and PP_NARG_MINUS1_ macros need to be wrapped similarly.

I'm 99% confident this fix will work with GCC as well as VC++. I'm just not sure how to go about making the change in the ruby generation file.

@shebaw
Copy link

shebaw commented May 22, 2017

You can explicitly use the numbered functions as a workaround.
Example:
FAKE_VALUE_FUNC1(void *, malloc, size_t)

@VincentDary
Copy link

VincentDary commented Dec 14, 2017

I work with gcc on linux and cl.exe on windows, the EXPAND trick work well for M$. Thank's

@meekrosoft
Copy link
Owner

Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants