... I'm attaching some code accompanying my blabber. Note - in fact I
noticed this some days ago - that probably the idea of passing complain
to check_narrowing is good anyway, otherwise we have a function emitting
unconditional warnings called by functions which have a tsubst_flags_t.
Paolo.
/////////////
Index: call.c
===================================================================
--- call.c (revision 213752)
+++ call.c (working copy)
@@ -6252,7 +6252,7 @@ convert_like_real (conversion *convs, tree expr, t
if (sub == error_mark_node)
return sub;
if (!BRACE_ENCLOSED_INITIALIZER_P (val))
- check_narrowing (TREE_TYPE (sub), val);
+ check_narrowing (TREE_TYPE (sub), val, complain);
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE,
sub);
if (!TREE_CONSTANT (sub))
TREE_CONSTANT (new_ctor) = false;
@@ -6480,10 +6480,11 @@ convert_like_real (conversion *convs, tree expr, t
break;
}
+ int error_count = errorcount;
if (convs->check_narrowing)
- check_narrowing (totype, expr);
+ check_narrowing (totype, expr, complain);
- if (issue_conversion_warnings)
+ if (issue_conversion_warnings && errorcount == error_count)
expr = cp_convert_and_check (totype, expr, complain);
else
expr = cp_convert (totype, expr, complain);
Index: cp-tree.h
===================================================================
--- cp-tree.h (revision 213752)
+++ cp-tree.h (working copy)
@@ -4331,6 +4331,7 @@ enum tsubst_flags {
for calls in decltype (5.2.2/11). */
tf_partial = 1 << 8, /* Doing initial explicit argument
substitution in fn_type_unification. */
+ tf_enum = 1 << 9, /* */
/* Convenient substitution flags combinations. */
tf_warning_or_error = tf_warning | tf_error
};
@@ -6214,7 +6215,7 @@ extern int abstract_virtuals_error_sfinae (tree, t
extern int abstract_virtuals_error_sfinae (abstract_class_use, tree,
tsubst_flags_t);
extern tree store_init_value (tree, tree, vec<tree,
va_gc>**, int);
-extern void check_narrowing (tree, tree);
+extern void check_narrowing (tree, tree, tsubst_flags_t);
extern tree digest_init (tree, tree,
tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int);
extern tree digest_nsdmi_init (tree, tree);
Index: decl.c
===================================================================
--- decl.c (revision 213752)
+++ decl.c (working copy)
@@ -12974,7 +12974,8 @@ build_enumerator (tree name, tree value, tree enum
}
else if (! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
value = perform_implicit_conversion_flags
- (ENUM_UNDERLYING_TYPE (enumtype), value, tf_warning_or_error,
+ (ENUM_UNDERLYING_TYPE (enumtype), value,
+ tf_warning_or_error | tf_enum,
LOOKUP_IMPLICIT | LOOKUP_NO_NARROWING);
if (value == error_mark_node)
Index: semantics.c
===================================================================
--- semantics.c (revision 213752)
+++ semantics.c (working copy)
@@ -2598,7 +2598,7 @@ finish_compound_literal (tree type, tree compound_
if (SCALAR_TYPE_P (type)
&& !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)
&& (complain & tf_warning_or_error))
- check_narrowing (type, compound_literal);
+ check_narrowing (type, compound_literal, complain);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
Index: typeck2.c
===================================================================
--- typeck2.c (revision 213752)
+++ typeck2.c (working copy)
@@ -845,13 +845,15 @@ store_init_value (tree decl, tree init, vec<tree,
/* Give errors about narrowing conversions within { }. */
void
-check_narrowing (tree type, tree init)
+check_narrowing (tree type, tree init, tsubst_flags_t complain)
{
tree ftype = unlowered_expr_type (init);
bool ok = true;
REAL_VALUE_TYPE d;
- if (!warn_narrowing || !ARITHMETIC_TYPE_P (type))
+ if (!(complain & tf_warning_or_error)
+ || (!warn_narrowing && !(complain & tf_enum))
+ || !ARITHMETIC_TYPE_P (type))
return;
if (BRACE_ENCLOSED_INITIALIZER_P (init)
@@ -859,9 +861,9 @@ void
{
tree elttype = TREE_TYPE (type);
if (CONSTRUCTOR_NELTS (init) > 0)
- check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value);
+ check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value, complain);
if (CONSTRUCTOR_NELTS (init) > 1)
- check_narrowing (elttype, CONSTRUCTOR_ELT (init, 1)->value);
+ check_narrowing (elttype, CONSTRUCTOR_ELT (init, 1)->value, complain);
return;
}
@@ -918,9 +920,15 @@ void
if (!ok)
{
if (cxx_dialect >= cxx11)
- pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
- "narrowing conversion of %qE from %qT to %qT inside { }",
- init, ftype, type);
+ {
+ if (complain & tf_enum)
+ error ("enumerator value %E is outside the range of underlying "
+ "type %<%T%>", init, type);
+ else
+ pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
+ "narrowing conversion of %qE from %qT to %qT inside { }",
+ init, ftype, type);
+ }
else
warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
"narrowing conversion of %qE from %qT to %qT inside { } "