]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
preprocessor: -Wbidi-chars and UCNs [PR104030]
authorMarek Polacek <polacek@redhat.com>
Thu, 20 Jan 2022 00:05:22 +0000 (19:05 -0500)
committerMarek Polacek <polacek@redhat.com>
Mon, 24 Jan 2022 22:48:23 +0000 (17:48 -0500)
Stephan Bergmann reported that our -Wbidi-chars breaks the build
of LibreOffice because we warn about UCNs even when their usage
is correct: LibreOffice constructs strings piecewise, as in:

  aText = u"\u202D" + aText;

and warning about that is overzealous.  Since no editor (AFAIK)
interprets UCNs to show them as Unicode characters, there's less
risk in misinterpreting them, and so perhaps we shouldn't warn
about them by default.  However, identifiers containing UCNs or
programs generating other programs could still cause confusion,
so I'm keeping the UCN checking.  To turn it on, you just need
to use -Wbidi-chars=unpaired,ucn or -Wbidi-chars=any,ucn.

The implementation is done by using the new EnumSet feature.

PR preprocessor/104030

gcc/c-family/ChangeLog:

* c.opt (Wbidi-chars): Mark as EnumSet.  Also accept =ucn.

gcc/ChangeLog:

* doc/invoke.texi: Update documentation for -Wbidi-chars.

libcpp/ChangeLog:

* include/cpplib.h (enum cpp_bidirectional_level): Add
bidirectional_ucn.  Set values explicitly.
* internal.h (cpp_reader): Adjust warn_bidi_p.
* lex.cc (maybe_warn_bidi_on_close): Don't warn about UCNs
unless UCN checking is on.
(maybe_warn_bidi_on_char): Likewise.

gcc/testsuite/ChangeLog:

* c-c++-common/Wbidi-chars-10.c: Turn on UCN checking.
* c-c++-common/Wbidi-chars-11.c: Likewise.
* c-c++-common/Wbidi-chars-14.c: Likewise.
* c-c++-common/Wbidi-chars-16.c: Likewise.
* c-c++-common/Wbidi-chars-17.c: Likewise.
* c-c++-common/Wbidi-chars-4.c: Likewise.
* c-c++-common/Wbidi-chars-5.c: Likewise.
* c-c++-common/Wbidi-chars-6.c: Likewise.
* c-c++-common/Wbidi-chars-7.c: Likewise.
* c-c++-common/Wbidi-chars-8.c: Likewise.
* c-c++-common/Wbidi-chars-9.c: Likewise.
* c-c++-common/Wbidi-chars-ranges.c: Likewise.
* c-c++-common/Wbidi-chars-18.c: New test.
* c-c++-common/Wbidi-chars-19.c: New test.
* c-c++-common/Wbidi-chars-20.c: New test.
* c-c++-common/Wbidi-chars-21.c: New test.
* c-c++-common/Wbidi-chars-22.c: New test.
* c-c++-common/Wbidi-chars-23.c: New test.

23 files changed:
gcc/c-family/c.opt
gcc/doc/invoke.texi
gcc/testsuite/c-c++-common/Wbidi-chars-10.c
gcc/testsuite/c-c++-common/Wbidi-chars-11.c
gcc/testsuite/c-c++-common/Wbidi-chars-14.c
gcc/testsuite/c-c++-common/Wbidi-chars-16.c
gcc/testsuite/c-c++-common/Wbidi-chars-17.c
gcc/testsuite/c-c++-common/Wbidi-chars-18.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-19.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-20.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-21.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-22.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-23.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/Wbidi-chars-4.c
gcc/testsuite/c-c++-common/Wbidi-chars-5.c
gcc/testsuite/c-c++-common/Wbidi-chars-6.c
gcc/testsuite/c-c++-common/Wbidi-chars-7.c
gcc/testsuite/c-c++-common/Wbidi-chars-8.c
gcc/testsuite/c-c++-common/Wbidi-chars-9.c
gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
libcpp/include/cpplib.h
libcpp/internal.h
libcpp/lex.cc

index db65c14a7a5af99d3652b9fb5b2c86e9e8b53857..9cfd2a6bc4e00a590156ac28fb89256756ed2364 100644 (file)
@@ -379,8 +379,8 @@ C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none)
 ;
 
 Wbidi-chars=
-C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level)
--Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters.
+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) EnumSet
+-Wbidi-chars=[none|unpaired|any|ucn] Warn about UTF-8 bidirectional control characters.
 
 ; Required for these enum values.
 SourceInclude
@@ -390,13 +390,16 @@ Enum
 Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized)
 
 EnumValue
-Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none)
+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) Set(1)
 
 EnumValue
-Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired)
+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) Set(1)
 
 EnumValue
-Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any)
+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) Set(1)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(ucn) Value(bidirectional_ucn) Set(2)
 
 Wbool-compare
 C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
index 309f5e38a8599811aa79ed88ad861d3d71230723..9e588db4fce6f7bcbfda8a98e80910b4cacabf25 100644 (file)
@@ -328,7 +328,7 @@ Objective-C and Objective-C++ Dialects}.
 -Warray-bounds  -Warray-bounds=@var{n}  -Warray-compare @gol
 -Wno-attributes  -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
 -Wno-attribute-warning  @gol
--Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol
+-Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{|}ucn@r{]} @gol
 -Wbool-compare  -Wbool-operation @gol
 -Wno-builtin-declaration-mismatch @gol
 -Wno-builtin-macro-redefined  -Wc90-c99-compat  -Wc99-c11-compat @gol
@@ -7803,7 +7803,7 @@ Attributes considered include @code{alloc_align}, @code{alloc_size},
 This is the default.  You can disable these warnings with either
 @option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}.
 
-@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]}
+@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{|}ucn@r{]}
 @opindex Wbidi-chars=
 @opindex Wbidi-chars
 @opindex Wno-bidi-chars
@@ -7820,6 +7820,10 @@ bidi contexts.  @option{-Wbidi-chars=none} turns the warning off.
 @option{-Wbidi-chars=any} warns about any use of bidirectional control
 characters.
 
+By default, this warning does not warn about UCNs.  It is, however, possible
+to turn on such checking by using @option{-Wbidi-chars=unpaired,ucn} or
+@option{-Wbidi-chars=any,ucn}.
+
 @item -Wbool-compare
 @opindex Wno-bool-compare
 @opindex Wbool-compare
index 3f851b69e658104caddeb027b396b91d1face28c..cdcdce2be089c4c09635d4423da9b3bf3e3fe4e0 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
 /* More nesting testing.  */
 
 /* RLE‫ LRI⁦ PDF‬ PDI⁩*/
index 270ce2368a95f994dc5521b5f0bbf0771826e982..ea83029d6b99718c7851d4ba2cb0178ef7fb9b40 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
 /* Test that we warn when mixing UCN and UTF-8.  */
 
 int LRE_‪_PDF_\u202c;
index ba5f75d9553cfefdd3fc9a1d998cfc75da302b0e..cb6b05efac1bc56af66686bf9809f111ff88bf6a 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
 /* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs,
    or RLOs.  */
 
index baa0159861c099fc0dc0cac34f95f7cdd8150e28..eaf0ec9a77717632f0c8d6e2701c3fb01f0ac1a2 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=any" } */
+/* { dg-options "-Wbidi-chars=any,ucn" } */
 /* Test LTR/RTL chars.  */
 
 /* LTR<‎> */
index 07cb4321f964522f7ac44afec956b20e6928b149..341922146a711bdc9453f4c1af178869cd70b794 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
 /* Test LTR/RTL chars.  */
 
 /* LTR<‎> */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-18.c b/gcc/testsuite/c-c++-common/Wbidi-chars-18.c
