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:
parent
531b10fcb0
commit
8d0d1915d9
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
13
gcc/cp/pt.c
13
gcc/cp/pt.c
|
@ -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 ();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -13,7 +13,7 @@ enum struct Color2 {
|
|||
Blue,
|
||||
Indigo = Green + 2,
|
||||
Violet,
|
||||
Red // { dg-error "redefinition" }
|
||||
Red // { dg-error "redeclaration" }
|
||||
};
|
||||
|
||||
enum Color {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue