c++: Detect long double -> double narrowing [PR94590]
authorMarek Polacek <polacek@redhat.com>
Sun, 19 Apr 2020 22:46:40 +0000 (18:46 -0400)
committerMarek Polacek <polacek@redhat.com>
Thu, 7 May 2020 18:15:37 +0000 (14:15 -0400)
This PR points out that we don't detect long double -> double narrowing
when long double happens to have the same precision as double; on x86_64
this can be achieved by -mlong-double-64.

[dcl.init.list]#7.2 specifically says "from long double to double or float,
or from double to float", but check_narrowing only checks

  TYPE_PRECISION (type) < TYPE_PRECISION (ftype)

so we need to handle the other cases too, e.g. by same_type_p as in
the following patch.

PR c++/94590 - Detect long double -> double narrowing.
* typeck2.c (check_narrowing): Detect long double -> double
narrowing even when double and long double have the same
precision.  Make it handle conversions to float too.

* g++.dg/cpp0x/Wnarrowing18.C: New test.

gcc/cp/ChangeLog
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C [new file with mode: 0644]

index 7454352020e1207492b21abfdda6ddd6f5728c65..031741e2264d3df1903ee585a6032c933c76f9fd 100644 (file)
@@ -1,3 +1,10 @@
+2020-05-07  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/94590 - Detect long double -> double narrowing.
+       * typeck2.c (check_narrowing): Detect long double -> double
+       narrowing even when double and long double have the same
+       precision.  Make it handle conversions to float too.
+
 2020-05-07  Marek Polacek  <polacek@redhat.com>
 
        PR c++/94255
index acf4414980c226f700e6fbbfd6a9093bf3077912..d407e4cbfa4895a7dafa28103750c234faca6698 100644 (file)
@@ -1008,10 +1008,17 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain,
              || !int_fits_type_p (init, type)))
        ok = false;
     }
+  /* [dcl.init.list]#7.2: "from long double to double or float, or from
+      double to float".  */
   else if (TREE_CODE (ftype) == REAL_TYPE
           && TREE_CODE (type) == REAL_TYPE)
     {
-      if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))
+      if ((same_type_p (ftype, long_double_type_node)
+          && (same_type_p (type, double_type_node)
+              || same_type_p (type, float_type_node)))
+         || (same_type_p (ftype, double_type_node)
+             && same_type_p (type, float_type_node))
+         || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)))
        {
          if (TREE_CODE (init) == REAL_CST)
            {
index bed2d90fb02700383ddc65f0e05ad91d1a147b9a..6712c1dfbb27af23dadb10e3cc3457b294a4a068 100644 (file)
@@ -1,3 +1,8 @@
+2020-05-07  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/94590 - Detect long double -> double narrowing.
+       * g++.dg/cpp0x/Wnarrowing18.C: New test.
+
 2020-05-07  Marek Polacek  <polacek@redhat.com>
 
        PR c++/94255
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C
new file mode 100644 (file)
index 0000000..0dc7075
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/94590 - Detect long double -> double narrowing.
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-mlong-double-64" { target x86_64-*-* i?86-*-* } }
+
+int
+main ()
+{
+  using T = long double;
+  extern long double ld;
+  extern T ld2;
+  extern const T ld3;
+  double d{ld}; // { dg-error "narrowing conversion" }
+  double d2{ld2}; // { dg-error "narrowing conversion" }
+  double d3{ld3}; // { dg-error "narrowing conversion" }
+}