new file mode 100644 (file)
index 0000000..ae586d5
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* By default, don't warn about UCNs.  */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+  return aText;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-19.c b/gcc/testsuite/c-c++-common/Wbidi-chars-19.c
new file mode 100644 (file)
index 0000000..9985c3b
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+  return aText;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-20.c b/gcc/testsuite/c-c++-common/Wbidi-chars-20.c
new file mode 100644 (file)
index 0000000..859f3d5
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=any" } */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-bogus "U\\+202D" "" { target *-*-* } .-1 } */
+  return aText;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-21.c b/gcc/testsuite/c-c++-common/Wbidi-chars-21.c
new file mode 100644 (file)
index 0000000..2720b8a
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=ucn,any" } */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+  return aText;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-22.c b/gcc/testsuite/c-c++-common/Wbidi-chars-22.c
new file mode 100644 (file)
index 0000000..f960e59
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=none,ucn" } */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-bogus "" "" { target *-*-* } .-1 } */
+  return aText;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-23.c b/gcc/testsuite/c-c++-common/Wbidi-chars-23.c
new file mode 100644 (file)
index 0000000..7de0a11
--- /dev/null
@@ -0,0 +1,11 @@
+/* PR preprocessor/104030 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=ucn" } */
+
+const char *
+fn ()
+{
+  const char *aText = "\u202D" "abc";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+  return aText;
+}
index 639e5c62e8886515754c2ebf00198f40e526304e..d2f0739dae06bc1a7b5168a03326021b8fe3712a 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */
+/* { dg-options "-Wbidi-chars=any,ucn -Wno-multichar -Wno-overflow" } */
 /* Test all bidi chars in various contexts (identifiers, comments,
    string literals, character constants), both UCN and UTF-8.  The bidi
    chars here are properly terminated, except for the character constants.  */
index 68cb053144ba46a72f30a5252bf3bfdb35ab75fe..ad49498fe234e5bbb5f8e89be0aebb96e1d2eff5 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn -Wno-multichar -Wno-overflow" } */
 /* Test all bidi chars in various contexts (identifiers, comments,
    string literals, character constants), both UCN and UTF-8.  The bidi
    chars here are properly terminated, except for the character constants.  */
index 0ce6fff2deed0643a2191bd2a1f952d38ab4d7c5..8c1c1b2a2705f222a5b1f4fc29642cdf95ef38f7 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=ucn,unpaired" } */
 /* Test nesting of bidi chars in various contexts.  */
 
 /* Terminated by the wrong char:  */
index d012d420ec04fe1755965ddd853d86da3746a84a..3270952a09a45c209834136af74634ab47792c65 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=any" } */
+/* { dg-options "-Wbidi-chars=any,ucn" } */
 /* Test we ignore UCNs in comments.  */
 
 // a b c \u202a 1 2 3
index 4f54c5092eca1296f8953d44bef37f37564d6bad..3983168c9f1e3a08ba88283692b8b0c81c280b66 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=any" } */
+/* { dg-options "-Wbidi-chars=any,ucn" } */
 /* Test \u vs \U.  */
 
 int a_\u202A;
index e2af1b1ca97f77d6048ad044c7b5ef54450ef831..0ddb0d931088c9207e7faa2332473f7dfb157f8d 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn" } */
 /* Test that we properly separate bidi contexts (comment/identifier/character
    constant/string literal).  */
 
index 298750a2a64c881b447552f4b2f72330a2e8dc3b..0c71f306dbc73c5911e25075295ef43c536ecc2c 100644 (file)
@@ -1,6 +1,6 @@
 /* PR preprocessor/103026 */
 /* { dg-do compile } */
-/* { dg-options "-Wbidi-chars=unpaired -fdiagnostics-show-caret" } */
+/* { dg-options "-Wbidi-chars=unpaired,ucn -fdiagnostics-show-caret" } */
 /* Verify that we escape and underline pertinent bidirectional
    control characters when quoting the source.  */
 
