re PR c++/53524 (Bogus enum comparison warning)

PR c++/53524
gcc/cp/
	* call.c (build_conditional_expr_1): Don't warn about comparison of
	two enumerators before their enumeration is complete.
	(build_new_op_1): Call decay_conversion before warn_logical_operator.
	* decl.c (build_enumerator): Set DECL_CONTEXT of an enumerator to
	its enumeration.
	* decl2.c (mark_used): Call used_types_insert for enums.
	* semantics.c (finish_id_expression): Don't decay CONST_DECL.
	(finish_member_declaration): Don't change DECL_CONTEXT of enumerators.
	* class.c (check_field_decls): Don't change DECL_CONTEXT of enums.
	* typeck.c (convert_for_assignment): Don't decay CONST_DECL.
	(build_class_member_access_expr): Look through unscoped enums.
	* search.c (context_for_name_lookup): Look through unscoped enums.
	* pt.c (tsubst_copy_and_build): Don't decay CONST_DECL.
	(tsubst_copy): Use DECL_CONTEXT to find the enumeration.
	* tree.c (decl_linkage): Likewise.
	* cvt.c (ocp_convert): Check decayed expr for enum range warning.
gcc/c-family/
	* c-common.c (get_priority): Call default_conversion.

From-SVN: r189174
This commit is contained in:
Jason Merrill 2012-07-02 15:14:23 -04:00 committed by Jason Merrill
parent 531b10fcb0
commit 8d0d1915d9
18 changed files with 90 additions and 54 deletions

View File

@ -1,3 +1,8 @@
2012-07-02 Jason Merrill <jason@redhat.com>
PR c++/53524
* c-common.c (get_priority): Call default_conversion.
2012-07-01 Uros Bizjak <ubizjak@gmail.com>
* c-pch.c (c_common_write_pch): Remove unused variables.

View File

@ -6587,11 +6587,12 @@ get_priority (tree args, bool is_destructor)
}
arg = TREE_VALUE (args);
arg = default_conversion (arg);
if (!host_integerp (arg, /*pos=*/0)
|| !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
goto invalid;
pri = tree_low_cst (TREE_VALUE (args), /*pos=*/0);
pri = tree_low_cst (arg, /*pos=*/0);
if (pri < 0 || pri > MAX_INIT_PRIORITY)
goto invalid;

View File

@ -1,3 +1,23 @@
2012-07-02 Jason Merrill <jason@redhat.com>
PR c++/53524
* call.c (build_conditional_expr_1): Don't warn about comparison of
two enumerators before their enumeration is complete.
(build_new_op_1): Call decay_conversion before warn_logical_operator.
* decl.c (build_enumerator): Set DECL_CONTEXT of an enumerator to
its enumeration.
* decl2.c (mark_used): Call used_types_insert for enums.
* semantics.c (finish_id_expression): Don't decay CONST_DECL.
(finish_member_declaration): Don't change DECL_CONTEXT of enumerators.
* class.c (check_field_decls): Don't change DECL_CONTEXT of enums.
* typeck.c (convert_for_assignment): Don't decay CONST_DECL.
(build_class_member_access_expr): Look through unscoped enums.
* search.c (context_for_name_lookup): Look through unscoped enums.
* pt.c (tsubst_copy_and_build): Don't decay CONST_DECL.
(tsubst_copy): Use DECL_CONTEXT to find the enumeration.
* tree.c (decl_linkage): Likewise.
* cvt.c (ocp_convert): Check decayed expr for enum range warning.
2012-06-29 Steven Bosscher <steven@gcc.gnu.org>
* Make-lang.in: Remove tree-mudflap.o from CXX_AND_OBJCXX_OBJS.

View File

@ -4365,6 +4365,7 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
struct z_candidate *candidates = 0;
struct z_candidate *cand;
void *p;
tree orig_arg2, orig_arg3;
/* As a G++ extension, the second argument to the conditional can be
omitted. (So that `a ? : c' is roughly equivalent to `a ? a :
@ -4404,6 +4405,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
orig_arg2 = arg2;
orig_arg3 = arg3;
arg2_type = unlowered_expr_type (arg2);
arg3_type = unlowered_expr_type (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
@ -4701,7 +4704,12 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& TREE_CODE (arg3_type) == ENUMERAL_TYPE)
{
if (complain & tf_warning)
if (TREE_CODE (orig_arg2) == CONST_DECL
&& TREE_CODE (orig_arg3) == CONST_DECL
&& DECL_CONTEXT (orig_arg2) == DECL_CONTEXT (orig_arg3))
/* Two enumerators from the same enumeration can have different
types when the enumeration is still being defined. */;
else if (complain & tf_warning)
warning (OPT_Wenum_compare,
"enumeral mismatch in conditional expression: %qT vs %qT",
arg2_type, arg3_type);
@ -5221,16 +5229,20 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
if (arg2)
{
conv = cand->convs[1];
if (conv->kind == ck_ref_bind)
conv = next_conversion (conv);
else
arg2 = decay_conversion (arg2, complain);
/* We need to call warn_logical_operator before
converting arg2 to a boolean_type. */
converting arg2 to a boolean_type, but after
decaying an enumerator to its value. */
if (complain & tf_warning)
warn_logical_operator (loc, code, boolean_type_node,
code_orig_arg1, arg1,
code_orig_arg2, arg2);
conv = cand->convs[1];
if (conv->kind == ck_ref_bind)
conv = next_conversion (conv);
arg2 = convert_like (conv, arg2, complain);
}
if (arg3)

View File

@ -3114,7 +3114,8 @@ check_field_decls (tree t, tree *access_decls,
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
DECL_CONTEXT (x) = t;
if (TREE_CODE (x) != CONST_DECL)
DECL_CONTEXT (x) = t;
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;

View File

@ -741,8 +741,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
values. Otherwise, the resulting enumeration value is
unspecified. */
if ((complain & tf_warning)
&& TREE_CODE (expr) == INTEGER_CST
&& !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type)))
&& TREE_CODE (e) == INTEGER_CST
&& !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type)))
warning_at (loc, OPT_Wconversion,
"the result of the conversion is unspecified because "
"%qE is outside the range of type %qT",

View File

@ -12570,7 +12570,7 @@ incremented enumerator value is too large for %<long%>");
a function could mean local to a class method. */
decl = build_decl (loc, CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
DECL_CONTEXT (decl) = enumtype;
TREE_CONSTANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;

View File

@ -4205,6 +4205,10 @@ mark_used (tree decl)
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
/* Mark enumeration types as used. */
if (TREE_CODE (decl) == CONST_DECL)
used_types_insert (DECL_CONTEXT (decl));
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{

View File

@ -12128,7 +12128,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
When we instantiate f<7>::S::g(), say, lookup_name is not
clever enough to find f<7>::a. */
enum_type
= tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
= tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl,
/*entering_scope=*/0);
for (v = TYPE_VALUES (enum_type);
@ -14385,17 +14385,6 @@ tsubst_copy_and_build (tree t,
return stmt_expr;
}
case CONST_DECL:
t = tsubst_copy (t, args, complain, in_decl);
/* As in finish_id_expression, we resolve enumeration constants
to their underlying values. */
if (TREE_CODE (t) == CONST_DECL && !processing_template_decl)
{
used_types_insert (TREE_TYPE (t));
return DECL_INITIAL (t);
}
return t;
case LAMBDA_EXPR:
{
tree r = build_lambda_expr ();

View File

@ -579,7 +579,8 @@ context_for_name_lookup (tree decl)
declared. */
tree context = DECL_CONTEXT (decl);
while (context && TYPE_P (context) && ANON_AGGR_TYPE_P (context))
while (context && TYPE_P (context)
&& (ANON_AGGR_TYPE_P (context) || UNSCOPED_ENUM_P (context)))
context = TYPE_CONTEXT (context);
if (!context)
context = global_namespace;
@ -623,9 +624,7 @@ dfs_access_in_type (tree binfo, void *data)
else
{
/* First, check for an access-declaration that gives us more
access to the DECL. The CONST_DECL for an enumeration
constant will not have DECL_LANG_SPECIFIC, and thus no
DECL_ACCESS. */
access to the DECL. */
if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
{
tree decl_access = purpose_member (type, DECL_ACCESS (decl));

View File

@ -2631,8 +2631,10 @@ finish_member_declaration (tree decl)
TREE_PROTECTED (DECL_TEMPLATE_RESULT (decl)) = TREE_PROTECTED (decl);
}
/* Mark the DECL as a member of the current class. */
DECL_CONTEXT (decl) = current_class_type;
/* Mark the DECL as a member of the current class, unless it's
a member of an enumeration. */
if (TREE_CODE (decl) != CONST_DECL)
DECL_CONTEXT (decl) = current_class_type;
/* Check for bare parameter packs in the member variable declaration. */
if (TREE_CODE (decl) == FIELD_DECL)
@ -3060,18 +3062,6 @@ finish_id_expression (tree id_expression,
}
return r;
}
/* Similarly, we resolve enumeration constants to their
underlying values. */
else if (TREE_CODE (decl) == CONST_DECL)
{
*idk = CP_ID_KIND_NONE;
if (!processing_template_decl)
{
used_types_insert (TREE_TYPE (decl));
return DECL_INITIAL (decl);
}
return decl;
}
else
{
bool dependent_p;
@ -3100,6 +3090,9 @@ finish_id_expression (tree id_expression,
if (!processing_template_decl)
/* No names are dependent outside a template. */
;
else if (TREE_CODE (decl) == CONST_DECL)
/* We don't want to treat enumerators as dependent. */
;
/* A template-id where the name of the template was not resolved
is definitely dependent. */
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
@ -3234,15 +3227,17 @@ finish_id_expression (tree id_expression,
marked either below or after overload resolution. */
if (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == CONST_DECL
|| TREE_CODE (decl) == RESULT_DECL)
mark_used (decl);
/* Only certain kinds of names are allowed in constant
expression. Enumerators and template parameters have already
expression. Template parameters have already
been handled above. */
if (! error_operand_p (decl)
&& integral_constant_expression_p
&& ! decl_constant_var_p (decl)
&& TREE_CODE (decl) != CONST_DECL
&& ! builtin_valid_in_constant_expr_p (decl))
{
if (!allow_non_integral_constant_expression_p)

View File

@ -3212,7 +3212,7 @@ decl_linkage (tree decl)
/* Linkage of a CONST_DECL depends on the linkage of the enumeration
type. */
if (TREE_CODE (decl) == CONST_DECL)
return decl_linkage (TYPE_NAME (TREE_TYPE (decl)));
return decl_linkage (TYPE_NAME (DECL_CONTEXT (decl)));
/* Some things that are not TREE_PUBLIC have external linkage, too.
For example, on targets that don't have weak symbols, we make all

View File

@ -2199,7 +2199,7 @@ build_class_member_access_expr (tree object, tree member,
/* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
presently be the anonymous union. Go outwards until we find a
type related to OBJECT_TYPE. */
while (ANON_AGGR_TYPE_P (member_scope)
while ((ANON_AGGR_TYPE_P (member_scope) || UNSCOPED_ENUM_P (member_scope))
&& !same_type_ignoring_top_level_qualifiers_p (member_scope,
object_type))
member_scope = TYPE_CONTEXT (member_scope);
@ -7582,10 +7582,6 @@ convert_for_assignment (tree type, tree rhs,
return error_mark_node;
}
/* Simplify the RHS if possible. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
if (c_dialect_objc ())
{
int parmno;

View File

@ -1,3 +1,11 @@
2012-07-02 Jason Merrill <jason@redhat.com>
PR c++/53524
* g++.dg/template/enum7.C: New.
* g++.dg/other/ptrmem10.C: Adjust.
* g++.dg/other/ptrmem11.C: Adjust.
* g++.dg/cpp0x/scoped_enum.C: Adjust.
2012-07-02 Steven Bosscher <steven@gcc.gnu.org>
* gcc.dg/tree-ssa/pr36881.c: Fix test case to not expand as bit tests.

View File

@ -13,7 +13,7 @@ enum struct Color2 {
Blue,
Indigo = Green + 2,
Violet,
Red // { dg-error "redefinition" }
Red // { dg-error "redeclaration" }
};
enum Color {

View File

@ -3,7 +3,7 @@
template <class C, void (C::*M) ()>
static
void foo(void *obj) // { dg-message "note" }
void foo(void *obj)
{
C *p = static_cast<C*>(obj);
(p->*M)();
@ -13,8 +13,7 @@ template <class C>
static void
bar(C *c, void (C::*m) ())
{
foo<C,m>((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun|could not convert)" }
// { dg-message "candidate" "candidate note" { target *-*-* } 16 }
foo<C,m>((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun|could not convert|constant)" }
}
struct S

View File

@ -5,7 +5,7 @@ struct A {};
template <int A::* p>
int
foo(A* q) // { dg-message "note" }
foo(A* q)
{
return q->*p;
}
@ -14,8 +14,7 @@ template <typename T>
int
bar(int T::* p)
{
return foo<p>(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member|could not convert)" }
// { dg-message "candidate" "candidate note" { target *-*-* } 17 }
return foo<p>(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member|could not convert|constant)" }
}
int i = bar<A>(0);

View File

@ -0,0 +1,8 @@
// PR c++/53524
template <class T> struct A { enum EA { ea }; };
template <class T, class U> struct B {
enum EB { eb1 = A<T>::ea, eb2 = A<U>::ea, eb3 = 0 ? eb1 : eb2 };
};
B<int,char> b;