mirror of git://gcc.gnu.org/git/gcc.git
![]() The P2843R3 Preprocessing is never undefined paper contains comments that various compilers handle comma operators in preprocessor expressions incorrectly and I think they are right. In both C and C++ the grammar uses constant-expression non-terminal for #if/#elif and in both C and C++ that NT is conditional-expression, so #if 1, 2 is IMHO clearly wrong in both languages. C89 then says for constant-expression "Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within the operand of a sizeof operator." Because all the remaining identifiers in the #if/#elif expression are replaced with 0 I think assignments, increment, decrement and function-call aren't that big deal because (0 = 1) or ++4 etc. are all invalid, but for comma expressions I think it matters. In r0-56429 PR456 Joseph has added !CPP_OPTION (pfile, c99) to handle that correctly. Then C99 changed that to: "Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated." That made for C99+ #if 1 || (1, 2) etc. valid but #if (1, 2) is still invalid, ditto #if 1 ? 1, 2 : 3 In C++ I can't find anything like that though, and as can be seen on say int a[(1, 2)]; int b[1 ? 1, 2 : 3]; being accepted by C++ and rejected by C while int c[1, 2]; int d[1 ? 2 : 3, 4]; being rejected in both C and C++, so I think for C++ it is indeed just the grammar that prevents #if 1, 2. When it is the second operand of ?: or inside of () the grammar just uses expression and that allows comma operator. So, the following patch uses different decisions for C++ when to diagnose comma operator in preprocessor expressions, for C++ tracks if it is inside of () (obviously () around #embed clauses don't count unless one uses limit ((1, 2)) etc.) or inside of the second ?: operand and allows comma operator there and disallows elsewhere. BTW, I wonder if anything in the standard disallows <=> in the preprocessor expressions. Say #if (0 <=> 1) < 0 etc. #include <compare> constexpr int a = (0 <=> 1) < 0; is valid (but not valid without #include <compare>) and the expressions don't use any identifiers. 2025-07-30 Jakub Jelinek <jakub@redhat.com> PR c++/120778 * internal.h (struct lexer_state): Add comma_ok member. * expr.cc (_cpp_parse_expr): Initialize it to 0, increment on CPP_OPEN_PAREN and CPP_QUERY, decrement on CPP_CLOSE_PAREN and CPP_COLON. (num_binary_op): For C++ pedwarn on comma operator if pfile->state.comma_ok is 0 instead of !c99 or skip_eval. * g++.dg/cpp/if-comma-1.C: New test. |
||
---|---|---|
.forgejo | ||
.github | ||
INSTALL | ||
c++tools | ||
config | ||
contrib | ||
fixincludes | ||
gcc | ||
gnattools | ||
gotools | ||
include | ||
libada | ||
libatomic | ||
libbacktrace | ||
libcc1 | ||
libcody | ||
libcpp | ||
libdecnumber | ||
libffi | ||
libgcc | ||
libgcobol | ||
libgfortran | ||
libgm2 | ||
libgo | ||
libgomp | ||
libgrust | ||
libiberty | ||
libitm | ||
libobjc | ||
libphobos | ||
libquadmath | ||
libsanitizer | ||
libssp | ||
libstdc++-v3 | ||
libvtv | ||
lto-plugin | ||
maintainer-scripts | ||
zlib | ||
.b4-config | ||
.dir-locals.el | ||
.gitattributes | ||
.gitignore | ||
ABOUT-NLS | ||
COPYING | ||
COPYING.LIB | ||
COPYING.RUNTIME | ||
COPYING3 | ||
COPYING3.LIB | ||
ChangeLog | ||
ChangeLog.jit | ||
ChangeLog.tree-ssa | ||
MAINTAINERS | ||
Makefile.def | ||
Makefile.in | ||
Makefile.tpl | ||
README | ||
SECURITY.txt | ||
ar-lib | ||
compile | ||
config-ml.in | ||
config.guess | ||
config.rpath | ||
config.sub | ||
configure | ||
configure.ac | ||
depcomp | ||
install-sh | ||
libtool-ldflags | ||
libtool.m4 | ||
ltgcc.m4 | ||
ltmain.sh | ||
ltoptions.m4 | ||
ltsugar.m4 | ||
ltversion.m4 | ||
lt~obsolete.m4 | ||
missing | ||
mkdep | ||
mkinstalldirs | ||
move-if-change | ||
multilib.am | ||
symlink-tree | ||
test-driver | ||
ylwrap |
README
This directory contains the GNU Compiler Collection (GCC). The GNU Compiler Collection is free software. See the files whose names start with COPYING for copying permission. The manuals, and some of the runtime libraries, are under different terms; see the individual source files for details. The directory INSTALL contains copies of the installation information as HTML and plain text. The source of this information is gcc/doc/install.texi. The installation information includes details of what is included in the GCC sources and what files GCC installs. See the file gcc/doc/gcc.texi (together with other files that it includes) for usage and porting information. An online readable version of the manual is in the files gcc/doc/gcc.info*. See http://gcc.gnu.org/bugs/ for how to report bugs usefully. Copyright years on GCC source files may be listed using range notation, e.g., 1987-2012, indicating that every year in the range, inclusive, is a copyrightable year that could otherwise be listed individually.