index 940c79f98c12ab233b249e3da2fe32b0b72fa137..3eba6f74b5726c13489b11db9807060f4d37daf3 100644 (file)
@@ -319,15 +319,16 @@ enum cpp_main_search
   CMS_system,  /* Search the system INCLUDE path.  */
 };
 
-/* The possible bidirectional control characters checking levels, from least
-   restrictive to most.  */
+/* The possible bidirectional control characters checking levels.  */
 enum cpp_bidirectional_level {
   /* No checking.  */
-  bidirectional_none,
+  bidirectional_none = 0,
   /* Only detect unpaired uses of bidirectional control characters.  */
-  bidirectional_unpaired,
+  bidirectional_unpaired = 1,
   /* Detect any use of bidirectional control characters.  */
-  bidirectional_any
+  bidirectional_any = 2,
+  /* Also warn about UCNs.  */
+  bidirectional_ucn = 4
 };
 
 /* This structure is nested inside struct cpp_reader, and
index 364c41c8149cd9c7544e2b828fcad051fcbc0325..badfd1b40daa54d791105204be5d587a493d8dba 100644 (file)
@@ -605,7 +605,8 @@ struct cpp_reader
      characters.  */
   bool warn_bidi_p () const
   {
-    return CPP_OPTION (this, cpp_warn_bidirectional) != bidirectional_none;
+    return (CPP_OPTION (this, cpp_warn_bidirectional)
+           & (bidirectional_unpaired|bidirectional_any));
   }
 };
 
index 4d736576cc1acf955eb057473270b851ae19c802..fb1dfabb7afef0d52fe4a42703370482e14cb037 100644 (file)
@@ -1560,8 +1560,11 @@ class unpaired_bidi_rich_location : public rich_location
 static void
 maybe_warn_bidi_on_close (cpp_reader *pfile, const uchar *p)
 {
-  if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired
-      && bidi::vec.count () > 0)
+  const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional);
+  if (bidi::vec.count () > 0
+      && (warn_bidi & bidirectional_unpaired
+         && (!bidi::current_ctx_ucn_p ()
+             || (warn_bidi & bidirectional_ucn))))
     {
       const location_t loc
        = linemap_position_for_column (pfile->line_table,
@@ -1597,7 +1600,7 @@ maybe_warn_bidi_on_char (cpp_reader *pfile, bidi::kind kind,
 
   const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional);
 
-  if (warn_bidi != bidirectional_none)
+  if (warn_bidi & (bidirectional_unpaired|bidirectional_any))
     {
       rich_location rich_loc (pfile->line_table, loc);
       rich_loc.set_escape_on_output (true);
@@ -1605,10 +1608,10 @@ maybe_warn_bidi_on_char (cpp_reader *pfile, bidi::kind kind,
       /* It seems excessive to warn about a PDI/PDF that is closing
         an opened context because we've already warned about the
         opening character.  Except warn when we have a UCN x UTF-8
-        mismatch.  */
+        mismatch, if UCN checking is enabled.  */
       if (kind == bidi::current_ctx ())
        {
-         if (warn_bidi == bidirectional_unpaired
+         if (warn_bidi == (bidirectional_unpaired|bidirectional_ucn)
              && bidi::current_ctx_ucn_p () != ucn_p)
            {
              rich_loc.add_range (bidi::current_ctx_loc ());
@@ -1617,7 +1620,8 @@ maybe_warn_bidi_on_char (cpp_reader *pfile, bidi::kind kind,
                              "a context by \"%s\"", bidi::to_str (kind));
            }
        }
-      else if (warn_bidi == bidirectional_any)
+      else if (warn_bidi & bidirectional_any
+              && (!ucn_p || (warn_bidi & bidirectional_ucn)))
        {
          if (kind == bidi::kind::PDF || kind == bidi::kind::PDI)
            cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,