aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/call.c7
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/decl2.c6
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/rtti.c8
-rw-r--r--gcc/cp/tree.c47
-rw-r--r--gcc/cp/typeck.c45
-rw-r--r--gcc/cp/typeck2.c16
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/warn/noeffect4.C88
12 files changed, 223 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6f8668c..6b7662f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,27 @@
+2003-09-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/12037
+ * cp-tree.h (COMPOUND_EXPR_OVERLOADED): New.
+ (build_min_non_dep): Declare.
+ * tree.c (build_min): Propagate TREE_SIDE_EFFECTS.
+ (build_min_non_dep): New.
+ * cvt.c (convert_to_void): Don't explicitly copy
+ TREE_SIDE_EFFECTS, TREE_NO_UNUSED_WARNING.
+ * call.c (build_new_method_call): Use build_min_non_dep.
+ * decl2.c (grok_array_decl): Likewise.
+ (build_offset_ref_call_from_tree): Likewise.
+ * typeck.c (finish_class_member_access_expr,
+ build_x_indirect_ref, build_x_binary_op, build_x_unary_op,
+ build_x_conditional_expr, build_x_compound_expr): Likewise.
+ (build_static_cast, build_reinterpret_cast,
+ build_const_cast): Propagate TREE_SIDE_EFFECTS inside a template.
+ * typeck2.c (build_x_arrow): Use build_min_non_dep.
+ (build_functional_cast): Propagate TREE_SIDE_EFFECTS inside a
+ template.
+ * rtti.c (build_dynamic_cast_1): Set DECL_IS_PURE.
+ (build_dynamic_cast): Set TREE_SIDE_EFFECTS.
+ * pt.c (build_non_dependent_expr): Check COMPOUND_EXPR_OVERLOADED.
+
2003-09-04 Richard Henderson <rth@redhat.com>
* decl2.c (mark_member_pointers_and_eh_handlers): Update for
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 35a8226..fee2357 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5081,9 +5081,10 @@ build_new_method_call (tree instance, tree fns, tree args,
finish:;
if (processing_template_decl && call != error_mark_node)
- return build_min (CALL_EXPR, TREE_TYPE (call),
- build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
- orig_args);
+ return build_min_non_dep
+ (CALL_EXPR, call,
+ build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
+ orig_args);
return call;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 278f5d6..8a2d512 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -39,6 +39,7 @@ struct diagnostic_context;
IDENTIFIER_MARKED (IDENTIFIER_NODEs)
NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
+ COMPOUND_EXPR_OVERLOADED (in COMPOUND_EXPR).
TREE_INDIRECT_USING (in NAMESPACE_DECL).
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
@@ -2294,6 +2295,10 @@ struct lang_decl GTY(())
#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
#define DELETE_EXPR_USE_VEC(NODE) TREE_LANG_FLAG_1 (NODE)
+/* Indicates that this is a non-dependent COMPOUND_EXPR which will
+ resolve to a function call. */
+#define COMPOUND_EXPR_OVERLOADED(NODE) TREE_LANG_FLAG_0 (NODE)
+
/* In a CALL_EXPR appearing in a template, true if Koenig lookup
should be performed at instantiation time. */
#define KOENIG_LOOKUP_P(NODE) TREE_LANG_FLAG_0(NODE)
@@ -4166,9 +4171,9 @@ extern tree canonical_type_variant (tree);
extern tree copy_base_binfos (tree, tree, tree);
extern int member_p (tree);
extern cp_lvalue_kind real_lvalue_p (tree);
-extern tree build_min (enum tree_code, tree,
- ...);
+extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
+extern tree build_min_non_dep (enum tree_code, tree, ...);
extern tree build_cplus_new (tree, tree);
extern tree get_target_expr (tree);
extern tree build_cplus_staticfn_type (tree, tree, tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 0a8e478..32d0d79 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -835,8 +835,6 @@ convert_to_void (tree expr, const char *implicit)
{
tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1),
TREE_OPERAND (expr, 0), new_op1);
- TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
- TREE_NO_UNUSED_WARNING (t) = TREE_NO_UNUSED_WARNING (expr);
expr = t;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 20d97d4..dfbffa7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -463,8 +463,8 @@ grok_array_decl (tree array_expr, tree index_exp)
expr = build_array_ref (array_expr, index_exp);
}
if (processing_template_decl && expr != error_mark_node)
- return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr,
- orig_index_exp);
+ return build_min_non_dep (ARRAY_REF, expr,
+ orig_array_expr, orig_index_exp);
return expr;
}
@@ -3029,7 +3029,7 @@ build_offset_ref_call_from_tree (tree fn, tree args)
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
- return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
+ return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args);
return expr;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 53d483c..c163018 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11811,7 +11811,8 @@ build_non_dependent_expr (tree expr)
TREE_OPERAND (expr, 0),
build_non_dependent_expr (TREE_OPERAND (expr, 1)),
build_non_dependent_expr (TREE_OPERAND (expr, 2)));
- if (TREE_CODE (expr) == COMPOUND_EXPR)
+ if (TREE_CODE (expr) == COMPOUND_EXPR
+ && !COMPOUND_EXPR_OVERLOADED (expr))
return build (COMPOUND_EXPR,
TREE_TYPE (expr),
TREE_OPERAND (expr, 0),
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 5e3437f..32d318d 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -652,6 +652,7 @@ build_dynamic_cast_1 (tree type, tree expr)
(NULL_TREE, ptrdiff_type_node, void_list_node))));
tmp = build_function_type (ptr_type_node, tmp);
dcast_fn = build_library_fn_ptr (name, tmp);
+ DECL_IS_PURE (dcast_fn) = 1;
pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn;
}
@@ -686,7 +687,12 @@ build_dynamic_cast (tree type, tree expr)
return error_mark_node;
if (processing_template_decl)
- return build_min (DYNAMIC_CAST_EXPR, type, expr);
+ {
+ expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
+ TREE_SIDE_EFFECTS (expr) = 1;
+
+ return expr;
+ }
return convert_from_reference (build_dynamic_cast_1 (type, expr));
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 1dddad4..8310bf1 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1265,11 +1265,8 @@ break_out_target_exprs (tree t)
return t;
}
-/* Obstack used for allocating nodes in template function and variable
- definitions. */
-
-/* Similar to `build_nt', except that we set TREE_COMPLEXITY to be the
- current line number. */
+/* Similar to `build_nt', but for template definitions of dependent
+ expressions */
tree
build_min_nt (enum tree_code code, ...)
@@ -1295,8 +1292,7 @@ build_min_nt (enum tree_code code, ...)
return t;
}
-/* Similar to `build', except we set TREE_COMPLEXITY to the current
- line-number. */
+/* Similar to `build', but for template definitions. */
tree
build_min (enum tree_code code, tree tt, ...)
@@ -1317,12 +1313,49 @@ build_min (enum tree_code code, tree tt, ...)
{
tree x = va_arg (p, tree);
TREE_OPERAND (t, i) = x;
+ if (x && TREE_SIDE_EFFECTS (x))
+ TREE_SIDE_EFFECTS (t) = 1;
}
va_end (p);
return t;
}
+/* Similar to `build', but for template definitions of non-dependent
+ expressions. NON_DEP is the non-dependent expression that has been
+ built. */
+
+tree
+build_min_non_dep (enum tree_code code, tree non_dep, ...)
+{
+ register tree t;
+ register int length;
+ register int i;
+ va_list p;
+
+ va_start (p, non_dep);
+
+ t = make_node (code);
+ length = TREE_CODE_LENGTH (code);
+ TREE_TYPE (t) = TREE_TYPE (non_dep);
+ TREE_COMPLEXITY (t) = input_line;
+ TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
+
+ for (i = 0; i < length; i++)
+ {
+ tree x = va_arg (p, tree);
+ TREE_OPERAND (t, i) = x;
+ }
+
+ if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
+ /* This should not be considered a COMPOUND_EXPR, because it
+ resolves to an overload. */
+ COMPOUND_EXPR_OVERLOADED (t) = 1;
+
+ va_end (p);
+ return t;
+}
+
/* Returns an INTEGER_CST (of type `int') corresponding to I.
Multiple calls with the same value of I may or may not yield the
same node; therefore, callers should never modify the node
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4823aba..da07fea 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1936,8 +1936,8 @@ finish_class_member_access_expr (tree object, tree name)
expr = build_class_member_access_expr (object, member, access_path,
/*preserve_reference=*/false);
if (processing_template_decl && expr != error_mark_node)
- return build_min (COMPONENT_REF, TREE_TYPE (expr), orig_object,
- orig_name);
+ return build_min_non_dep (COMPONENT_REF, expr,
+ orig_object, orig_name);
return expr;
}
@@ -1994,7 +1994,7 @@ build_x_indirect_ref (tree expr, const char *errorstring)
rval = build_indirect_ref (expr, errorstring);
if (processing_template_decl && rval != error_mark_node)
- return build_min (INDIRECT_REF, TREE_TYPE (rval), orig_expr);
+ return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
else
return rval;
}
@@ -2637,7 +2637,7 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
if (processing_template_decl && expr != error_mark_node)
- return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
+ return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
return expr;
}
@@ -3537,7 +3537,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
}
if (processing_template_decl && exp != error_mark_node)
- return build_min (code, TREE_TYPE (exp), orig_expr, NULL_TREE);
+ return build_min_non_dep (code, exp, orig_expr,
+ /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
return exp;
}
@@ -4277,8 +4278,8 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2)
expr = build_conditional_expr (ifexp, op1, op2);
if (processing_template_decl && expr != error_mark_node)
- return build_min (COND_EXPR, TREE_TYPE (expr),
- orig_ifexp, orig_op1, orig_op2);
+ return build_min_non_dep (COND_EXPR, expr,
+ orig_ifexp, orig_op1, orig_op2);
return expr;
}
@@ -4324,8 +4325,8 @@ build_x_compound_expr (tree op1, tree op2)
result = build_compound_expr (op1, op2);
if (processing_template_decl && result != error_mark_node)
- return build_min (COMPOUND_EXPR, TREE_TYPE (result),
- orig_op1, orig_op2);
+ return build_min_non_dep (COMPOUND_EXPR, result, orig_op1, orig_op2);
+
return result;
}
@@ -4382,8 +4383,10 @@ build_static_cast (tree type, tree expr)
if (processing_template_decl)
{
- tree t = build_min (STATIC_CAST_EXPR, type, expr);
- return t;
+ expr = build_min (STATIC_CAST_EXPR, type, expr);
+ /* We don't know if it will or will not have side effects. */
+ TREE_SIDE_EFFECTS (expr) = 1;
+ return expr;
}
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -4473,9 +4476,10 @@ build_static_cast (tree type, tree expr)
converted to an enumeration type. */
|| (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
- /* Really, build_c_cast should defer to this function rather
- than the other way around. */
- return build_c_cast (type, expr);
+ /* Really, build_c_cast should defer to this function rather
+ than the other way around. */
+ return build_c_cast (type, expr);
+
if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
&& CLASS_TYPE_P (TREE_TYPE (type))
&& CLASS_TYPE_P (TREE_TYPE (intype))
@@ -4491,6 +4495,7 @@ build_static_cast (tree type, tree expr)
ba_check | ba_quiet, NULL);
return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
}
+
if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
|| (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
{
@@ -4567,6 +4572,11 @@ build_reinterpret_cast (tree type, tree expr)
if (processing_template_decl)
{
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+
+ if (!TREE_SIDE_EFFECTS (t)
+ && type_dependent_expression_p (expr))
+ /* There might turn out to be side effects inside expr. */
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
@@ -4651,6 +4661,11 @@ build_const_cast (tree type, tree expr)
if (processing_template_decl)
{
tree t = build_min (CONST_CAST_EXPR, type, expr);
+
+ if (!TREE_SIDE_EFFECTS (t)
+ && type_dependent_expression_p (expr))
+ /* There might turn out to be side effects inside expr. */
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
@@ -4720,6 +4735,8 @@ build_c_cast (tree type, tree expr)
{
tree t = build_min (CAST_EXPR, type,
tree_cons (NULL_TREE, value, NULL_TREE));
+ /* We don't know if it will or will not have side effects. */
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 8b5af5e..28d876d 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1023,9 +1023,12 @@ build_x_arrow (tree expr)
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
{
if (processing_template_decl)
- return build_min (ARROW_EXPR,
- TREE_TYPE (TREE_TYPE (last_rval)),
- orig_expr);
+ {
+ expr = build_min_non_dep (ARROW_EXPR, last_rval, orig_expr);
+ /* It will be dereferenced. */
+ TREE_TYPE (expr) = TREE_TYPE (TREE_TYPE (last_rval));
+ return expr;
+ }
return build_indirect_ref (last_rval, NULL);
}
@@ -1120,7 +1123,12 @@ build_functional_cast (tree exp, tree parms)
type = exp;
if (processing_template_decl)
- return build_min (CAST_EXPR, type, parms);
+ {
+ tree t = build_min (CAST_EXPR, type, parms);
+ /* We don't know if it will or will not have side effects. */
+ TREE_SIDE_EFFECTS (t) = 1;
+ return t;
+ }
if (! IS_AGGR_TYPE (type))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c475b9a..693ae0c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-09-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/12037
+ * g++.dg/warn/noeffect4.C: New test.
+
2003-09-04 Matt Austern <austern@apple.com>
* g++.dg/ext/fnname1.C: New test. (__func__ for C++.)
diff --git a/gcc/testsuite/g++.dg/warn/noeffect4.C b/gcc/testsuite/g++.dg/warn/noeffect4.C
new file mode 100644
index 0000000..a4c46da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/noeffect4.C
@@ -0,0 +1,88 @@
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 2 Sep 2003 <nathan@codesourcery.com>
+
+// PR 12037.
+
+struct X
+{
+ int operator+(int);
+ int operator-(int);
+ int operator*(int);
+ int operator/(int);
+ int operator%(int);
+ int operator>>(int);
+ int operator<<(int);
+ int operator&(int);
+ int operator|(int);
+ int operator^(int);
+ int operator&&(int);
+ int operator||(int);
+ int operator==(int);
+ int operator!=(int);
+ int operator<(int);
+ int operator<=(int);
+ int operator>(int);
+ int operator>=(int);
+ int operator*();
+ int operator!();
+ int operator~();
+ int operator++();
+ int operator--();
+ int operator++(int);
+ int operator--(int);
+ int operator()();
+ int operator,(int);
+ X *operator->();
+ operator int () const;
+ int m;
+ virtual ~X ();
+ X &Foo ();
+};
+struct Y : X
+{
+};
+
+template<int I> void Foo (X &x)
+{
+ x + I;
+ x - I;
+ x * I;
+ x / I;
+ x % I;
+ x >> I;
+ x << I;
+ x & I;
+ x | I;
+ x && I;
+ x || I;
+ x == I;
+ x != I;
+ x < I;
+ x <= I;
+ x > I;
+ x >= I;
+ *x;
+ !x;
+ ~x;
+ x++;
+ x--;
+ ++x;
+ --x;
+ x ();
+ x, I;
+ x->m;
+ static_cast<int> (x);
+ dynamic_cast<Y &> (x);
+ reinterpret_cast<int> (x.Foo ());
+ const_cast<X &> (x.Foo ());
+
+ reinterpret_cast<int *> (&x);// { dg-warning "no effect" "" }
+ const_cast<X &> (x); // { dg-warning "no effect" "" }
+ sizeof (x++); // { dg-warning "no effect" "" }
+ __alignof__ (x++); // { dg-warning "no effect" "" }
+}
+
+