Repository navigation
Conversation
…to false)
Report "invalid expression" when the #if expression can not be folded to a
single number. This also covers a missing operator ("1 2") and empty
parentheses ("()").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dmcppcheck
left a comment
There was a problem hiding this comment.
AI review
The new throw makes some valid #if expressions fatal. When evaluate() throws, simplecpp::preprocess clears the whole output and returns. So any valid expression that constFold() can't reduce to one number now loses the whole file, where before that condition was only treated as false.
- Comma operator (regression):
constFold()has no case for the comma operator.#if (1, 0)used to give the same result as gcc and clang (false). Now it's a syntax error and the file isn't preprocessed. gcc gives only a-Wpedanticwarning, and clang accepts the parenthesized form.#if 1 ? (2, 3) : 4was silently false before (wrong) and is now a fatal error. not/complafter a binary operator (C++):isAlternativeUnaryOp()only acceptsnot/complat the start of the expression or right after(. So#if 1 && not 0and#if 1 and not Xused to be silently false (also wrong) and now abort the file. g++ and clang++ both give true.
Both are evaluator gaps that the old return 0 hid. Before this check makes them fatal, the comma operator should be supported in constFold() and the alternative unary operators recognised after any operator. The other cases I tried came out the same as in base: the PR's own error cases and about 50 valid expressions (ternaries, unary operators, defined, __has_include, character literals, alternative tokens at the start). Apart from the two problems above, I found no new problems. Nobody has commented on the PR yet.
Testing
Build and test suites: make -j8 testrunner simplecpp CXXOPTS=-Werror built in pr/ without warnings. ./testrunner, python3 run-tests.py (0 failed), python3 -m pytest integration_test.py (128 passed) and ./selfcheck.sh all passed. I also built base/simplecpp to compare against.
Reproducing the comma regression:
// scratch/t2.c
#if (1, 0)
YES
#else
NO
#endif$ gcc -E -P t2.c -> NO (only a -Wpedantic warning about the comma)
$ clang -E -P t2.c -> NO
$ base/simplecpp t2.c -> NO
$ pr/simplecpp t2.c -> t2.c:1: syntax error: failed to evaluate #if condition, invalid expression
For #if 1 ? (2, 3) : 4, gcc and clang give YES, base gave NO, and the PR gives the same syntax error. For #if 1, 2, gcc gives YES (clang rejects it), and the PR gives the error.
Reproducing the not/compl problem (C++):
// scratch/a.cpp
#if 1 && not 0
YES
#else
NO
#endif$ g++ -E -P a.cpp -> YES
$ base/simplecpp a.cpp -> NO
$ pr/simplecpp a.cpp -> a.cpp:1: syntax error: failed to evaluate #if condition, invalid expression
1 and not 0, 1 or not 0, 1 and compl 0 and 1 bitand compl 0 fail the same way. not 0 and 1 and 1 and (not 0) work.
Other expressions tried: about 50 more expressions, compared with gcc. Ternaries, unary operators, defined, __has_include, character literals, true, __LINE__ and others give the same result as base. I also checked that #elif after a branch that was already taken isn't evaluated, so invalid expressions there don't raise the new error.
Automated review of 7fad448 by Claude. The pull request was built and tested locally.
Report "invalid expression" when the #if expression can not be folded to a single number. This also covers a missing operator ("1 2") and empty parentheses ("()").