Hi,

after more than 2 years, I'm finally back to this issue:

    https://gcc.gnu.org/ml/gcc-patches/2012-05/msg01442.html
    https://gcc.gnu.org/ml/gcc-patches/2012-05/msg01502.html

and the below draft, which passes testing, tries to implement as closely as possible what Jason suggested in the thread above. How does it look?

Thanks!
Paolo.

///////////////////
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 212431)
+++ cp/call.c   (working copy)
@@ -3773,9 +3773,13 @@ build_user_type_conversion_1 (tree totype, tree ex
   if (flags & LOOKUP_NO_NARROWING)
     conv->check_narrowing = true;
 
-  /* Combine it with the second conversion sequence.  */
-  cand->second_conv = merge_conversion_sequences (conv,
-                                                 cand->second_conv);
+  if (!(flags & LOOKUP_FOR_CHECK_NARROWING))
+    /* Combine it with the second conversion sequence.  */
+    cand->second_conv = merge_conversion_sequences (conv,
+                                                   cand->second_conv);
+  else
+    /* For convert_for_check_narrowing drop the second conversion.  */
+    cand->second_conv = conv;
 
   return cand;
 }
@@ -3809,6 +3813,37 @@ build_user_type_conversion (tree totype, tree expr
   return ret;
 }
 
+/* Used by check_narrowing.  */
+
+tree
+convert_for_check_narrowing (tree totype, tree expr)
+{
+  struct z_candidate *cand;
+  tree ret;
+
+  bool subtime = timevar_cond_start (TV_OVERLOAD);
+  cand = build_user_type_conversion_1 (totype, expr,
+                                      LOOKUP_NORMAL
+                                      | LOOKUP_FOR_CHECK_NARROWING,
+                                      tf_none);
+
+  if (cand)
+    {
+      if (cand->second_conv->kind == ck_ambig)
+       ret = error_mark_node;
+      else
+       ret = convert_like (cand->second_conv, expr, tf_none);
+    }
+  else
+    ret = NULL_TREE;
+
+  if (!ret || ret == error_mark_node)
+    ret = expr;
+
+  timevar_cond_stop (TV_OVERLOAD, subtime);
+  return ret;
+}
+
 /* Subroutine of convert_nontype_argument.
 
    EXPR is an argument for a template non-type parameter of integral or
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 212431)
+++ cp/cp-tree.h        (working copy)
@@ -4573,6 +4573,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T
 #define LOOKUP_NO_NON_INTEGRAL (LOOKUP_NO_RVAL_BIND << 1)
 /* Used for delegating constructors in order to diagnose self-delegation.  */
 #define LOOKUP_DELEGATING_CONS (LOOKUP_NO_NON_INTEGRAL << 1)
+/* Used by convert_for_check_narrowing.  */
+#define LOOKUP_FOR_CHECK_NARROWING (LOOKUP_DELEGATING_CONS << 1)
 
 #define LOOKUP_NAMESPACES_ONLY(F)  \
   (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
@@ -5050,6 +5052,8 @@ extern bool sufficient_parms_p                    
(const_tree);
 extern tree type_decays_to                     (tree);
 extern tree build_user_type_conversion         (tree, tree, int,
                                                 tsubst_flags_t);
+extern tree convert_for_check_narrowing         (tree, tree);
+
 extern tree build_new_function_call            (tree, vec<tree, va_gc> **, 
bool, 
                                                 tsubst_flags_t);
 extern tree build_operator_new_call            (tree, vec<tree, va_gc> **, 
tree *,
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c        (revision 212431)
+++ cp/typeck2.c        (working copy)
@@ -854,6 +854,13 @@ check_narrowing (tree type, tree init)
   if (!warn_narrowing || !ARITHMETIC_TYPE_P (type))
     return;
 
+  if (CLASS_TYPE_P (ftype))
+    {
+      /* Look through, eg, conversion operators (c++/53159).  */
+      init = convert_for_check_narrowing (type, init);
+      ftype = unlowered_expr_type (init);
+    }
+
   if (BRACE_ENCLOSED_INITIALIZER_P (init)
       && TREE_CODE (type) == COMPLEX_TYPE)
     {
Index: testsuite/g++.dg/cpp0x/Wnarrowing1.C
===================================================================
--- testsuite/g++.dg/cpp0x/Wnarrowing1.C        (revision 0)
+++ testsuite/g++.dg/cpp0x/Wnarrowing1.C        (working copy)
@@ -0,0 +1,14 @@
+// PR c++/53159
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wnarrowing -Wno-overflow" }
+
+struct X
+{
+  constexpr operator int() { return __INT_MAX__; }
+};
+
+int f() { return __INT_MAX__; }
+
+signed char a { __INT_MAX__ };  // { dg-warning "narrowing conversion" }
+signed char b { f() };          // { dg-warning "narrowing conversion" }
+signed char c { X{} };          // { dg-warning "narrowing conversion" }

Reply via email to