Visual C++ : Defect report or not?

U

user923005

I seem to recall that if a macro is evaluated and the macro is
defined, but a value for the macro does not exist, it should be
evaluated as zero, but I can't find it in the standard. There is a
program called Hoichess, that has the following include file:

#define EXPTOSTRING1(x) #x
#define EXPTOSTRING(x) EXPTOSTRING1(x)
#ifdef DEFAULT_HASHSIZE
std::cout << "\tDEFAULT_HASHSIZE " << EXPTOSTRING(DEFAULT_HASHSIZE)
<< "\n";
#endif
#ifdef DEFAULT_PAWNHASHSIZE
std::cout << "\tDEFAULT_PAWNHASHSIZE " <<
EXPTOSTRING(DEFAULT_PAWNHASHSIZE) << "\n";
#endif
#ifdef DEFAULT_EVALCACHESIZE
std::cout << "\tDEFAULT_EVALCACHESIZE " <<
EXPTOSTRING(DEFAULT_EVALCACHESIZE) << "\n";
#endif
#ifdef DEFAULT_BOOK
std::cout << "\tDEFAULT_BOOK " << EXPTOSTRING(DEFAULT_BOOK) << "\n";
#endif
#ifdef USE_UNMAKE_MOVE
std::cout << "\tUSE_UNMAKE_MOVE " << EXPTOSTRING(USE_UNMAKE_MOVE) <<
"\n";
#endif
#ifdef USE_IID
std::cout << "\tUSE_IID " << EXPTOSTRING(USE_IID) << "\n";
#endif
#ifdef USE_PVS
std::cout << "\tUSE_PVS " << EXPTOSTRING(USE_PVS) << "\n";
#endif
#ifdef USE_HISTORY
std::cout << "\tUSE_HISTORY " << EXPTOSTRING(USE_HISTORY) << "\n";
#endif
#ifdef USE_KILLER
std::cout << "\tUSE_KILLER " << EXPTOSTRING(USE_KILLER) << "\n";
#endif
#ifdef USE_NULLMOVE
std::cout << "\tUSE_NULLMOVE " << EXPTOSTRING(USE_NULLMOVE) << "\n";
#endif
#ifdef USE_FUTILITYPRUNING
std::cout << "\tUSE_FUTILITYPRUNING " <<
EXPTOSTRING(USE_FUTILITYPRUNING) << "\n";
#endif
#ifdef USE_EXTENDED_FUTILITYPRUNING
std::cout << "\tUSE_EXTENDED_FUTILITYPRUNING " <<
EXPTOSTRING(USE_EXTENDED_FUTILITYPRUNING) << "\n";
#endif
#ifdef USE_RAZORING
std::cout << "\tUSE_RAZORING " << EXPTOSTRING(USE_RAZORING) << "\n";
#endif
#ifdef USE_EVALCACHE
std::cout << "\tUSE_EVALCACHE " << EXPTOSTRING(USE_EVALCACHE) <<
"\n";
#endif
#ifdef EXTEND_IN_CHECK
std::cout << "\tEXTEND_IN_CHECK " << EXPTOSTRING(EXTEND_IN_CHECK) <<
"\n";
#endif
#ifdef EXTEND_RECAPTURE
std::cout << "\tEXTEND_RECAPTURE " << EXPTOSTRING(EXTEND_RECAPTURE)
<< "\n";
#endif
#ifdef MAXDEPTH
std::cout << "\tMAXDEPTH " << EXPTOSTRING(MAXDEPTH) << "\n";
#endif
#ifdef MAXPLY
std::cout << "\tMAXPLY " << EXPTOSTRING(MAXPLY) << "\n";
#endif
#ifdef MOVELIST_MAXSIZE
std::cout << "\tMOVELIST_MAXSIZE " << EXPTOSTRING(MOVELIST_MAXSIZE)
<< "\n";
#endif
#ifdef COLLECT_STATISTICS
std::cout << "\tCOLLECT_STATISTICS " <<
EXPTOSTRING(COLLECT_STATISTICS) << "\n";
#endif
#ifdef STATS_MOVELIST
std::cout << "\tSTATS_MOVELIST " << EXPTOSTRING(STATS_MOVELIST) <<
"\n";
#endif
#undef EXPTOSTRING
#undef EXPTOSTRING1

There is another header file that contains this:
/* $Id: config.h 1452 2007-10-30 16:11:59Z holger $
*
* HoiChess/config.h
*
* Copyright (C) 2004, 2005 Holger Ruckdeschel <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef CONFIG_H
#define CONFIG_H

/* Default size of main hash table */
#define DEFAULT_HASHSIZE "32M"

/* Default size of pawn hash table */
#define DEFAULT_PAWNHASHSIZE "4M"

/* Default size of evaluation cache */
#define DEFAULT_EVALCACHESIZE "4M"

/* Default location of opening book */
#define DEFAULT_BOOK "book.dat"

