+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.
}
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;
+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.
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 :
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))
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);
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)
/* 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;
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",
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;
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))
{
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);
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 ();
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;
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));
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)
}
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;
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
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)
/* 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
/* 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);
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;
+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.
Blue,
Indigo = Green + 2,
Violet,
- Red // { dg-error "redefinition" }
+ Red // { dg-error "redeclaration" }
};
enum Color {
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)();
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
template <int A::* p>
int
-foo(A* q) // { dg-message "note" }
+foo(A* q)
{
return q->*p;
}
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);
--- /dev/null
+// 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;