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.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
Or should this wait till GCC 11?  (Though I don't expect that this problem
is common enough.)

        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/typeck2.c                          |  9 ++++++++-
 gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C | 15 +++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C

diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 56fd9bafa7e..2165978bf1c 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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)
            {
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C 
b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C
new file mode 100644
index 00000000000..0dc7075cd62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing18.C
@@ -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" }
+}

base-commit: 5da301cbd81c41b2e9629f55dd1b1889f7dae75e
-- 
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA

Reply via email to