Commit e295e3d9 by Marek Polacek Committed by Marek Polacek

PR c++/92032 - DR 1601: Promotion of enum with fixed underlying type.

I've been messing with compare_ics recently and noticed that we don't
implement CWG 1601, which should be fairly easy.  Thus this patch.

The motivating example is 
  enum E : char { e };
  void f(char);
  void f(int);
  void g() {
    f(e);
  }
where the call to f was ambiguous but we should choose f(char).

Currently we give f(int) cr_promotion in standard_conversion, while
f(char) remains cr_std, which is worse than cr_promotion.  So I thought
I'd give it cr_promotion also and then add a tiebreaker to compare_ics.

	* call.c (standard_conversion): When converting an enumeration with
	a fixed underlying type to the underlying type, give it the cr_promotion
	rank.
	(compare_ics): Implement a tiebreaker as per CWG 1601.

	* g++.dg/cpp0x/scoped_enum10.C: New test.
	* g++.dg/cpp0x/scoped_enum11.C: New test.

From-SVN: r276766
parent cb57504a
2019-10-09 Marek Polacek <polacek@redhat.com>
PR c++/92032 - DR 1601: Promotion of enum with fixed underlying type.
* call.c (standard_conversion): When converting an enumeration with
a fixed underlying type to the underlying type, give it the cr_promotion
rank.
(compare_ics): Implement a tiebreaker as per CWG 1601.
2019-10-08 Andrew Sutton <asutton@lock3software.com>
Jason Merrill <jason@redhat.com>
......
......@@ -1472,8 +1472,18 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
conv = build_conv (ck_std, to, conv);
/* Give this a better rank if it's a promotion. */
if (same_type_p (to, type_promotes_to (from))
tree underlying_type = NULL_TREE;
if (TREE_CODE (from) == ENUMERAL_TYPE
&& ENUM_FIXED_UNDERLYING_TYPE_P (from))
underlying_type = ENUM_UNDERLYING_TYPE (from);
/* Give this a better rank if it's a promotion.
To handle CWG 1601, also bump the rank if we are converting
an enumeration with a fixed underlying type to the underlying
type. */
if ((same_type_p (to, type_promotes_to (from))
|| (underlying_type && same_type_p (to, underlying_type)))
&& next_conversion (conv)->rank <= cr_promotion)
conv->rank = cr_promotion;
}
......@@ -10473,6 +10483,31 @@ compare_ics (conversion *ics1, conversion *ics2)
}
}
/* [over.ics.rank]
Per CWG 1601:
-- A conversion that promotes an enumeration whose underlying type
is fixed to its underlying type is better than one that promotes to
the promoted underlying type, if the two are different. */
if (ics1->rank == cr_promotion
&& ics2->rank == cr_promotion
&& UNSCOPED_ENUM_P (from_type1)
&& ENUM_FIXED_UNDERLYING_TYPE_P (from_type1)
&& same_type_p (from_type1, from_type2))
{
tree utype = ENUM_UNDERLYING_TYPE (from_type1);
tree prom = type_promotes_to (from_type1);
if (!same_type_p (utype, prom))
{
if (same_type_p (to_type1, utype)
&& same_type_p (to_type2, prom))
return 1;
else if (same_type_p (to_type2, utype)
&& same_type_p (to_type1, prom))
return -1;
}
}
/* Neither conversion sequence is better than the other. */
return 0;
}
......
2019-10-09 Marek Polacek <polacek@redhat.com>
PR c++/92032 - DR 1601: Promotion of enum with fixed underlying type.
* g++.dg/cpp0x/scoped_enum10.C: New test.
* g++.dg/cpp0x/scoped_enum11.C: New test.
2019-10-08 Andrew Sutton <asutton@lock3software.com>
* lib/target-supports.exp (check_effective_target_concepts): Check
......
// PR c++/92032 - DR 1601: Promotion of enumeration with fixed underlying type.
// { dg-do compile { target c++11 } }
enum E : char { e };
enum F : int { f };
enum G : long { g };
enum H : unsigned { h };
int f1(char);
void f1(int);
void f2(int);
int f2(char);
int f3(int);
void f3(short);
int f4(long);
void f4(int);
void f5(unsigned);
int f5(int);
int f6(unsigned);
void f6(int);
void
test ()
{
int r = 0;
r += f1 (e);
r += f2 (e);
r += f3 (f);
r += f4 (g);
r += f5 (f);
r += f6 (h);
}
// PR c++/92032 - DR 1601: Promotion of enumeration with fixed underlying type.
// { dg-do compile { target c++11 } }
enum E1 : long { e1 };
enum E2 : short { e2 };
int f1(short);
void f1(int);
void f2(int);
int f2(short);
void f3(int);
int f3(long);
int f4(short);
void f4(long);
int f5(int);
void f5(long);
int f6(unsigned int); // { dg-message "candidate" }
void f6(long); // { dg-message "candidate" }
void
fn ()
{
int r = 0;
r += f1 (e2);
r += f2 (e2);
r += f3 (e1);
r += f4 (e2);
r += f5 (e2);
r += f6 (e2); // { dg-error "ambiguous" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment