OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Sep 2003 08:24:28 +0000 (08:24 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Sep 2003 08:24:28 +0000 (08:24 +0000)
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.
testsuite:
PR c++/12037
* g++.dg/warn/noeffect4.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71108 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/noeffect4.C [new file with mode: 0644]

index 6f8668c..6b7662f 100644 (file)
@@ -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
index 35a8226..fee2357 100644 (file)
@@ -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;
 }
 
index 278f5d6..8a2d512 100644 (file)
@@ -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);
index 0a8e478..32d0d79 100644 (file)
@@ -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;
          }
 
index 20d97d4..dfbffa7 100644 (file)
@@ -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;
 }
 
index 53d483c..c163018 100644 (file)
@@ -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),
index 5e3437f..32d318d 100644 (file)
@@ -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));
 }
index 1dddad4..8310bf1 100644 (file)
@@ -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
index 4823aba..da07fea 100644 (file)
@@ -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;
 }
 \f
@@ -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;
     }
 
index 8b5af5e..28d876d 100644 (file)
@@ -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))
     {
index c475b9a..693ae0c 100644 (file)
@@ -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 (file)
index 0000000..a4c46da
--- /dev/null
@@ -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" "" }
+}
+  
+