I want to declare a debug flag is on or off in these both ways:
#define inDebugMode true
or
const bool inDebugMode = true;
The compiler in Visual Studio 2010 always gives a warning:
warning C4127: conditional expression is constant
Why is that? How can I declare it correctly?
Without seeing the code, I suspect you have the following construct:
if (inDebugMode)
{
}
which will always be true, hence the warning.
Recommend using the preprocessor instead of if:
#define inDebugMode 1
#if inDebugMode
#endif
This will remove the warning and prevent the debugging code being compiled when unrequired. Note you can also specify the value of a macro via the compiler switch /D:
cl.exe /DinDebugMode=1 ...
but you need to ensure you rebuild all sources if you choose the command line option, not just the changed sources.
This warning is not for the definition but for the use of it.
lets say you write in your code something like:
if (inDebugMode)
{
//your code
}
when the compiler encounter it (after the precompile in case of the define) this is always true and there it thinks the "if" is not needed. that's way it's only a warning not a error.
in order to avoid it you can do like that:
#define inDebugMode 1
//some code
#if inDebugMode
//your code you only want to run in debug
#endif
this way if you not in debug all the code in the "#if" section will be omitted by the precompiler and the compiler wouldn't have a problem.
If you don't like preprocessor directives and would like to use the const bool, then you may disable "warning C4127" directly (Project Properties / C/C++ / Advanced / Disable Specific Warnings / type "4127").
Related
I use CLion to write C++ programs. One file has
#ifdef USE_BAKER_READ_BARRIER
static constexpr bool kUseBakerReadBarrier = true;
#else
static constexpr bool kUseBakerReadBarrier = false;
#endif
and other files use kUseBakerReadBarrier.
CLion always complains about the usage of kUseBakerReadBarrier, saying the condition is always true.
Admittedly, the const is true under the current setting. But I will sometimes compile the project without compiler option -DUSE_BAKER_READ_BARRIER, then the branch of kUseBakerReadBarrier==false kicks in.
These kinds of false warnings add many yellow eyesores to a file and makes it hard for me to spot real warnings.
What's the best way to handle these "false always-true" warnings?
I don't want to suppress all "Simplifiable Statements" warnings, as I would like IDE to warn me like
bool a=true;
if(a)
...
I'm open to know the behavior/solution in other IDE, preferably Visual Studio as well.
Not sure it's doable in general; analyzing exponentially growing amount of conditional compilation of C++ which is already hard, would take an unreasonable amount of programmer's and CPU time.
You can silence a particular line with a #pragma, though. CLion's inspections usually even offer to do it for you as one of the the fixup variants.
We have a pretty large project here in C++/.NET/Visual Studio, for performance testing we incuded some code that makes it possible to evaluate the execution time between certain points.
PERFORMANCE_TEST BeginMeasureTime("execute someCode")
someCode
PERFORMANCE_TEST EndMeasureTime("execute someCode")
Usually while developing the PERFORMANCE_TEST macro would be set to // so the evaluation code is switched off. So if code / interfaces etc. change and the code after the PERFORMANCE_TEST macro becomes invalid, the developer will not notice that.
Is there any smarter way to have the performance evaluation code only built in a special version of the project but still make sure that it stays consistent? How would you normally do something like that?
One easy way would be to change
PERFORMANCE_TEST xxx
to
PERFORMANCE_TEST(xxx)
Then instead of
#if PERFORMANCE_TEST_ENABLED
#define PERFORMANCE_TEST
#else
#define PERFORMANCE_TEST //
#endif
you could have
#if PERFORMANCE_TEST_ENABLED
#define PERFORMANCE_TEST(x) {x;}
#else
#define PERFORMANCE_TEST(x) if(0) { x; }
#endif
An optimizing compiler should generate no code for the second version if performance tests are disabled (or at the very least it'll not branch on the if), but it'll still be part of the compilation.
Alternatively, if build times aren't a huge concern you could simply always build both versions into separate directories.
It's been a while since I did something like this the following should be what you want. If the MACRO is defined then the function is included, else it the function is a noop and compiled out the code.
#ifdef MACRO
#define MACRO_NAME(arg1, arg2, ...) [code to expand to]
#else
#define MACRO_NAME(arg1, arg2, ...) noop
#endif
Update:
Ok so I slightly got the question a bit incorrect.
Most static analysis tools can be configured to scan certain #defines
CPPCheck for example can be given the following arguments.
-D<ID> Define preprocessor symbol. Unless --max-configs or
--force is used, Cppcheck will only check the given
configuration when -D is used.
Example: '-DDEBUG=1 -D__cplusplus'.
So you can then scan the code twice, thus achieving your goal.
I would say this is the best of both before you can add more scans if you add more #define
Or you can use some of the following to scan more configurations.
-f, --force Force checking of all configurations in files. If used
together with '--max-configs=', the last option is the
one that is effective.
and
--max-configs=<limit>
Maximum number of configurations to check in a file
before skipping it. Default is '12'. If used together
with '--force', the last option is the one that is
effective.
We used this type of operation at a previous company, we build code for WIN32, Pocket PC and WM5 and WM6 all from the same code base but had static checking on all build configurations. But the end result was the removal of non redundant code in all builds.
I would like to be able to do something like this using visual c++ compiler (vc12):
// If we have compiled with O2
#ifdef _O2_FLAG_
bool debug_mode = false;
// If we are in dirty slow non optimized land
#else
bool debug_mode = true;
#endif
But I cannot find a predefined macro for this purpose.
Context:
The debug_mode flag is used like:
if (!debug_mode && search_timer->seconds_elapsed() > 20) {
return best_result_so_far;
}
The problem being that in a debug instance that I step through this constantly fails and bombs me out because strangely it takes me a lot longer to step through the code than the CPU normally goes through it :-)
If there is some underlying clock that pauses when debug does that would also solve my problem. Currently I am using the difference between two calls to std::chrono::high_res_clock::now().
EDIT:
In response to several comments explaining why I don't want to do what I want to do, I should perhaps reword the question as simply: Is there an equivalent of gcc's __optimize__ in cl?
You could use either _DEBUG or NDEBUG to detect the debug configuration. This technically doesn't mean the same thing as the optimization flag, but 99% of the time this should suffice.
Another option would be to add a preprocessor definition to the project yourself.
I use the code below for assert in "release", have for some time with no issues ever.
Then along came Visual Studio 2010 Pro SP1, and things went south, as also happened to mr. Krunthar.
Problem is, when I have a piece of code in which I do sanity checks like this:
#define ASSERT(condition, msg) do { (void)sizeof(condition); } while (0,0)
// Note: (0,0) is to avoid warning C4127: conditional expression is constant
{
int result = CallMeOnce(); // its side effects are the important stuff
// perform additional sanity checks in debug
ASSERT(result >= 0, "too low");
ASSERT(result <= 100, "too high");
ASSERT(!isPrime(result), "too prime");
}
VS2010 spits out a warning C4189: 'result' : local variable is initialized but not referenced
I am at a loss on how to fix that:
Code like (void)(condition) will execute any expression passed as condition, which is a no no
Putting CallMeOnce() inside the ASSERT expression is impossible
Refactoring all the different CallMeOnce()s is NOT an option
I'd rather not have to write scaffolding code like (void)result, if (result == result) {} or UNREFERENCED_PARAMETER(result) (or equivalent) outside the macro just to avoid the warning as it makes the code even harder to read (pollution), and is easy to forget while writing code in Debug. Also: in lots of places!
I'm considering creating another macro (ASSERTU?) just for variables, but it feels so... quirky!
Has anyone found a better way out?
Thanks a lot!
Edit: Clarified preference for the variable handling at caller's level
in your assert macro you have
(void)sizeof(condition);
presumably this code was written by someone else, so, explanation:
the rôle of the (void) cast is to tell the compiler that you really intended this do-nothing expression statement to do nothing.
now do the same for your result
that was easy, wasn't it? sometimes solution is just staring you in the face. ;-)
by the way, when this construct is used to suppress warnings about unused formal arguments, you might want to add a redefinition of the name, like
(void) unusedArg; struct unusedArg;
this prevents inadvertently using the argument with later maintenance of the code
however, the error generated by visual c++ is not exactly informative
there are umpteen level of sophistication that can be added, but i think even the name redefinition is perhaps going too far – the cost greater than the advantage, perhaps
You can use the UNREFERENCED_PARAMETER macro.
It seems I got somewhere!
#define ASSERT(condition, msg) \
do { \
if (0,0) { \
(void)(condition); \
} \
} while (0,0)
Mandatory explanation:
(void)(condition); will suppress C4189, but will execute any expression or function call passed in.
However, if (false) {...} will make sure that whatever (valid expression) "..." may be, it will not be executed. Code optimization phase will see it as dead code and throw it away (no code generated at all for the block in my tests!).
Finally, the owl trick (0,0) will prevent C4127, which seems a quite useless warning in the first place but hey, less clutter in the compilation output!
The only weakness I could find to this solution is that condition needs to be compilable code, so if you #ifdef-ed out part of the expression, it will raise an error. It might be that it's also compiling (though not calling) the code for the called functions; more research would be useful.
This is much nicer. Also: an expression instead of a statement
#define ASSERT(condition, msg) ( false ? (void)(condition) : (void)0 )
though you might want both debug and release versions of your assert to have the same semantic, so a do {...} while (0,0) around it might be appropriate.
You can use pairs of __pragma(warning(push)) __pragma(warning(disable: 4127)) and __pragma(warning(pop)) to silence C4127 just for the ASSERT line.
Then (void)(true ? (void)0 : ((void)(expression))) silences C4189.
This is an excerpt from my own implementation of an assertion macro.
The PPK_ASSERT(expression) macro will ultimately expand to PPK_ASSERT_3(level, expression) or PPK_ASSERT_UNUSED(expression) depending on whether assertions are enabled or disabled.
#define PPK_ASSERT_3(level, expression, ...)\
__pragma(warning(push))\
__pragma(warning(disable: 4127))\
do\
{\
static bool _ignore = false;\
if (PPK_ASSERT_LIKELY(expression) || _ignore || pempek::assert::implementation::ignoreAllAsserts());\
else\
{\
if (pempek::assert::implementation::handleAssert(PPK_ASSERT_FILE, PPK_ASSERT_LINE, PPK_ASSERT_FUNCTION, #expression, level, _ignore, __VA_ARGS__) == pempek::assert::implementation::AssertAction::Break)\
PPK_ASSERT_DEBUG_BREAK();\
}\
}\
while (false)\
__pragma(warning(pop))
and
#define PPK_ASSERT_UNUSED(expression) (void)(true ? (void)0 : ((void)(expression)))
I can't find a clear statement on the semantics of Q_ASSERT under release builds. If there is no assertion checking, then is the asserted expression evaluated at all?
Consider the following code
Q_ASSERT(do_something_report_false_if_failed());
Will do_something_report_false_if_failed() run under all potential Qt build configurations? Would it be safer (even though a bit more verbose and less readable) to do this instead:
bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)
The latter approach has the downside that ASSERT failures are less verbose, but perhaps it shows more clearly that the statement is executed?
The expression inside the Q_ASSERT will not be evaluated in non-debug build configurations.
Consider the source code below from the Qt repo.
#if !defined(Q_ASSERT)
# ifndef QT_NO_DEBUG
# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
# else
# define Q_ASSERT(cond) qt_noop()
# endif
#endif
If QT_NO_DEBUG is defined, then the entire Q_ASSERT statement is replaced with a qt_noop(), thereby removing any expression that it previously contained.
Never rely on any side effects created by an expression inside a Q_ASSERT statement. Technically it is still possible to ensure that QT_NO_DEBUG is not defined in a specific build configuration, but this is not a Good Idea™.
This seems to be different in Qt5.5 (but not earlier - see Qt5.4):
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
# define Q_ASSERT(cond) do { } while ((false) && (cond))
# else
# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
# endif
#endif
I'm now getting lots of "warning C4127: conditional expression is constant" in Visual Studio 2013.
Update:
Qt5.5 release notes say:
Q_ASSERT will now expand the condition even in release mode when
asserts are disabled, albeit in an unreachable code path. This
solves compiler warnings about variables and functions that were
unused in release mode because they were only used in assertions.
Unfortunately, codebases that hid those functions and variables
via #ifndef will need to remove the conditionals to compile with Qt 5.5.