Skip to content

Fix #612: reject floating literals in preprocessor conditions - #706

Merged
danmar merged 3 commits into
cppcheck-opensource:masterfrom
Abusalah0:fix-612-floating-preprocessor-literals
Nov 6, 2026
Merged

danmar merged 3 commits into
cppcheck-opensource:masterfrom
Abusalah0:fix-612-floating-preprocessor-literals

Conversation

@Abusalah0

Copy link
Copy Markdown
Contributor

Fixes #612.

preprocessor conditional expressions only permit integral expressions, but simplecpp previously passed floating-point literals into integer constant folding. Integer conversion then consumed their integral prefix, allowing expressions such as A == 1.0 to evaluate successfully.

Detect floating-point spellings before numeric simplification and report a syntax error. This covers decimal-point, decimal exponent, and hexadecimal exponent forms while preserving valid integer literals.

Tests cover:

  • the original A == 1.0 reproducer;
  • .5 in #elif;
  • 1e3;
  • 1.f;
  • 0x1p3;
  • a valid integer comparison.

@danmar

danmar commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

please look at the CI issues..

@Abusalah0

Copy link
Copy Markdown
Contributor Author

sorry i did notice it at first, I pushed the fix, it was one indentation space.

@danmar

danmar commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

I think you will need to rebase from latest master. I made a CI fix with #707

@Abusalah0
Abusalah0 force-pushed the fix-612-floating-preprocessor-literals branch from 748755d to 5a52bc3 Compare October 27, 2026 09:58
@Abusalah0

Copy link
Copy Markdown
Contributor Author

Done

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

One new problem: a floating literal in an #elif that gcc and clang never evaluate now makes simplecpp report an error. simplecpp evaluates #elif conditions even after an earlier branch has been taken. Until now a floating literal there evaluated quietly; with this PR it throws. So

#if 1
ok
#elif 1.0
bad
#endif

now gives syntax error: failed to evaluate #elif condition, floating point literal in preprocessor expression and no output. gcc and clang both print ok with no diagnostic. cppcheck would stop checking a file that compiles fine, for example #if __cplusplus >= 201103L … #elif VERSION >= 1.5.

This comes from existing behaviour: base already does the same for #elif 1/0 after a taken group. But the PR adds a new, more likely way to hit it. It should be fixed (by not evaluating #elif once a branch was taken) or at least covered by a test or a known-issue note before merging.

Otherwise the detection matches gcc/clang on every spelling I tried. That includes 1.0, .5, 1e3, 1E3, 1e+3, 0e0, -1.0, 1.f, 0x1p3, 0X1P3, 0x1.p1, and literals in short-circuited operands (1 || 1.0, 0 ? 1.5 : 1). Hex integers containing e/E (0xE, 0x1e), 1ULL, digit separators, '.', __has_include("a.h")/<a.h> and skipped #if 0 blocks are not affected.

Minor: some invalid integer literals now get the floating-point message, while gcc gives a different one. For 1_e gcc says "invalid suffix", for 012e "exponent has no digits", for 1..2 "too many decimal points". They are errors in both, so it is only the wording. The extra work per token is negligible.

Testing

Build: make -j8 testrunner simplecpp CXXOPTS=-Werror in pr/ built with no warnings. I also built base/.

Test suites: all pass.

  • ./testrunner: exit 0, no failures.
  • python3 run-tests.py: 176 tests, 0 failed, same as base.
  • pytest integration_test.py: 128 passed.
  • ./selfcheck.sh: exit 0.

Edge cases: I ran 25 #if <expr> variants through pr, base and gcc -E. Every floating spelling is now rejected, matching gcc's "floating constant in preprocessor expression". Integer and hex-with-e literals, char literals, digit separators, defined(A) with A defined as 2.0, __has_include with a dotted name, and floats inside skipped #if 0 blocks are unchanged.

Regression found:

printf '#if 1\nok\n#elif 1.0\nbad\n#endif\n' > f.c
/work/pr/simplecpp f.c
# f.c:3: syntax error: failed to evaluate #elif condition, floating point literal in preprocessor expression
/work/base/simplecpp f.c   # ok
gcc -E -P f.c              # ok (no diagnostic)
clang -E -P f.c            # ok (no diagnostic)

Base already behaves like this for #elif 1/0 after a taken group, so the root cause is that simplecpp evaluates #elif after a taken branch. The PR makes it more likely to happen.


Automated review of 5a52bc3 by Claude. The pull request was built and tested locally.

Comment thread simplecpp.cpp Resolved
@danmar
danmar merged commit ca3426a into cppcheck-opensource:master Nov 6, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

do not allow floating point literals in preprocessor checks

3 participants