aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-08-07 08:52:38 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-08-07 08:52:38 +0200
commit3b66a2a7890f2ae27ad4c1e1ac62b6551a2ffbae (patch)
tree62691ecd2c6dd38ff5732fa1cc649afaa39a64c7 /gcc
parent2c5bd8e9fb16584cdd1d090b9a5a63dd9140b61b (diff)
downloadgcc-3b66a2a7890f2ae27ad4c1e1ac62b6551a2ffbae.zip
gcc-3b66a2a7890f2ae27ad4c1e1ac62b6551a2ffbae.tar.gz
gcc-3b66a2a7890f2ae27ad4c1e1ac62b6551a2ffbae.tar.bz2
c++: Add testcase for CWG2575 [PR120778]
From the paper it isn't clear what caused the decision changes, not to drop the "the token defined is generated as a result of this replacement process or" part and make [cpp.cond]/10 violations IFNDR rather than ill-formed (the latter maybe so that the extension to handle e.g. !A(A) below etc. can be accepted). Anyway, because that case hasn't been dropped and we pedwarn on it already, and diagnose everything else the way it should, the following patch just adds testcase for it. 2025-08-07 Jakub Jelinek <jakub@redhat.com> PR preprocessor/120778 * g++.dg/DRs/dr2575.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2575.C51
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/DRs/dr2575.C b/gcc/testsuite/g++.dg/DRs/dr2575.C
new file mode 100644
index 0000000..f350282
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2575.C
@@ -0,0 +1,51 @@
+// DR 2575 - Undefined behavior when macro-replacing "defined" operator
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A defined
+#if !A(A) // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if A(B) // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if !A A // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if A B // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if defined A + B
+#else
+#error
+#endif
+#if defined +B // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined 1 // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined (A + B) // { dg-error "missing '\\\)' after 'defined'" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (+B) // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (1) // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing '\\\(' in expression" "" { target *-*-* } .-1 }
+#if defined () // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined A, B // { dg-error "comma operator in operand of #if" }
+#endif
+#if defined (A), B // { dg-error "comma operator in operand of #if" }
+#endif
+#if (defined A), B // { dg-error "comma operator in operand of #if" }
+#endif
+#if defined (A, B) // { dg-error "missing '\\\)' after 'defined'" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (A) + B
+#else
+#error
+#endif
+#if (defined A) + B
+#else
+#error
+#endif