/* Use a single board in search tree, in connection with
Board::unmake_move().
* Otherwise, the board will be copied from node to node each time a
move is
* made. */
//#define USE_UNMAKE_MOVE

/* Use internal iterative deepening */
#define USE_IID

/* Use principal variation search */
#define USE_PVS

/* Use history table */
#define USE_HISTORY

/* Use killer heuristic */
#define USE_KILLER

/* Use null-move pruning */
#define USE_NULLMOVE

/* Use futility pruning */
#define USE_FUTILITYPRUNING

/* Use extended futility pruning */
#define USE_EXTENDED_FUTILITYPRUNING

/* Use razoring */
//#define USE_RAZORING

/* Use evaluation cache */
#define USE_EVALCACHE

/* Search extensions */
#define EXTEND_IN_CHECK
#define EXTEND_RECAPTURE

/* Maximum depth for full-width search */
#define MAXDEPTH 900

/* Maximum search tree depth (full-width + quiescence search) */
#define MAXPLY 1024

/* Maximum size of a Movelist */
#define MOVELIST_MAXSIZE 256

/* Collect statistics, e.g. hash table hits, cutoffs during search,
etc. */
#define COLLECT_STATISTICS

/* Collect statistics about maximum number of moves stored in a
movelist
* (expensive!) */
//#define STATS_MOVELIST

#endif // CONFIG_H


My Visual C++ compiler gives an error for any macro that does not have
a value defined such as:
#define USE_IID

Here is the list of errors coughed up:
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(19) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(19) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(22) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(22) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(25) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(25) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(28) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(28) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(31) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(31) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(34) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(34) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(37) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(37) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(43) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(43) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(46) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(46) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(49) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(49) :
error C2059: syntax error : '<<'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(61) :
warning C4003: not enough actual parameters for macro 'EXPTOSTRING1'
e:\pgn\winboard-engines\hoichess-0.10.2\src\debug_printconfig.h(61) :
error C2059: syntax error : '<<'
eval.cc

So my question is, is the compiler right to throw the errors, or am I
remembering how macros are supposed to operate incorrectly. Chapter
and verse from the current standard would be greatly appreciated.

P.S.
Works fine with GCC, but of course a compiler does not make the rules
-- even though it can extend them.
 
G

Guest

Version of g++ used to compile the above code and version of vc++ used
to compile the above code

I think that Jack Klein was referring to the fact that you removed all
the context from your reply, so anyone who had not read the OP would not
know what code worked fine in gcc. This problem is also demonstrated by
your reply in which you refers to "the above code" when there is no code
in your message.
 
J

James Kanze

I seem to recall that if a macro is evaluated and the macro is
defined, but a value for the macro does not exist, it should be
evaluated as zero, but I can't find it in the standard.

If a macro is defined, it expands to its definition. Always.
If a macro is defined, it has a value (which may be the empty
string).
There is a program called Hoichess, that has the following
include file:

I'm certainly not going to waste my time trying to figure out
all that. Distill it to a small example, and I'll see.
However:
#define EXPTOSTRING1(x) #x
#define EXPTOSTRING(x) EXPTOSTRING1(x)

[...]
#ifdef USE_IID
std::cout << "\tUSE_IID " << EXPTOSTRING(USE_IID) << "\n";
#endif [...]
My Visual C++ compiler gives an error for any macro that does
not have a value defined such as:
#define USE_IID

You mean, if the macro has the value of the empty string.

It's an interesting question, but I think VC++ is correct here.
According to §16.3.4, "After all parameters in the replacement
list have been substituted, the resulting preprocessor token
sequence is rescanned with all subsequent preprocessing tokens
of the source file for more macro names to replace." After all
parameters in the replacement list have been substituted,
the macro EXPTOSTRING(USE_IID) becomes EXPTOSTRING1(), it is
this which is then scanned for further macros. And you have a
function style macro which requires one argument, but has none,
which is an error. (There are special contexts where the
replacement of an argument doesn't occur. But this isn't one of
them; if it were, then the results would be "USE_IID", and not
some value.)

With regards to the evaluation to zero, I think you're confusing
this with the behavior in an #if. In that case, if a macro
isn't defined (not if it is defined to be empty), it is replaced
by zero. (More correctly, in an #if or and #elif, after all
macro expansion and evaluation of the defined operator, any
remaining keywords or symbols, except true and false, are
converted into the token 0, before the expression is evaluated.)
 
D

Dann Corbit

andreyvul said:
g++ version?
vc++ version?

It is irrelevant to the question (about how the standard is to be
interpreted concering macros), which James Kanze answered in full.

But for your edification:

$ gcc --version
gcc.exe (GCC) 4.0.1 20050608 (prerelease)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Microsoft Visual Studio 2005
Version 8.0.50727.762 (SP.050727-7600)
Microsoft .NET Framework
Version 2.0.50727

Installed Edition: Enterprise

Microsoft Visual C++ 2005 77642-113-3000004-41589
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top