MSVC: unexpected token '__cdecl', expected 'expression' - c++

Porting an application to Windows, I am now trying to compile it with VS2017 and am running into a host of problems. One of which is that a template wrapper I wrote to make a C++ member function available to be called from a C library (FUSE) doesn't work:
template <class T> class Callback {};
template <class T, class ...Arguments>
struct Callback<T(Arguments...)>
{
template <T(operations::*CALLBACK)(Arguments...)>
static T wrap(Arguments... parameters)
{
auto *instance = static_cast<operations*>(fuse_get_context()->private_data);
return (instance->*CALLBACK)(std::forward<Arguments>(parameters)...);
}
};
I am trying to set the callbacks like this in the constructor:
_operations.get_attr = Callback<std::remove_reference<decltype(*_high_level.getattr)>::type>::wrap<&operations::getattr>;
This is - I believe - valid code, but it doesn't comopile with some warnings and an error:
warning C4229: anachronism used: modifiers on data are ignored
error C2760: syntax error: unexpected token '__cdecl', expected 'expression'
note: see reference to function template instantiation 'T Callback<int (const char *,stat64_cygwin *)>::wrap<int operations::getattr(const char *,stat64_cygwin *)>(const char *,stat64_cygwin *)' being compiled
with
[
T=int
]
note: see reference to function template instantiation 'T Callback<int (const char *,stat64_cygwin *)>::wrap<int operations::getattr(const char *,stat64_cygwin *)>(const char *,stat64_cygwin *)' being compiled
with
[
T=int
]
error C2059: syntax error: '__cdecl'
The warning about anachronisms points to the line containing the template specifications for the wrap function. The error points to the line where the callback is actually invoked and returned, inside the wrap function.
It's very confusing, after reading somewhat I found that anachronisms are the sort-of attributes used in Windows APIs, which I don't use here, and I also don't have any __cdecl here. I have no idea how to proceed here.

Renaming CALLBACK to MEMFUNC worked. Apparantly, Windows defines CALLBACK to something unexpected, causing the code to be expanded in a way it doesn't compile.
Besides the fact that it's weird to just define random stuff like this (without prefixing it with WINDOWS_), it's unfortunate that the compiler generates errors which do not properly indicate that it originates in some #define, making it hard to debug.

Related

Errors when compiling catch with Visual Studio 2008

Update: using catch 1.9.7 solved this problem.
I am just getting started with using catch and have been unable to get even a simple test project to compile. I am using Visual Studio 2008 and have catch.hpp v1.10.0 (single file version).
I created a simple test project following the catch tutorial. main.cpp is the only file and the code consists of:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("test case 1")
{
REQUIRE(1==2);
}
I get the following errors when I compile:
c:\utilities\catch\catchtest\catchtest\catch.hpp(1333) : warning C4181: qualifier applied to reference type; ignored
c:\utilities\catch\catchtest\catchtest\catch.hpp(1838) : see reference to class template instantiation 'Catch::Internal::Evaluator<T1,T2,Op>' being compiled
with
[
T1=const int &,
T2=const int &,
Op=IsEqualTo
]
c:\utilities\catch\catchtest\catchtest\catch.hpp(1836) : while compiling class template member function 'void Catch::BinaryExpression<LhsT,Op,RhsT>::endExpression(void) const'
with
[
LhsT=const int &,
Op=IsEqualTo,
RhsT=const int &
]
c:\utilities\catch\catchtest\catchtest\main.cpp(8) : see reference to class template instantiation 'Catch::BinaryExpression<LhsT,Op,RhsT>' being compiled
with
[
LhsT=const int &,
Op=IsEqualTo,
RhsT=const int &
]
c:\utilities\catch\catchtest\catchtest\catch.hpp(1333) : error C2529: 'lhs' : reference to reference is illegal
c:\utilities\catch\catchtest\catchtest\catch.hpp(1333) : warning C4181: qualifier applied to reference type; ignored
c:\utilities\catch\catchtest\catchtest\catch.hpp(1333) : error C2529: 'rhs' : reference to reference is illegal
c:\utilities\catch\catchtest\catchtest\catch.hpp(1838) : error C2664: 'Catch::Internal::Evaluator<T1,T2,Op>::evaluate' : cannot convert parameter 1 from 'const int' to 'const int &(&)'
with
[
T1=const int &,
T2=const int &,
Op=IsEqualTo
]
c:\utilities\catch\catchtest\catchtest\catch.hpp(1839) : error C2228: left of '.endExpression' must have class/struct/union
Any assistance would be much appreciated. I haven't been able to find anything in the catch documentation or online and am eager to get started with it.
The latest master of Catch is for modern C++ compiler and the Visual Studio 2008 compiler is pretty old now. There's some switches you can use to downgrade some of the features:
https://github.com/philsquared/Catch/blob/master/docs/configuration.md
Try it with 'CATCH_CONFIG_NO_CPP11' defined before #include'ing catch.
For future reference: support for MSVC 9 was broken by this commit and reverting b6e7c9bd7a160c07c5de894292022687895c17a3 (done on top of it) and then this one is sufficient to fix the problem.

how to deal with a c++ related warning in boost option header file?

i have Microsoft Visual Studio (MSVS) 2012 Pro and i have set warning level to a slightly elevated level of 4. when doing this i am getting warnings for some of the included header files from the boost library. the message is this:
C:\Users\****\boost/optional/optional.hpp(595): warning C4244: 'initializing' : conversion from 'T_DOUBLE' to 'float', possible loss of data
C:\Users\****\boost/optional/optional.hpp(430) : see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::construct<double>(Expr &&,const void *)' being compiled
with
[
T=T_FLOAT,
Expr=T_DOUBLE
]
C:\Users\****\boost/optional/optional.hpp(430) : see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::construct<double>(Expr &&,const void *)' being compiled
with
[
T=T_FLOAT,
Expr=T_DOUBLE
]
the code in the file leading to this warning is this (line 610 on most recent beta of boost 1.64.0.B2 still resembles it exactly - but i am not on the beta now):
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
template<class Expr>
void construct ( Expr&& expr, void const* )
{
new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
m_initialized = true ;
}
what is the reason (=learn to understand) for this warning and how to eliminate it in the boost header for me any anyone else? alternatively thinking: does it make sense to "fix" it in such a global way, or is there a deeper meaning pointing rather to somewhere else (either boost or application codes) to improve or fix those other codes?
You are probably passing a double literal into method that expects float. Something like foo(1.0) instead of foo(1.0f)

(Default) construct an object for every variadic type

Consider this code snippet:
void Foo(std::string str1, std::string str2) {}
template<typename... Types>
void Bar()
{
Foo(Types{}...); // wont compile
}
Bar<std::string, std::string>();
What I want to do here is to default construct two std::string objects inside the Bar method and pass them to Foo. However my vain attempts (one of them being in the snippet) wont compile so I am wondering whether this is even possible.
I compiled with VC 2013, which throws compiler errors at me. As stated in the comments, other compilers can handle it. Can anyone tell whether the above snippet is standard conform?
It's a problem in the MSVC variadic template expansion process; when it unpacks the list of types it fails to recognise them as suitable for a constructor call. As a workaround, you can perform a type transformation to force the compiler to recognise them:
template<typename T> using identity_t = T; // NEW CODE
void Foo(int, int);
template<typename... Types>
void Bar()
{
Foo(identity_t<Types>{}...); // use identity type transformation
}
int main() {
Bar<int, int>();
}
I haven't managed to find an issue number yet.
This crashes the VC 2013 compiler for me. The errors seem to indicate that it has some problems parsing the code. So when the compiler crashes it must be a compiler bug.
1>main.cpp(23): error C2144: syntax error : 'std::string' should be preceded by ')'
1> main.cpp(28) : see reference to function template instantiation 'void Bar<std::string,std::string>(void)' being compiled
1>main.cpp(23): error C2660: 'Foo' : function does not take 0 arguments
1>main.cpp(23): error C2143: syntax error : missing ';' before '{'
1>main.cpp(23): error C2143: syntax error : missing ';' before ','
1>c1xx : fatal error C1063: INTERNAL COMPILER ERROR
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1>cl : Command line warning D9028: minimal rebuild failure, reverting to normal build
1>
1>Build FAILED.

C++ pointer-to-method template deduction doesn't compile when targeting x86, but works with x64

I've got this sample code:
struct A
{
int foo() { return 27; }
};
template<typename T>
struct Gobstopper
{
};
template<>
struct Gobstopper<int(void)>
{
Gobstopper(int, int) { } // To differentiate from general Gobstopper template
};
template<typename ClassType, typename Signature>
void DeduceMethodSignature(Signature ClassType::* method, ClassType& instance)
{
// If Signature is int(), Gobstopper<> should resolve to the specialized one.
// But it only does on x64!
Gobstopper<Signature>(1, 2);
}
int main(int argc, char** argv)
{
A a;
DeduceMethodSignature(&A::foo, a);
return 0;
}
This compiles fine with g++. It also compiles fine with VC10, but only when building for the 64-bit platform. When I build for the 32-bit platform, I get this compile error:
error C2661: 'Gobstopper<T>::Gobstopper' : no overloaded function takes 2 arguments
1> with
1> [
1> T=int (void)
1> ]
1> c:\...\test.cpp(26) : see reference to function template instantiation 'void DeduceMethodSignature<A,int(void)>(Signature (__thiscall A::* ),ClassType &)' being compiled
1> with
1> [
1> Signature=int (void),
1> ClassType=A
1> ]
The error indicates that the non-specialized version of Gobstopper is being used, which must mean the Signature is something other that int (void). But the error also clearly says that Signature is int (void). So where does the error come from? And how can I fix it?
The only thing I can think of that might change from 32-bit to 64-bit and not show up in the signature displayed in the error message is the calling convention; apparently, there is a unified calling convention for VC x64, whereas for x86 each calling convention is distinct. But even if that's the problem, I have no idea how to fix it.
Edit: I should mention that I tried this with regular (non-member) function pointers, and that worked fine.
You are quite correct.
The type of Signature with a Win32 target is int __thiscall(void) while on x64 it is int __cdecl(void). Note that on either target the type of non-member functions commonly called int(void) is indeed int __cdecl(void) so, by coincidence one of the constructed types actually (not really correctly!) matches.
In general it is not advisable to mix the different types of function pointers by template magic, so the Gobstopper specialization should look at something like int (ClassType::*)() instead.

Cannot seem to come up with right parameter for _set_se_translator

I am trying to implement _set_se_translator. I tried to write a function with the following signature (from my .cpp file - of course, I have a similar signature in my .h file):
void CIntersonBScan::trans_func(unsigned int u, EXCEPTION_POINTERS* pExp)
I then pass this function as a parameter to _set_se_translator by writing the following code:
_set_se_translator(&CIntersonBScan::trans_func);
I then compile my code and get the following error message:
error C2664: '_set_se_translator': cannot convert parameter 1 from 'void(__thiscall CIntersonBScan::*)(unsigned int,EXCEPTION_POINTERS *)' to '_se_translator_function'
In the eh.h file, I found the following definition for _se_translator_function:
typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS*);
I tried varying the signature of trans_func and still got the same error message. I already set the /EHa compile option. How to I create a function that would actually match the signature of _se_translator_function?
typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS*);
This must be a free function, or a static member function - it cannot be a non-static member function (because these have a hidden implicit this parameter - and cannot match _se_translator_function).
It needs to be a free standing function, not a member function. That is why the types don't match.