aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c3
-rw-r--r--gcc/cp/ChangeLog20
-rw-r--r--gcc/cp/call.c22
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/cvt.c4
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/pt.c13
-rw-r--r--gcc/cp/search.c7
-rw-r--r--gcc/cp/semantics.c25
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum.C2
-rw-r--r--gcc/testsuite/g++.dg/other/ptrmem10.C5
-rw-r--r--gcc/testsuite/g++.dg/other/ptrmem11.C5
-rw-r--r--gcc/testsuite/g++.dg/template/enum7.C8
18 files changed, 90 insertions, 54 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index e19e703..8b7c4b7 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 61d7567..2a528e2 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9b5b7c1..448dd5c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 09965b3..72394f4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6307e84..264258c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 998d4eb..9550f15 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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",
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ab56019..18beaa9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d8c7260..cbb1053 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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))
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7e1c46f..f8f416a 100644
--- a/gcc/cp/pt.c
+++ b/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 ();
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index e6d6be8..d112c05 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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));
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d45a6e2..f1a94c1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 2b541cd..a03f845 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 971f386..3bc3ead 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 066eb5c..5d5a2ce 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
index c52a3fe..4b0317c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
@@ -13,7 +13,7 @@ enum struct Color2 {
Blue,
Indigo = Green + 2,
Violet,
- Red // { dg-error "redefinition" }
+ Red // { dg-error "redeclaration" }
};
enum Color {
diff --git a/gcc/testsuite/g++.dg/other/ptrmem10.C b/gcc/testsuite/g++.dg/other/ptrmem10.C
index a17df7f..ff8c843 100644
--- a/gcc/testsuite/g++.dg/other/ptrmem10.C
+++ b/gcc/testsuite/g++.dg/other/ptrmem10.C
@@ -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
diff --git a/gcc/testsuite/g++.dg/other/ptrmem11.C b/gcc/testsuite/g++.dg/other/ptrmem11.C
index e73164e..e18abdd 100644
--- a/gcc/testsuite/g++.dg/other/ptrmem11.C
+++ b/gcc/testsuite/g++.dg/other/ptrmem11.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/template/enum7.C b/gcc/testsuite/g++.dg/template/enum7.C
new file mode 100644
index 0000000..8c464a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/enum7.C
@@ -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;