weidai11 / cryptopp

free C++ class library of cryptographic schemes
https://cryptopp.com
Other
4.86k stars 1.51k forks source link

Crypto++ 8.2 and misc.h:94:32: error: missing binary operator before token "0" #864

Closed chenyuan-liu closed 5 years ago

chenyuan-liu commented 5 years ago

I compile Crypto++ library source code in CentOS 6, run Linux command to get OS info and version:

#uname -a
Linux centos6 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

[SNIP unneeded by JW]

#make
g++ -I/usr/local/mysql/include -I/usr/local/include/cryptopp -Wall -O0 -fPIC -st
d=c++0x -c ArbiInst.cpp ArbiProduct.cpp ArbiStatus.cpp ArbiTemplate.cpp Broker.c
pp Common.cpp conf.cpp CtpMdBase.cpp CtpMdRecvIF.cpp CtpTdBase.cpp CtpTd.cpp DbI
f.cpp Exchange.cpp GridOrder.cpp GridOrderMgr.cpp Instrument.cpp IpAddr.cpp Isp.
cpp main.cpp Model.cpp OrderInfo.cpp OrderLeg.cpp OrderLegItem.cpp Position.cpp
Product.cpp Seat.cpp SimNow.cpp SocketAgent.cpp Socket.cpp stdafx.cpp StrategyBa
se.cpp Strategy.cpp Timer.cpp times.cpp TradingDetail.cpp TradingLog.cpp Trading
Time.cpp TradingTimeType.cpp User.cpp UserStatus.cpp
In file included from /usr/local/include/cryptopp/seckey.h:11,
                 from /usr/local/include/cryptopp/rijndael.h:13,
                 from /usr/local/include/cryptopp/aes.h:13,
                 from /usr/local/include/cryptopp/dll.h:16,
                 from Socket.cpp:45:
/usr/local/include/cryptopp/misc.h:94:32: error: missing binary operator before token "0"
make: *** [*.o] Error 1

I tried to change /usr/local/include/cryptopp/misc.h:94 from:

#elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)
#define SIZE_MAX SIZE_T_MAX

to:

#elif defined(SIZE_T_MAX)
    #if (SIZE_T_MAX > 0)
        #define SIZE_MAX SIZE_T_MAX
    #endif

but it didn't work, compiler report another error.

noloader commented 5 years ago
> In file included from /usr/local/include/cryptopp/seckey.h:11,
> from /usr/local/include/cryptopp/rijndael.h:13,
> from /usr/local/include/cryptopp/aes.h:13,
> from /usr/local/include/cryptopp/dll.h:16,
> from Socket.cpp:45:
> /usr/local/include/cryptopp/misc.h:94:32: error: missing binary operator before token "0"
> make: *** [*.o] Error 1

This is kind of weird. Here is misc.h : 94 from Crypto++ 8.2:

#ifndef SIZE_MAX
# if defined(__SIZE_MAX__) && (__SIZE_MAX__ > 0)
#  define SIZE_MAX __SIZE_MAX__
# elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)    <= Problem here
#  define SIZE_MAX SIZE_T_MAX
# elif defined(__SIZE_TYPE__)
#  define SIZE_MAX (~(__SIZE_TYPE__)0)
# else
#  define SIZE_MAX ((std::numeric_limits<size_t>::max)())
# endif
#endif

I can't duplicate it on my CentOS 6 virtual machine. On my CentOS 6 machine SIZE_MAX is defined to:

#define SIZE_MAX (~(__SIZE_TYPE__)0)

In fact, I can't duplicate it by undefining SIZE_MAX:

#undef SIZE_MAX
#ifndef SIZE_MAX
# if defined(__SIZE_MAX__) && (__SIZE_MAX__ > 0)
#  define SIZE_MAX __SIZE_MAX__
...
#endif

My guess is - and it is purely a guess - your project is defining SIZE_T_MAX to something.

You might be able to see what SIZE_T_MAX is being defined to with:

g++ -dM -E -std=c++0x ArbiInst.cpp ArbiProduct.cpp ArbiStatus.cpp ArbiTemplate.c
pp Broker.cpp Common.cpp conf.cpp CtpMdBase.cpp CtpMdRecvIF.cpp CtpTdBase.cpp Ct
pTd.cpp DbIf.cpp Exchange.cpp GridOrder.cpp GridOrderMgr.cpp Instrument.cpp IpAd
dr.cpp Isp.cpp main.cpp Model.cpp OrderInfo.cpp OrderLeg.cpp OrderLegItem.cpp Po
sition.cppProduct.cpp Seat.cpp SimNow.cpp SocketAgent.cpp Socket.cpp stdafx.cpp
StrategyBase.cpp Strategy.cpp Timer.cpp times.cpp TradingDetail.cpp TradingLog.c
pp TradingTime.cpp TradingTimeType.cpp User.cpp UserStatus.cpp | grep SIZE_T_MAX

I tried to edit /usr/local/include/cryptopp/misc.h:94 from: ...

Try changing this:

#elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)
#define SIZE_MAX SIZE_T_MAX

To:

#elif defined(SIZE_T_MAX) && ((SIZE_T_MAX) > 0)
#define SIZE_MAX SIZE_T_MAX

Or:

#elif defined(SIZE_T_MAX) && ((SIZE_T_MAX)+0 > 0)
#define SIZE_MAX SIZE_T_MAX

Or, find what is undefining SIZE_MAX and defining SIZE_T_MAX in your headers. Maybe #undef SIZE_T_MAX before including Crypto++ headers.

chenyuan-liu commented 5 years ago

I found where defined SIZE_T_MAX and what SIZE_T_MAX was defined to. My project compile with Crypto++ 8.2 lib and mysql connector lib at the same time, SIZE_T_MAX is defined by mysql connector header file /usr/local/mysql/include/my_global.h:

408 #ifndef SIZE_T_MAX
409 #define SIZE_T_MAX      (~((size_t) 0))
410 #endif
411 

fixed this by #undef it in my project source file:

#define CRYPTOPP_DEFAULT_NO_DLL
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1

#undef SIZE_T_MAX    //<== here undef

#include "dll.h"
#include "aes.h"

#define SIZE_T_MAX      (~((size_t) 0)) //<== here define again

#include <iostream>
#include <sstream>
#include <locale>
#include <ctime>

Thanks

noloader commented 5 years ago

That is weird. Did MySQL #undef SIZE_MAX? How did it get into that code path?

Remember, this is how Crypto++ guards it:

#ifndef SIZE_MAX
# if defined(__SIZE_MAX__) && (__SIZE_MAX__ > 0)
#  define SIZE_MAX __SIZE_MAX__
# elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)    <= Problem here
#  define SIZE_MAX SIZE_T_MAX
# elif defined(__SIZE_TYPE__)
#  define SIZE_MAX (~(__SIZE_TYPE__)0)
# else
#  define SIZE_MAX ((std::numeric_limits<size_t>::max)())
# endif
#endif
noloader commented 5 years ago

OK, I can duplicate it with:

$ cat test.cxx
#include <mysql/my_global.h>

#undef SIZE_MAX
#undef __SIZE_MAX__
#undef SIZE_T_MAX

#define SIZE_T_MAX      (~((size_t) 0))

#ifndef SIZE_MAX
# if defined(__SIZE_MAX__) && (__SIZE_MAX__ > 0)
#  define SIZE_MAX __SIZE_MAX__
# elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)
#  define SIZE_MAX SIZE_T_MAX
# elif defined(__SIZE_TYPE__)
#  define SIZE_MAX (~(__SIZE_TYPE__)0)
# else
#  define SIZE_MAX ((std::numeric_limits<size_t>::max)())
# endif
#endif

int main(int argc, char* argv[])
{
    return 0;
}

And:

$ g++ test.cxx -o test.exe
In file included from test.cxx:1:
/usr/include/mysql/my_global.h:3:2: warning: #warning This file should not be included by clients, include only <mysql.h> [-Wcpp]
    3 | #warning This file should not be included by clients, include only <mysql.h>
      |  ^~~~~~~
test.cxx:7:37: error: missing binary operator before token "0"
    7 | #define SIZE_T_MAX      (~((size_t) 0))
      |                                     ^
test.cxx:12:32: note: in expansion of macro ‘SIZE_T_MAX’
   12 | # elif defined(SIZE_T_MAX) && (SIZE_T_MAX > 0)
      |                                ^~~~~~~~~~
noloader commented 5 years ago

@chenyuan-liu,

After thinking about it... we need to clear that error. It seems we were just getting lucky in the past. It worked by design in the past because some of these macros, like SIZE_T_MAX, was defined like 4294967296UL or 18446744073709552000ULL. In fact when I tested it, those were the types of values that were used by distros. But this report shows how fragile it was.

We removed the part of the test that did SIZE_T_MAX > 0. I added a compile test in cryptlib.cpp to ensure SIZE_MAX > 0 holds. It does not always hold on some rare systems. I ran across one several years ago. The *_MAX define was used to indicate a typedef existed.

Also see Commit e8b07b162feb.

chenyuan-liu commented 5 years ago

I searched in all header files my project included: project self header files, mysql connector header file, there isn't any #undef SIZE_MAX, even the word SIZE_MAX in my project source files. I changed my_golbal.h:409 #define SIZE_T_MAX to:

#define SIZE_T_MAX      ((size_t)(~((size_t) 0)))

compiler report new error:

/usr/local/include/cryptopp/misc.h:94:32: error: missing binary operator before token "("

I tried to fix the error of my project a few days, first time I search in google, many people report similar error is:

error: missing binary operator before token "("

similar error is reported by other different projects. I guess, maybe it's relative to gcc compiler version or not.

noloader commented 5 years ago

@chenyuan-liu ,

I guess, maybe it's relative to gcc compiler version or not.

No, its the lame preprocessor. The preprocessor mostly sucks at doing anything useful. See What does the compiler error “missing binary operator before token” mean? on Stack Overflow.