diff options
-rw-r--r-- | gcc/cp/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cp/call.c | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 9 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 8 | ||||
-rw-r--r-- | gcc/cp/tree.c | 47 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 45 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/noeffect4.C | 88 |
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" "" } +} + + |