Merge C++ delayed folding branch.
authorJason Merrill <jason@gcc.gnu.org>
Sat, 14 Nov 2015 00:08:05 +0000 (19:08 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 14 Nov 2015 00:08:05 +0000 (19:08 -0500)
* call.c (build_conditional_expr_1, convert_like_real)
(convert_arg_to_ellipsis, convert_for_arg_passing): Don't fold.
(build_new_op_1, build_over_call, build_cxx_call): Fold for warnings.
* class.c (build_base_path, determine_primary_bases)
(update_vtable_entry_for_fn, check_bitfield_decl)
(layout_nonempty_base_or_field, layout_empty_base)
(propagate_binfo_offsets, include_empty_classes)
(layout_class_type, build_vbase_offset_vtbl_entries): Use
fold_convert.
* constexpr.c (cxx_eval_builtin_function_call): Fold away the NOP_EXPR.
(cxx_eval_call_expression): Handle MEM_REF.
(cxx_eval_pointer_plus_expression): Fold the second operand.
(cxx_eval_constant_expression): Handle MEM_REF, UNARY_PLUS_EXPR.
(fold_simple_1, fold_simple): New.
(maybe_constant_value_1): Factor out from maybe_constant_value.
(cv_cache, maybe_constant_value): Cache results.
(maybe_constant_init): Handle null input.
(potential_constant_expression_1): Handle RESULT_DECL, EMPTY_CLASS_EXPR.
* cp-array-notation.c (build_array_notation_ref): Fold operands.
* cp-gimplify.c (cp_fold_r, cp_fold): New.
(cp_genericize_r): Use fold_convert.  Don't fold SIZEOF_EXPR.
(cp_genericize): Fold everything.
(contains_label_1, contains_label_p): New.
(cp_fold, cp_fully_fold): New.
* cp-tree.h (class cache_map): New.
* cvt.c (cp_convert_to_pointer, ocp_convert): Use convert_to_*_nofold.
(cp_convert_and_check): Use cp_fully_fold.
(convert, convert_force): Don't fold.
* decl.c (fold_sizeof_expr): Change from fold_sizeof_expr_r.
(compute_array_index_type): Use cp_fully_fold.
(build_enumerator): Use fold_convert.
* decl2.c (get_guard_cond, set_guard): Use fold_convert.
* init.c (build_zero_init_1): Fold zero-initializers.
(build_new_1): Fold nelts calculations.
(build_vec_delete_1): Fold conversions.
(build_vec_init): Fold maxindex.
* parser.c (cp_parser_binary_expression): Fold LHS of || and &&.
(cp_parser_question_colon_clause): Fold LHS.
* pt.c (convert_nontype_argument): Fold nullptr conversion.
* semantics.c (finish_unary_op_expr): Fold for warnings.
(handle_omp_array_sections_1): Fold length and low bound.
(handle_omp_for_class_iterator): Fold various things.
* tree.c (builtin_valid_in_constant_expr_p): Add
BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE.
(convert_bitfield_to_declared_type): Don't fold.
(handle_init_priority_attribute): Fold.
(fold_if_not_in_template): Remove.
* typeck.c (decay_conversion, build_class_member_access_expr)
(build_simple_component_ref, cp_build_array_ref, build_vec_cmp)
(cp_pointer_int_sum, pointer_diff): Don't fold.
(cp_build_binary_op): Fold for warnings and PMF ops.
(cp_build_unary_op): Fold negation of a constant, nothing else.
(expand_ptrmemfunc_cst): Fold operations.
* typeck2.c (split_nonconstant_init): Fold initializer.
(store_init_value): Likewise.
(check_narrowing): Try folding.
* config-lang.in (gtfiles): Add cp-gimplify.c.

From-SVN: r230365

46 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/config-lang.in
gcc/cp/constexpr.c
gcc/cp/cp-array-notation.c
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/objcp/ChangeLog
gcc/objcp/config-lang.in
gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
gcc/testsuite/c-c++-common/fold-bitand-4.c
gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
gcc/testsuite/g++.dg/cpp0x/pr53792.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr56868.cpp [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/attr-aligned01.C
gcc/testsuite/g++.dg/ext/offsetof1.C
gcc/testsuite/g++.dg/init/const7.C
gcc/testsuite/g++.dg/init/self1.C
gcc/testsuite/g++.dg/other/error22.C
gcc/testsuite/g++.dg/other/error24.C
gcc/testsuite/g++.dg/other/error26.C
gcc/testsuite/g++.dg/parse/array-size2.C
gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
gcc/testsuite/g++.dg/ubsan/shift-1.C
gcc/testsuite/g++.dg/warn/overflow-warn-1.C
gcc/testsuite/g++.dg/warn/overflow-warn-3.C
gcc/testsuite/g++.dg/warn/overflow-warn-4.C
gcc/testsuite/g++.old-deja/g++.other/null3.C

index 52f95a04131d19fd5074edfa2d48998ffabfd299..2ea5448f08ecc38c7b9c29d9a1b4f417a9b350c1 100644 (file)
@@ -1,3 +1,65 @@
+2015-11-13  Kai Tietz  <ktietz70@googlemail.com>
+           Marek Polacek  <polacek@redhat.com>
+           Jason Merrill  <jason@redhat.com>
+
+       * call.c (build_conditional_expr_1, convert_like_real)
+       (convert_arg_to_ellipsis, convert_for_arg_passing): Don't fold.
+       (build_new_op_1, build_over_call, build_cxx_call): Fold for warnings.
+       * class.c (build_base_path, determine_primary_bases)
+       (update_vtable_entry_for_fn, check_bitfield_decl)
+       (layout_nonempty_base_or_field, layout_empty_base)
+       (propagate_binfo_offsets, include_empty_classes)
+       (layout_class_type, build_vbase_offset_vtbl_entries): Use
+       fold_convert.
+       * constexpr.c (cxx_eval_builtin_function_call): Fold away the NOP_EXPR.
+       (cxx_eval_call_expression): Handle MEM_REF.
+       (cxx_eval_pointer_plus_expression): Fold the second operand.
+       (cxx_eval_constant_expression): Handle MEM_REF, UNARY_PLUS_EXPR.
+       (fold_simple_1, fold_simple): New.
+       (maybe_constant_value_1): Factor out from maybe_constant_value.
+       (cv_cache, maybe_constant_value): Cache results.
+       (maybe_constant_init): Handle null input.
+       (potential_constant_expression_1): Handle RESULT_DECL, EMPTY_CLASS_EXPR.
+       * cp-array-notation.c (build_array_notation_ref): Fold operands.
+       * cp-gimplify.c (cp_fold_r, cp_fold): New.
+       (cp_genericize_r): Use fold_convert.  Don't fold SIZEOF_EXPR.
+       (cp_genericize): Fold everything.
+       (contains_label_1, contains_label_p): New.
+       (cp_fold, cp_fully_fold): New.
+       * cp-tree.h (class cache_map): New.
+       * cvt.c (cp_convert_to_pointer, ocp_convert): Use convert_to_*_nofold.
+       (cp_convert_and_check): Use cp_fully_fold.
+       (convert, convert_force): Don't fold.
+       * decl.c (fold_sizeof_expr): Change from fold_sizeof_expr_r.
+       (compute_array_index_type): Use cp_fully_fold.
+       (build_enumerator): Use fold_convert.
+       * decl2.c (get_guard_cond, set_guard): Use fold_convert.
+       * init.c (build_zero_init_1): Fold zero-initializers.
+       (build_new_1): Fold nelts calculations.
+       (build_vec_delete_1): Fold conversions.
+       (build_vec_init): Fold maxindex.
+       * parser.c (cp_parser_binary_expression): Fold LHS of || and &&.
+       (cp_parser_question_colon_clause): Fold LHS.
+       * pt.c (convert_nontype_argument): Fold nullptr conversion.
+       * semantics.c (finish_unary_op_expr): Fold for warnings.
+       (handle_omp_array_sections_1): Fold length and low bound.
+       (handle_omp_for_class_iterator): Fold various things.
+       * tree.c (builtin_valid_in_constant_expr_p): Add
+       BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE.
+       (convert_bitfield_to_declared_type): Don't fold.
+       (handle_init_priority_attribute): Fold.
+       (fold_if_not_in_template): Remove.
+       * typeck.c (decay_conversion, build_class_member_access_expr)
+       (build_simple_component_ref, cp_build_array_ref, build_vec_cmp)
+       (cp_pointer_int_sum, pointer_diff): Don't fold.
+       (cp_build_binary_op): Fold for warnings and PMF ops.
+       (cp_build_unary_op): Fold negation of a constant, nothing else.
+       (expand_ptrmemfunc_cst): Fold operations.
+       * typeck2.c (split_nonconstant_init): Fold initializer.
+       (store_init_value): Likewise.
+       (check_narrowing): Try folding.
+       * config-lang.in (gtfiles): Add cp-gimplify.c.
+
 2015-11-13  David Malcolm  <dmalcolm@redhat.com>
 
        * error.c (pedwarn_cxx98): Pass line_table to rich_location ctor.
index a860e461ddd6ae584abfea7d1394dfd9efc0f452..77c29366b1351c1cd93e2c09717f9ef5e1cd3179 100644 (file)
@@ -4748,7 +4748,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
          tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
          arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
        }
-      return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+      return build3_loc (loc, VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
     }
 
   /* [expr.cond]
@@ -5152,9 +5152,6 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 
  valid_operands:
   result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
-  if (!cp_unevaluated_operand)
-    /* Avoid folding within decltype (c++/42013) and noexcept.  */
-    result = fold_if_not_in_template (result);
 
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
@@ -5690,8 +5687,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
                 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);
+                                      code_orig_arg1, fold (arg1),
+                                      code_orig_arg2, fold (arg2));
 
              arg2 = convert_like (conv, arg2, complain);
            }
@@ -5729,7 +5726,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
     case TRUTH_OR_EXPR:
       if (complain & tf_warning)
        warn_logical_operator (loc, code, boolean_type_node,
-                              code_orig_arg1, arg1, code_orig_arg2, arg2);
+                              code_orig_arg1, fold (arg1),
+                              code_orig_arg2, fold (arg2));
       /* Fall through.  */
     case GT_EXPR:
     case LT_EXPR:
@@ -5740,9 +5738,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
       if ((complain & tf_warning)
          && ((code_orig_arg1 == BOOLEAN_TYPE)
              ^ (code_orig_arg2 == BOOLEAN_TYPE)))
-       maybe_warn_bool_compare (loc, code, arg1, arg2);
+       maybe_warn_bool_compare (loc, code, fold (arg1),
+                                fold (arg2));
       if (complain & tf_warning && warn_tautological_compare)
-       warn_tautological_cmp (loc, code, arg1, arg2);
+       warn_tautological_cmp (loc, code, fold (arg1), fold (arg2));
       /* Fall through.  */
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -6496,7 +6495,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          imag = perform_implicit_conversion (TREE_TYPE (totype),
                                              imag, complain);
          expr = build2 (COMPLEX_EXPR, totype, real, imag);
-         return fold_if_not_in_template (expr);
+         return expr;
        }
       expr = reshape_init (totype, expr, complain);
       expr = get_target_expr_sfinae (digest_init (totype, expr, complain),
@@ -6737,7 +6736,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
                    "implicit conversion from %qT to %qT when passing "
                    "argument to function",
                    arg_type, double_type_node);
-      arg = convert_to_real (double_type_node, arg);
+      arg = convert_to_real_nofold (double_type_node, arg);
     }
   else if (NULLPTR_TYPE_P (arg_type))
     arg = null_pointer_node;
@@ -6982,7 +6981,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
   bitfield_type = is_bitfield_expr_with_lowered_type (val);
   if (bitfield_type 
       && TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
-    val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+    val = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type), val);
 
   if (val == error_mark_node)
     ;
@@ -7502,7 +7501,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   gcc_assert (j <= nargs);
   nargs = j;
 
-  check_function_arguments (TREE_TYPE (fn), nargs, argarray);
+  /* Avoid to do argument-transformation, if warnings for format, and for
+     nonnull are disabled.  Just in case that at least one of them is active
+     the check_function_arguments function might warn about something.  */
+
+  if (warn_nonnull || warn_format || warn_suggest_attribute_format)
+    {
+      tree *fargs = (!nargs ? argarray
+                           : (tree *) alloca (nargs * sizeof (tree)));
+      for (j = 0; j < nargs; j++)
+       fargs[j] = maybe_constant_value (argarray[j]);
+
+      check_function_arguments (TREE_TYPE (fn), nargs, fargs);
+    }
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
@@ -7693,7 +7704,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
                tsubst_flags_t complain)
 {
   tree fndecl;
-  int optimize_sav;
 
   /* Remember roughly where this call is.  */
   location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
@@ -7705,9 +7715,18 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
   /* Check that arguments to builtin functions match the expectations.  */
   if (fndecl
       && DECL_BUILT_IN (fndecl)
-      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-      && !check_builtin_function_arguments (fndecl, nargs, argarray))
-    return error_mark_node;
+      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      int i;
+
+      /* We need to take care that values to BUILT_IN_NORMAL
+         are reduced.  */
+      for (i = 0; i < nargs; i++)
+       argarray[i] = maybe_constant_value (argarray[i]);
+
+      if (!check_builtin_function_arguments (fndecl, nargs, argarray))
+       return error_mark_node;
+    }
 
     /* If it is a built-in array notation function, then the return type of
      the function is the element type of the array passed in as array 
@@ -7741,17 +7760,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
        }
     }
 
-  /* Some built-in function calls will be evaluated at compile-time in
-     fold ().  Set optimize to 1 when folding __builtin_constant_p inside
-     a constexpr function so that fold_builtin_1 doesn't fold it to 0.  */
-  optimize_sav = optimize;
-  if (!optimize && fndecl && DECL_IS_BUILTIN_CONSTANT_P (fndecl)
-      && current_function_decl
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    optimize = 1;
-  fn = fold_if_not_in_template (fn);
-  optimize = optimize_sav;
-
   if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
 
index 866e342145d2b914d13119466d6e4b37d9250a6a..216a30141d486755a2479c6472dd72fc1475d45b 100644 (file)
@@ -421,7 +421,7 @@ build_base_path (enum tree_code code,
 
          t = TREE_TYPE (TYPE_VFIELD (current_class_type));
          t = build_pointer_type (t);
-         v_offset = convert (t, current_vtt_parm);
+         v_offset = fold_convert (t, current_vtt_parm);
          v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
        }
       else
@@ -554,8 +554,6 @@ build_simple_base_path (tree expr, tree binfo)
        expr = build3 (COMPONENT_REF,
                       cp_build_qualified_type (type, type_quals),
                       expr, field, NULL_TREE);
-       expr = fold_if_not_in_template (expr);
-
        /* Mark the expression const or volatile, as appropriate.
           Even though we've dealt with the type above, we still have
           to mark the expression itself.  */
@@ -1847,9 +1845,9 @@ determine_primary_bases (tree t)
                 another hierarchy. As we're about to use it as a
                 primary base, make sure the offsets match.  */
              delta = size_diffop_loc (input_location,
-                                  convert (ssizetype,
+                                  fold_convert (ssizetype,
                                            BINFO_OFFSET (base_binfo)),
-                                  convert (ssizetype,
+                                  fold_convert (ssizetype,
                                            BINFO_OFFSET (this_primary)));
 
              propagate_binfo_offsets (this_primary, delta);
@@ -1911,7 +1909,7 @@ determine_primary_bases (tree t)
             another hierarchy. As we're about to use it as a primary
             base, make sure the offsets match.  */
          delta = size_diffop_loc (input_location, ssize_int (0),
-                              convert (ssizetype, BINFO_OFFSET (primary)));
+                              fold_convert (ssizetype, BINFO_OFFSET (primary)));
 
          propagate_binfo_offsets (primary, delta);
        }
@@ -2635,7 +2633,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
          if (virtual_offset
              || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
            {
-             tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
+             tree offset = fold_convert (ssizetype, BINFO_OFFSET (thunk_binfo));
 
              if (virtual_offset)
                {
@@ -2643,7 +2641,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
                     offset to be from there.  */
                  offset = 
                    size_diffop (offset,
-                                convert (ssizetype,
+                                fold_convert (ssizetype,
                                          BINFO_OFFSET (virtual_offset)));
                }
              if (fixed_offset)
@@ -2732,8 +2730,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
     /* The `this' pointer needs to be adjusted from the declaration to
        the nearest virtual base.  */
     delta = size_diffop_loc (input_location,
-                        convert (ssizetype, BINFO_OFFSET (virtual_base)),
-                        convert (ssizetype, BINFO_OFFSET (first_defn)));
+                        fold_convert (ssizetype, BINFO_OFFSET (virtual_base)),
+                        fold_convert (ssizetype, BINFO_OFFSET (first_defn)));
   else if (lost)
     /* If the nearest definition is in a lost primary, we don't need an
        entry in our vtable.  Except possibly in a constructor vtable,
@@ -2745,9 +2743,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
        BINFO to pointing at the base where the final overrider
        appears.  */
     delta = size_diffop_loc (input_location,
-                        convert (ssizetype,
+                        fold_convert (ssizetype,
                                  BINFO_OFFSET (TREE_VALUE (overrider))),
-                        convert (ssizetype, BINFO_OFFSET (binfo)));
+                        fold_convert (ssizetype, BINFO_OFFSET (binfo)));
 
   modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
 
@@ -3469,7 +3467,7 @@ check_bitfield_decl (tree field)
 
   if (w != error_mark_node)
     {
-      DECL_SIZE (field) = convert (bitsizetype, w);
+      DECL_SIZE (field) = fold_convert (bitsizetype, w);
       DECL_BIT_FIELD (field) = 1;
       return true;
     }
@@ -4314,8 +4312,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
        OFFSET.  */
     propagate_binfo_offsets (binfo,
                             size_diffop_loc (input_location,
-                                         convert (ssizetype, offset),
-                                         convert (ssizetype,
+                                         fold_convert (ssizetype, offset),
+                                         fold_convert (ssizetype,
                                                   BINFO_OFFSET (binfo))));
 }
 
@@ -4362,7 +4360,7 @@ layout_empty_base (record_layout_info rli, tree binfo,
       /* That didn't work.  Now, we move forward from the next
         available spot in the class.  */
       atend = true;
-      propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
+      propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc));
       while (1)
        {
          if (!layout_conflict_p (binfo,
@@ -5976,9 +5974,9 @@ propagate_binfo_offsets (tree binfo, tree offset)
 
   /* Update BINFO's offset.  */
   BINFO_OFFSET (binfo)
-    = convert (sizetype,
+    = fold_convert (sizetype,
               size_binop (PLUS_EXPR,
-                          convert (ssizetype, BINFO_OFFSET (binfo)),
+                          fold_convert (ssizetype, BINFO_OFFSET (binfo)),
                           offset));
 
   /* Find the primary base class.  */
@@ -6183,7 +6181,7 @@ include_empty_classes (record_layout_info rli)
        = size_binop (PLUS_EXPR,
                      rli->bitpos,
                      size_binop (MULT_EXPR,
-                                 convert (bitsizetype,
+                                 fold_convert (bitsizetype,
                                           size_binop (MINUS_EXPR,
                                                       eoc, rli_size)),
                                  bitsize_int (BITS_PER_UNIT)));
@@ -6457,7 +6455,7 @@ layout_class_type (tree t, tree *virtuals_p)
       eoc = end_of_class (t, /*include_virtuals_p=*/0);
       TYPE_SIZE_UNIT (base_t)
        = size_binop (MAX_EXPR,
-                     convert (sizetype,
+                     fold_convert (sizetype,
                               size_binop (CEIL_DIV_EXPR,
                                           rli_size_so_far (rli),
                                           bitsize_int (BITS_PER_UNIT))),
@@ -6466,7 +6464,7 @@ layout_class_type (tree t, tree *virtuals_p)
        = size_binop (MAX_EXPR,
                      rli_size_so_far (rli),
                      size_binop (MULT_EXPR,
-                                 convert (bitsizetype, eoc),
+                                 fold_convert (bitsizetype, eoc),
                                  bitsize_int (BITS_PER_UNIT)));
       TYPE_ALIGN (base_t) = rli->record_align;
       TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
@@ -9302,7 +9300,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
       /* Figure out where we can find this vbase offset.  */
       delta = size_binop (MULT_EXPR,
                          vid->index,
-                         convert (ssizetype,
+                         fold_convert (ssizetype,
                                   TYPE_SIZE_UNIT (vtable_entry_type)));
       if (vid->primary_vtbl_p)
        BINFO_VPTR_FIELD (b) = delta;
index 357abdc292b695a2518341fdafd9e05c9cdb76ae..ba841dfef7711fced9dcfc6231d11228090e1cc1 100644 (file)
@@ -29,4 +29,4 @@ compilers="cc1plus\$(exeext)"
 
 target_libs="target-libstdc++-v3"
 
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c"
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c"
index 159c4b308f4589fa3bbe18c1991e6c2f9f561589..aabb980915459ef1b7bd4657ee486361661ed65b 100644 (file)
@@ -1035,6 +1035,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
   force_folding_builtin_constant_p = true;
   new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
                                        CALL_EXPR_FN (t), nargs, args);
+  /* Fold away the NOP_EXPR from fold_builtin_n.  */
+  new_call = fold (new_call);
   force_folding_builtin_constant_p = save_ffbcp;
   VERIFY_CONSTANT (new_call);
   return new_call;
@@ -1275,6 +1277,16 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       ctx->values->put (new_ctx.object, ctor);
       ctx = &new_ctx;
     }
+  else if (DECL_BY_REFERENCE (DECL_RESULT (fun))
+          && TREE_CODE (t) != AGGR_INIT_EXPR)
+    {
+      /* convert_to_void stripped our AGGR_INIT_EXPR, in which case we don't
+        care about a constant value.  ??? we could still optimize away the
+        call.  */
+      gcc_assert (ctx->quiet && !ctx->object);
+      *non_constant_p = true;
+      return t;
+    }
 
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
@@ -2540,6 +2552,17 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
   tree orig_op0 = TREE_OPERAND (t, 0);
   bool empty_base = false;
 
+  /* We can handle a MEM_REF like an INDIRECT_REF, if MEM_REF's second
+     operand is an integer-zero.  Otherwise reject the MEM_REF for now.  */
+
+  if (TREE_CODE (t) == MEM_REF
+      && (!TREE_OPERAND (t, 1) || !integer_zerop (TREE_OPERAND (t, 1))))
+    {
+      gcc_assert (ctx->quiet);
+      *non_constant_p = true;
+      return t;
+    }
+
   /* First try to simplify it directly.  */
   tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0,
                                  &empty_base);
@@ -3073,6 +3096,8 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
   if (TREE_CODE (op00) != ADDR_EXPR)
     return NULL_TREE;
 
+  op01 = cxx_eval_constant_expression (ctx, op01, lval,
+                                      non_constant_p, overflow_p);
   op00 = TREE_OPERAND (op00, 0);
 
   /* &A[i] p+ j => &A[i + j] */
@@ -3333,6 +3358,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       /* These differ from cxx_eval_unary_expression in that this doesn't
         check for a constant operand or result; an address can be
         constant without its operand being, and vice versa.  */
+    case MEM_REF:
     case INDIRECT_REF:
       r = cxx_eval_indirect_ref (ctx, t, lval,
                                 non_constant_p, overflow_p);
@@ -3370,17 +3396,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case SIZEOF_EXPR:
-      if (SIZEOF_EXPR_TYPE_P (t))
-       r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
-                                       SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (t, 0)))
-       r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
-                                       false);
-      else
-       r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
-                                       false);
-      if (r == error_mark_node)
-       r = size_one_node;
+      r = fold_sizeof_expr (t);
       VERIFY_CONSTANT (r);
       break;
 
@@ -3538,8 +3554,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
     case NOP_EXPR:
+    case UNARY_PLUS_EXPR:
       {
+       enum tree_code tcode = TREE_CODE (t);
        tree oldop = TREE_OPERAND (t, 0);
+
        tree op = cxx_eval_constant_expression (ctx, oldop,
                                                lval,
                                                non_constant_p, overflow_p);
@@ -3559,11 +3578,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
            *non_constant_p = true;
            return t;
          }
-       if (op == oldop)
+       if (op == oldop && tcode != UNARY_PLUS_EXPR)
          /* We didn't fold at the top so we could check for ptr-int
             conversion.  */
          return fold (t);
-       r = fold_build1 (TREE_CODE (t), type, op);
+       if (tcode == UNARY_PLUS_EXPR)
+         r = fold_convert (TREE_TYPE (t), op);
+       else
+         r = fold_build1 (tcode, type, op);
        /* Conversion of an out-of-range value has implementation-defined
           behavior; the language considers it different from arithmetic
           overflow, which is undefined.  */
@@ -3831,12 +3853,86 @@ cxx_constant_value (tree t, tree decl)
   return cxx_eval_outermost_constant_expr (t, false, true, decl);
 }
 
+/* Helper routine for fold_simple function.  Either return simplified
+   expression T, otherwise NULL_TREE.
+   In contrast to cp_fully_fold, and to maybe_constant_value, we try to fold
+   even if we are within template-declaration.  So be careful on call, as in
+   such case types can be undefined.  */
+
+static tree
+fold_simple_1 (tree t)
+{
+  tree op1;
+  enum tree_code code = TREE_CODE (t);
+
+  switch (code)
+    {
+    case INTEGER_CST:
+    case REAL_CST:
+    case VECTOR_CST:
+    case FIXED_CST:
+    case COMPLEX_CST:
+      return t;
+
+    case SIZEOF_EXPR:
+      return fold_sizeof_expr (t);
+
+    case ABS_EXPR:
+    case CONJ_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case NOP_EXPR:
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case ADDR_SPACE_CONVERT_EXPR:
+
+      op1 = TREE_OPERAND (t, 0);
+
+      t = const_unop (code, TREE_TYPE (t), op1);
+      if (!t)
+       return NULL_TREE;
+
+      if (CONVERT_EXPR_CODE_P (code)
+         && TREE_OVERFLOW_P (t) && !TREE_OVERFLOW_P (op1))
+       TREE_OVERFLOW (t) = false;
+      return t;
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* If T is a simple constant expression, returns its simplified value.
+   Otherwise returns T.  In contrast to maybe_constant_value do we
+   simplify only few operations on constant-expressions, and we don't
+   try to simplify constexpressions.  */
+
+tree
+fold_simple (tree t)
+{
+  tree r = NULL_TREE;
+  if (processing_template_decl)
+    return t;
+
+  r = fold_simple_1 (t);
+  if (!r)
+    r = t;
+
+  return r;
+}
+
 /* If T is a constant expression, returns its reduced value.
    Otherwise, if T does not have TREE_CONSTANT set, returns T.
    Otherwise, returns a version of T without TREE_CONSTANT.  */
 
-tree
-maybe_constant_value (tree t, tree decl)
+static tree
+maybe_constant_value_1 (tree t, tree decl)
 {
   tree r;
 
@@ -3862,6 +3958,24 @@ maybe_constant_value (tree t, tree decl)
   return r;
 }
 
+static GTY((cache, deletable)) cache_map cv_cache;
+
+/* If T is a constant expression, returns its reduced value.
+   Otherwise, if T does not have TREE_CONSTANT set, returns T.
+   Otherwise, returns a version of T without TREE_CONSTANT.  */
+
+tree
+maybe_constant_value (tree t, tree decl)
+{
+  tree ret = cv_cache.get (t);
+  if (!ret)
+    {
+      ret = maybe_constant_value_1 (t, decl);
+      cv_cache.put (t, ret);
+    }
+  return ret;
+}
+
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
@@ -3927,6 +4041,8 @@ fold_non_dependent_expr (tree t)
 tree
 maybe_constant_init (tree t, tree decl)
 {
+  if (!t)
+    return t;
   if (TREE_CODE (t) == EXPR_STMT)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CONVERT_EXPR
@@ -4037,6 +4153,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
     case FIELD_DECL:
     case PARM_DECL:
+    case RESULT_DECL:
     case USING_DECL:
     case USING_STMT:
     case PLACEHOLDER_EXPR:
@@ -4625,6 +4742,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see these in statement-expressions.  */
       return true;
 
+    case EMPTY_CLASS_EXPR:
+      return false;
+
     default:
       if (objc_is_property_ref (t))
        return false;
index d44505425b6215d9ec15b20c67c3666bc17eb491..84d79258fdbbecb7ae85cf3f19b6cb30e9b55d89 100644 (file)
@@ -1380,7 +1380,12 @@ build_array_notation_ref (location_t loc, tree array, tree start, tree length,
     
   if (!stride) 
     stride = build_one_cst (ptrdiff_type_node);
-  
+
+  stride = maybe_constant_value (stride);
+  length = maybe_constant_value (length);
+  if (start)
+    start = maybe_constant_value (start);
+
   /* When dealing with templates, triplet type-checking will be done in pt.c 
      after type substitution.  */
   if (processing_template_decl 
index 2b77e75e183fadec577fb3170234de3a1bb4ce99..5f5cd367f58830ad7b7e5b22306e7d31c0596f0f 100644 (file)
@@ -36,7 +36,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Forward declarations.  */
 
 static tree cp_genericize_r (tree *, int *, void *);
+static tree cp_fold_r (tree *, int *, void *);
 static void cp_genericize_tree (tree*);
+static tree cp_fold (tree);
 
 /* Local declarations.  */
 
@@ -914,6 +916,71 @@ struct cp_genericize_data
   bool no_sanitize_p;
 };
 
+/* Perform any pre-gimplification folding of C++ front end trees to
+   GENERIC.
+   Note:  The folding of none-omp cases is something to move into
+     the middle-end.  As for now we have most foldings only on GENERIC
+     in fold-const, we need to perform this before transformation to
+     GIMPLE-form.  */
+
+static tree
+cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+  tree stmt;
+  enum tree_code code;
+
+  *stmt_p = stmt = cp_fold (*stmt_p);
+
+  code = TREE_CODE (stmt);
+  if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE
+      || code == OMP_TASKLOOP || code == CILK_FOR || code == CILK_SIMD)
+    {
+      tree x;
+      int i, n;
+
+      cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
+      x = OMP_FOR_COND (stmt);
+      if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
+       {
+         cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
+         cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
+       }
+      else if (x && TREE_CODE (x) == TREE_VEC)
+       {
+         n = TREE_VEC_LENGTH (x);
+         for (i = 0; i < n; i++)
+           {
+             tree o = TREE_VEC_ELT (x, i);
+             if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
+               cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+           }
+       }
+      x = OMP_FOR_INCR (stmt);
+      if (x && TREE_CODE (x) == TREE_VEC)
+       {
+         n = TREE_VEC_LENGTH (x);
+         for (i = 0; i < n; i++)
+           {
+             tree o = TREE_VEC_ELT (x, i);
+             if (o && TREE_CODE (o) == MODIFY_EXPR)
+               o = TREE_OPERAND (o, 1);
+             if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
+                       || TREE_CODE (o) == POINTER_PLUS_EXPR))
+               {
+                 cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
+                 cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+               }
+           }
+       }
+      cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
+      *walk_subtrees = 0;
+    }
+
+  return NULL;
+}
+
 /* Perform any pre-gimplification lowering of C++ front end trees to
    GENERIC.  */
 
@@ -973,7 +1040,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       if (__builtin_expect (wtd->omp_ctx != NULL, 0)
          && omp_var_to_track (TREE_OPERAND (stmt, 0)))
        omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
-      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
+      *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
       *walk_subtrees = 0;
     }
   else if (TREE_CODE (stmt) == RETURN_EXPR
@@ -1288,22 +1355,6 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
           || TREE_CODE (stmt) == OMP_DISTRIBUTE
           || TREE_CODE (stmt) == OMP_TASKLOOP)
     genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
-  else if (TREE_CODE (stmt) == SIZEOF_EXPR)
-    {
-      if (SIZEOF_EXPR_TYPE_P (stmt))
-       *stmt_p
-         = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
-                                       SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (stmt, 0)))
-       *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
-                                             SIZEOF_EXPR, false);
-      else
-       *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
-                                             SIZEOF_EXPR, false);
-      if (*stmt_p == error_mark_node)
-       *stmt_p = size_one_node;
-      return NULL;
-    }
   else if ((flag_sanitize
            & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
           && !wtd->no_sanitize_p)
@@ -1414,6 +1465,10 @@ cp_genericize (tree fndecl)
 {
   tree t;
 
+  /* Fold ALL the trees!  FIXME we should be able to remove this, but
+     apparently that still causes optimization regressions.  */
+  cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, NULL, NULL);
+
   /* Fix up the types of parms passed by invisible reference.  */
   for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
@@ -1777,3 +1832,402 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
         && DECL_LANG_SPECIFIC (decl)
         && DECL_OMP_PRIVATIZED_MEMBER (decl);
 }
+
+/* Callback for walk_tree, looking for LABEL_EXPR.  Return *TP if it is
+   a LABEL_EXPR; otherwise return NULL_TREE.  Do not check the subtrees
+   of GOTO_EXPR.  */
+
+static tree
+contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+  switch (TREE_CODE (*tp))
+    {
+    case LABEL_EXPR:
+      return *tp;
+
+    case GOTO_EXPR:
+      *walk_subtrees = 0;
+
+      /* ... fall through ...  */
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* Return whether the sub-tree ST contains a label which is accessible from
+   outside the sub-tree.  */
+
+static bool
+contains_label_p (tree st)
+{
+  return
+   walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE;
+}
+
+/* Perform folding on expression X.  */
+
+tree
+cp_fully_fold (tree x)
+{
+  return cp_fold (x);
+}
+
+static GTY((cache, deletable)) cache_map fold_cache;
+
+/*  This function tries to fold an expression X.
+    To avoid combinatorial explosion, folding results are kept in fold_cache.
+    If we are processing a template or X is invalid, we don't fold at all.
+    For performance reasons we don't cache expressions representing a
+    declaration or constant.
+    Function returns X or its folded variant.  */
+
+static tree
+cp_fold (tree x)
+{
+  tree op0, op1, op2, op3;
+  tree org_x = x, r = NULL_TREE;
+  enum tree_code code;
+  location_t loc;
+
+  if (!x || error_operand_p (x))
+    return x;
+
+  if (processing_template_decl
+      || (EXPR_P (x) && !TREE_TYPE (x)))
+    return x;
+
+  /* Don't bother to cache DECLs or constants.  */
+  if (DECL_P (x) || CONSTANT_CLASS_P (x))
+    return x;
+
+  if (tree cached = fold_cache.get (x))
+    return cached;
+
+  code = TREE_CODE (x);
+  switch (code)
+    {
+    case SIZEOF_EXPR:
+      x = fold_sizeof_expr (x);
+      break;
+
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case NOP_EXPR:
+    case NON_LVALUE_EXPR:
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+       return x;
+
+      if (!TREE_OPERAND (x, 0)
+         || TREE_CODE (TREE_OPERAND (x, 0)) == NON_LVALUE_EXPR)
+       return x;
+
+      loc = EXPR_LOCATION (x);
+      op0 = TREE_OPERAND (x, 0);
+
+      if (TREE_CODE (x) == NOP_EXPR
+         && TREE_OVERFLOW_P (op0)
+         && TREE_TYPE (x) == TREE_TYPE (op0))
+       return x;
+
+      op0 = cp_fold (op0);
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      /* Conversion of an out-of-range value has implementation-defined
+        behavior; the language considers it different from arithmetic
+        overflow, which is undefined.  */
+      if (TREE_CODE (op0) == INTEGER_CST
+         && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
+       TREE_OVERFLOW (x) = false;
+
+      break;
+
+    case SAVE_EXPR:
+    case ADDR_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case CONJ_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FLOAT_EXPR:
+    case NEGATE_EXPR:
+    case ABS_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case UNARY_PLUS_EXPR:
+    case INDIRECT_REF:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0));
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      gcc_assert (TREE_CODE (x) != COND_EXPR
+                 || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
+      break;
+
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case INIT_EXPR:
+
+       loc = EXPR_LOCATION (x);
+       op0 = cp_fold (TREE_OPERAND (x, 0));
+       op1 = cp_fold (TREE_OPERAND (x, 1));
+
+       if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1)
+         x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+       break;
+
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case COMPOUND_EXPR:
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_XOR_EXPR:
+    case LT_EXPR: case LE_EXPR:
+    case GT_EXPR: case GE_EXPR:
+    case EQ_EXPR: case NE_EXPR:
+    case UNORDERED_EXPR: case ORDERED_EXPR:
+    case UNLT_EXPR: case UNLE_EXPR:
+    case UNGT_EXPR: case UNGE_EXPR:
+    case UNEQ_EXPR: case LTGT_EXPR:
+    case RANGE_EXPR: case COMPLEX_EXPR:
+    case MODIFY_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0));
+      op1 = cp_fold (TREE_OPERAND (x, 1));
+      if ((code == COMPOUND_EXPR || code == MODIFY_EXPR)
+         && ((op1 && TREE_SIDE_EFFECTS (op1))
+              || (op0 && TREE_SIDE_EFFECTS (op0))))
+       break;
+      if (TREE_CODE (x) == COMPOUND_EXPR && !op0)
+       op0 = build_empty_stmt (loc);
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
+       x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+      x = fold (x);
+
+      if (TREE_CODE (x) == COMPOUND_EXPR && TREE_OPERAND (x, 0) == NULL_TREE
+         && TREE_OPERAND (x, 1))
+       return TREE_OPERAND (x, 1);
+      break;
+
+    case VEC_COND_EXPR:
+    case COND_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0));
+
+      if (TREE_SIDE_EFFECTS (op0))
+       break;
+
+      op1 = cp_fold (TREE_OPERAND (x, 1));
+      op2 = cp_fold (TREE_OPERAND (x, 2));
+
+      if (TREE_CODE (op0) == INTEGER_CST)
+       {
+         tree un;
+
+         if (integer_zerop (op0))
+           {
+             un = op1;
+             r = op2;
+           }
+         else
+           {
+             un = op2;
+             r = op1;
+           }
+
+          if ((!TREE_SIDE_EFFECTS (un) || !contains_label_p (un))
+              && (! VOID_TYPE_P (TREE_TYPE (r)) || VOID_TYPE_P (x)))
+            {
+             if (CAN_HAVE_LOCATION_P (r)
+                 && EXPR_LOCATION (r) != loc
+                 && !(TREE_CODE (r) == SAVE_EXPR
+                      || TREE_CODE (r) == TARGET_EXPR
+                      || TREE_CODE (r) == BIND_EXPR))
+               {
+                 r = copy_node (r);
+                 SET_EXPR_LOCATION (r, loc);
+               }
+             x = r;
+           }
+
+         break;
+       }
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+       break;
+
+      x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+
+      if (code != COND_EXPR)
+       x = fold (x);
+
+      break;
+
+    case CALL_EXPR:
+      {
+       int i, m, sv = optimize, nw = sv, changed = 0;
+       tree callee = get_callee_fndecl (x);
+
+       if (callee && DECL_BUILT_IN (callee) && !optimize
+           && DECL_IS_BUILTIN_CONSTANT_P (callee)
+           && current_function_decl
+           && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+         nw = 1;
+       optimize = nw;
+       r = fold (x);
+       optimize = sv;
+
+       if (TREE_CODE (r) != CALL_EXPR)
+         {
+           x = cp_fold (r);
+           break;
+         }
+
+       x = copy_node (x);
+
+       m = call_expr_nargs (x);
+       for (i = 0; i < m; i++)
+         {
+           r = cp_fold (CALL_EXPR_ARG (x, i));
+           if (r != CALL_EXPR_ARG (x, i))
+             changed = 1;
+           CALL_EXPR_ARG (x, i) = r;
+         }
+
+       optimize = nw;
+       r = fold (x);
+       optimize = sv;
+
+       if (TREE_CODE (r) != CALL_EXPR)
+         {
+           x = cp_fold (r);
+           break;
+         }
+
+       optimize = nw;
+
+       /* Invoke maybe_constant_value for functions being declared
+          constexpr, and are no AGGR_INIT_EXPRs ...
+          TODO:
+          Due issues in maybe_constant_value for CALL_EXPR with
+          arguments passed by reference, it is disabled.  */
+       if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
+          r = maybe_constant_value (x);
+       optimize = sv;
+
+        if (TREE_CODE (r) != CALL_EXPR)
+         {
+           x = r;
+           break;
+         }
+
+       if (!changed)
+         x = org_x;
+       break;
+      }
+
+    case CONSTRUCTOR:
+      {
+       unsigned i;
+       constructor_elt *p;
+       vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
+       FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+         p->value = cp_fold (p->value);
+       break;
+      }
+    case TREE_VEC:
+      {
+       bool changed = false;
+       vec<tree, va_gc> *vec = make_tree_vector ();
+       int i, n = TREE_VEC_LENGTH (x);
+       vec_safe_reserve (vec, n);
+
+       for (i = 0; i < n; i++)
+         {
+           tree op = cp_fold (TREE_VEC_ELT (x, i));
+           vec->quick_push (op);
+           if (op != TREE_VEC_ELT (x, i))
+             changed = true;
+         }
+
+       if (changed)
+         {
+           r = copy_node (x);
+           for (i = 0; i < n; i++)
+             TREE_VEC_ELT (r, i) = (*vec)[i];
+           x = r;
+         }
+
+       release_tree_vector (vec);
+      }
+
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0));
+      op1 = cp_fold (TREE_OPERAND (x, 1));
+      op2 = cp_fold (TREE_OPERAND (x, 2));
+      op3 = cp_fold (TREE_OPERAND (x, 3));
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)
+         || op2 != TREE_OPERAND (x, 2) || op3 != TREE_OPERAND (x, 3))
+       x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
+
+      x = fold (x);
+      break;
+
+    default:
+      return org_x;
+    }
+
+  fold_cache.put (org_x, x);
+  /* Prevent that we try to fold an already folded result again.  */
+  if (x != org_x)
+    fold_cache.put (x, x);
+
+  return x;
+}
+
+#include "gt-cp-cp-gimplify.h"
index 828f2682fab97895d37860d8b343dfb5fcf1b9e9..84437b4a8277503fcbe64e6909aa5532a4da2d8d 100644 (file)
@@ -5447,6 +5447,42 @@ extern cp_parameter_declarator *no_parameters;
 /* True if we saw "#pragma GCC java_exceptions".  */
 extern bool pragma_java_exceptions;
 
+/* Data structure for a mapping from tree to tree that's only used as a cache;
+   we don't GC-mark trees in the map, and we clear the map when collecting
+   garbage.  Global variables of this type must be marked
+   GTY((cache,deletable)) so that the gt_cleare_cache function is called by
+   ggc_collect but we don't try to load the map pointer from a PCH.
+
+   FIXME improve to use keep_cache_entry.  */
+class cache_map
+{
+  /* Use a lazily initialized pointer rather than a map member since a
+     hash_map can't be constructed in a static initializer.  */
+  hash_map<tree, tree> *map;
+
+public:
+  tree get (tree key)
+  {
+    if (map)
+      if (tree *slot = map->get (key))
+       return *slot;
+    return NULL_TREE;
+  }
+
+  bool put (tree key, tree val)
+  {
+    if (!map)
+      map = new hash_map<tree, tree>;
+    return map->put (key, val);
+  }
+
+  friend inline void gt_cleare_cache (cache_map &cm)
+  {
+    if (cm.map)
+      cm.map->empty();
+  }
+};
+
 /* in call.c */
 extern bool check_dtor_name                    (tree, tree);
 bool magic_varargs_p                            (tree);
@@ -6474,7 +6510,6 @@ extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
        walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
 #define cp_walk_tree_without_duplicates(tp,func,data) \
        walk_tree_without_duplicates_1 (tp, func, data, cp_walk_subtrees)
-extern tree fold_if_not_in_template            (tree);
 extern tree rvalue                             (tree);
 extern tree convert_bitfield_to_declared_type   (tree);
 extern tree cp_save_expr                       (tree);
@@ -6705,6 +6740,7 @@ extern tree cxx_omp_clause_dtor                   (tree, tree);
 extern void cxx_omp_finish_clause              (tree, gimple_seq *);
 extern bool cxx_omp_privatize_by_reference     (const_tree);
 extern bool cxx_omp_disregard_value_expr       (tree, bool);
+extern tree cp_fully_fold                      (tree);
 
 /* in name-lookup.c */
 extern void suggest_alternatives_for            (location_t, tree);
@@ -6796,12 +6832,14 @@ extern tree cxx_constant_value                  (tree, tree = NULL_TREE);
 extern tree maybe_constant_value               (tree, tree = NULL_TREE);
 extern tree maybe_constant_init                        (tree, tree = NULL_TREE);
 extern tree fold_non_dependent_expr            (tree);
+extern tree fold_simple                                (tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
 extern bool is_instantiation_of_constexpr       (tree);
 extern bool var_in_constexpr_fn                 (tree);
 extern void explain_invalid_constexpr_fn        (tree);
 extern vec<tree> cx_error_context               (void);
+extern tree fold_sizeof_expr                   (tree);
 
 /* In c-family/cilk.c */
 extern bool cilk_valid_spawn                    (tree);
index c6e13f3f570f8c6a0f66182b3c61901a603a01a7..0231efc95279b3f22f56e5244be9a535b61dea3a 100644 (file)
@@ -50,7 +50,7 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
 
    Here is a list of all the functions that assume that widening and
    narrowing is always done with a NOP_EXPR:
-     In convert.c, convert_to_integer.
+     In convert.c, convert_to_integer[_nofold].
      In c-typeck.c, build_binary_op_nodefault (boolean ops),
        and c_common_truthvalue_conversion.
      In expr.c: expand_expr, for operands of a MULT_EXPR.
@@ -237,7 +237,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
       gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
                  == GET_MODE_SIZE (TYPE_MODE (type)));
 
-      return convert_to_pointer (type, expr);
+      return convert_to_pointer_nofold (type, expr);
     }
 
   if (type_unknown_p (expr))
@@ -630,22 +630,25 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
 
   if (TREE_TYPE (expr) == type)
     return expr;
-  
+  if (expr == error_mark_node)
+    return expr;
   result = cp_convert (type, expr, complain);
 
   if ((complain & tf_warning)
       && c_inhibit_evaluation_warnings == 0)
     {
-      tree folded = maybe_constant_value (expr);
-      tree stripped = folded;
-      tree folded_result
-       = folded != expr ? cp_convert (type, folded, complain) : result;
-
-      /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a
-        NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
-      STRIP_NOPS (stripped);
-
-      if (!TREE_OVERFLOW_P (stripped)
+      tree folded = cp_fully_fold (expr);
+      tree folded_result;
+      if (folded == expr)
+       folded_result = result;
+      else
+       {
+         /* Avoid bogus -Wparentheses warnings.  */
+         TREE_NO_WARNING (folded) = true;
+         folded_result = cp_convert (type, folded, tf_none);
+       }
+      folded_result = fold_simple (folded_result);
+      if (!TREE_OVERFLOW_P (folded)
          && folded_result != error_mark_node)
        warnings_for_convert_and_check (input_location, type, folded,
                                        folded_result);
@@ -703,9 +706,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* For complex data types, we need to perform componentwise
         conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-       return fold_if_not_in_template (convert_to_complex (type, e));
+       return convert_to_complex_nofold (type, e);
       else if (VECTOR_TYPE_P (type))
-       return fold_if_not_in_template (convert_to_vector (type, e));
+       return convert_to_vector (type, e);
       else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -718,7 +721,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
          /* We shouldn't be treating objects of ADDRESSABLE type as
             rvalues.  */
          gcc_assert (!TREE_ADDRESSABLE (type));
-         return fold_if_not_in_template (build_nop (type, e));
+         return build_nop (type, e);
        }
     }
 
@@ -796,7 +799,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
          return cp_truthvalue_conversion (e);
        }
 
-      converted = fold_if_not_in_template (convert_to_integer (type, e));
+      converted = convert_to_integer_nofold (type, e);
 
       /* Ignore any integer overflow caused by the conversion.  */
       return ignore_overflows (converted, e);
@@ -808,7 +811,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       return nullptr_node;
     }
   if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain));
+    return cp_convert_to_pointer (type, e, complain);
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -823,7 +826,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
                      in_vtype, type);
          return error_mark_node;
        }
-      return fold_if_not_in_template (convert_to_vector (type, e));
+      return convert_to_vector (type, e);
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
@@ -839,9 +842,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
                      TREE_TYPE (e));
        }
       if (code == REAL_TYPE)
-       return fold_if_not_in_template (convert_to_real (type, e));
+       return convert_to_real_nofold (type, e);
       else if (code == COMPLEX_TYPE)
-       return fold_if_not_in_template (convert_to_complex (type, e));
+       return convert_to_complex_nofold (type, e);
     }
 
   /* New C++ semantics:  since assignment is now based on
@@ -1454,7 +1457,7 @@ convert (tree type, tree expr)
   intype = TREE_TYPE (expr);
 
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
@@ -1472,13 +1475,11 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
   enum tree_code code = TREE_CODE (type);
 
   if (code == REFERENCE_TYPE)
-    return (fold_if_not_in_template
-           (convert_to_reference (type, e, CONV_C_CAST, 0,
-                                  NULL_TREE, complain)));
+    return convert_to_reference (type, e, CONV_C_CAST, 0,
+                                NULL_TREE, complain);
 
   if (code == POINTER_TYPE)
-    return fold_if_not_in_template (convert_to_pointer_force (type, e,
-                                                             complain));
+    return convert_to_pointer_force (type, e, complain);
 
   /* From typeck.c convert_for_assignment */
   if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR
index 383b47d29edd9de2a5631e01088a1558e0f55d31..675342efcd9f0ac31df18d9e6f51d484ba2ed785 100644 (file)
@@ -8589,33 +8589,24 @@ stabilize_vla_size (tree size)
   cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
 }
 
-/* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
-   not inside of SAVE_EXPR and fold them.  */
+/* Reduce a SIZEOF_EXPR to its value.  */
 
-static tree
-fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
-{
-  tree expr = *expr_p;
-  if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
-    *walk_subtrees = 0;
-  else if (TREE_CODE (expr) == SIZEOF_EXPR)
-    {
-      *(bool *)data = true;
-      if (SIZEOF_EXPR_TYPE_P (expr))
-       expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
-                                          SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (expr, 0)))
-       expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-                                          false);
-      else
-        expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-                                          false);
-      if (expr == error_mark_node)
-        expr = size_one_node;
-      *expr_p = expr;
-      *walk_subtrees = 0;
-    }
-  return NULL;
+tree
+fold_sizeof_expr (tree t)
+{
+  tree r;
+  if (SIZEOF_EXPR_TYPE_P (t))
+    r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+                                   SIZEOF_EXPR, false);
+  else if (TYPE_P (TREE_OPERAND (t, 0)))
+    r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+                                   false);
+  else
+    r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+                                   false);
+  if (r == error_mark_node)
+    r = size_one_node;
+  return r;
 }
 
 /* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8708,7 +8699,18 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
       SET_TYPE_STRUCTURAL_EQUALITY (itype);
       return itype;
     }
-  
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      tree folded = cp_fully_fold (size);
+      if (TREE_CODE (folded) == INTEGER_CST)
+       pedwarn (location_of (size), OPT_Wpedantic,
+                "size of array is not an integral constant-expression");
+      /* Use the folded result for VLAs, too; it will have resolved
+        SIZEOF_EXPR.  */
+      size = folded;
+    }
+
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
@@ -8795,7 +8797,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
                                  cp_convert (ssizetype, integer_one_node,
                                              complain),
                                  complain);
-      itype = fold (itype);
+      itype = maybe_constant_value (itype);
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
@@ -8803,18 +8805,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
          /* A variable sized array.  */
          itype = variable_size (itype);
 
-         if (TREE_CODE (itype) != SAVE_EXPR)
-           {
-             /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
-                they might survive till gimplification.  */
-             tree newitype = itype;
-             bool found = false;
-             cp_walk_tree_without_duplicates (&newitype,
-                                              fold_sizeof_expr_r, &found);
-             if (found)
-               itype = variable_size (fold (newitype));
-           }
-
          stabilize_vla_size (itype);
 
          if (flag_sanitize & SANITIZE_VLA
@@ -13514,7 +13504,7 @@ incremented enumerator value is too large for %<long%>");
                   "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
 
           /* Convert the value to the appropriate type.  */
-          value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
+          value = fold_convert (ENUM_UNDERLYING_TYPE (enumtype), value);
         }
     }
 
index 149f8a1c04917d4f40160e6fe75c410de8bc521c..47c9ec96d24fa497fb7e30c1ade92955cb05c0f5 100644 (file)
@@ -3112,7 +3112,7 @@ get_guard_cond (tree guard, bool thread_safe)
     {
       guard_value = integer_one_node;
       if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-       guard_value = convert (TREE_TYPE (guard), guard_value);
+       guard_value = fold_convert (TREE_TYPE (guard), guard_value);
       guard = cp_build_binary_op (input_location,
                                  BIT_AND_EXPR, guard, guard_value,
                                  tf_warning_or_error);
@@ -3120,7 +3120,7 @@ get_guard_cond (tree guard, bool thread_safe)
 
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-    guard_value = convert (TREE_TYPE (guard), guard_value);
+    guard_value = fold_convert (TREE_TYPE (guard), guard_value);
   return cp_build_binary_op (input_location,
                             EQ_EXPR, guard, guard_value,
                             tf_warning_or_error);
@@ -3138,7 +3138,7 @@ set_guard (tree guard)
   guard = get_guard_bits (guard);
   guard_init = integer_one_node;
   if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
-    guard_init = convert (TREE_TYPE (guard), guard_init);
+    guard_init = fold_convert (TREE_TYPE (guard), guard_init);
   return cp_build_modify_expr (guard, NOP_EXPR, guard_init, 
                               tf_warning_or_error);
 }
index 9e582d66e3eb2ebb5a5ae265689a93e51ce73724..fccd2896a87db3196db92352158cf15d867d39fb 100644 (file)
@@ -175,9 +175,9 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
        initialized are initialized to zero.  */
     ;
   else if (TYPE_PTR_OR_PTRMEM_P (type))
-    init = convert (type, nullptr_node);
+    init = fold (convert (type, nullptr_node));
   else if (SCALAR_TYPE_P (type))
-    init = convert (type, integer_zero_node);
+    init = fold (convert (type, integer_zero_node));
   else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
     {
       tree field;
@@ -2558,6 +2558,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       outer_nelts_from_type = true;
     }
 
+  /* Lots of logic below. depends on whether we have a constant number of
+     elements, so go ahead and fold it now.  */
+  if (outer_nelts)
+    outer_nelts = maybe_constant_value (outer_nelts);
+
   /* If our base type is an array, then make sure we know how many elements
      it has.  */
   for (elt_type = type;
@@ -2608,7 +2613,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
   /* Warn if we performed the (T[N]) to T[N] transformation and N is
      variable.  */
   if (outer_nelts_from_type
-      && !TREE_CONSTANT (maybe_constant_value (outer_nelts)))
+      && !TREE_CONSTANT (outer_nelts))
     {
       if (complain & tf_warning_or_error)
        {
@@ -2708,7 +2713,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
       max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
 
-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+      size = size_binop (MULT_EXPR, size, fold_convert (sizetype, nelts));
 
       if (TREE_CONSTANT (outer_nelts))
        {
@@ -2897,7 +2902,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
        {
          placement_expr = get_target_expr (placement_first);
          CALL_EXPR_ARG (alloc_call, 1)
-           = convert (TREE_TYPE (placement), placement_expr);
+           = fold_convert (TREE_TYPE (placement), placement_expr);
        }
 
       if (!member_new_p
@@ -3506,7 +3511,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   /* The below is short by the cookie size.  */
   virtual_size = size_binop (MULT_EXPR, size_exp,
-                            convert (sizetype, maxindex));
+                            fold_convert (sizetype, maxindex));
 
   tbase = create_temporary_var (ptype);
   tbase_init
@@ -3549,7 +3554,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
       /* The below is short by the cookie size.  */
       virtual_size = size_binop (MULT_EXPR, size_exp,
-                                convert (sizetype, maxindex));
+                                fold_convert (sizetype, maxindex));
 
       if (! TYPE_VEC_NEW_USES_COOKIE (type))
        /* no header */
@@ -3595,8 +3600,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
                      fold_build2_loc (input_location,
                                   NE_EXPR, boolean_type_node, base,
-                                  convert (TREE_TYPE (base),
-                                           nullptr_node)),
+                                  fold_convert (TREE_TYPE (base),
+                                                nullptr_node)),
                      body, integer_zero_node);
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -3718,6 +3723,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
+  maxindex = maybe_constant_value (maxindex);
   if (explicit_value_init_p)
     gcc_assert (!init);
 
@@ -3759,6 +3765,8 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex, complain);
+  maxindex = fold_simple (maxindex);
+
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
index 0c918ecfe886c55f30abf920af55545d3093f40b..4ca79830712e96ee4050a62fb69dfe3568533ad8 100644 (file)
@@ -6778,7 +6778,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
         2. ARRAY [ EXP : EXP ]
         3. ARRAY [ EXP : EXP : EXP ]  */
 
-      *init_index = cp_parser_expression (parser);     
+      *init_index = cp_parser_expression (parser);
       if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
        {  
          /* This indicates that we have a normal array expression.  */
@@ -8522,9 +8522,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
       /* For "false && x" or "true || x", x will never be executed;
         disable warnings while evaluating it.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-       c_inhibit_evaluation_warnings += current.lhs == truthvalue_false_node;
+       c_inhibit_evaluation_warnings +=
+         cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-       c_inhibit_evaluation_warnings += current.lhs == truthvalue_true_node;
+       c_inhibit_evaluation_warnings +=
+         cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       /* Extract another operand.  It may be the RHS of this expression
         or the LHS of a new, higher priority expression.  */
@@ -8571,9 +8573,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 
       /* Undo the disabling of warnings done above.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-       c_inhibit_evaluation_warnings -= current.lhs == truthvalue_false_node;
+       c_inhibit_evaluation_warnings -=
+         cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-       c_inhibit_evaluation_warnings -= current.lhs == truthvalue_true_node;
+       c_inhibit_evaluation_warnings -=
+         cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       if (warn_logical_not_paren
          && TREE_CODE_CLASS (current.tree_type) == tcc_comparison
@@ -8659,7 +8663,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 static tree
 cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
 {
-  tree expr;
+  tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr);
   tree assignment_expr;
   struct cp_token *token;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -8674,7 +8678,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
                "ISO C++ does not allow ?: with omitted middle operand");
       /* Implicit true clause.  */
       expr = NULL_TREE;
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+      c_inhibit_evaluation_warnings +=
+       folded_logical_or_expr == truthvalue_true_node;
       warn_for_omitted_condop (token->location, logical_or_expr);
     }
   else
@@ -8682,11 +8687,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
       bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
       parser->colon_corrects_to_scope_p = false;
       /* Parse the expression.  */
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+      c_inhibit_evaluation_warnings +=
+       folded_logical_or_expr == truthvalue_false_node;
       expr = cp_parser_expression (parser);
       c_inhibit_evaluation_warnings +=
-       ((logical_or_expr == truthvalue_true_node)
-        - (logical_or_expr == truthvalue_false_node));
+       ((folded_logical_or_expr == truthvalue_true_node)
+        - (folded_logical_or_expr == truthvalue_false_node));
       parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
     }
 
@@ -8694,7 +8700,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
   cp_parser_require (parser, CPP_COLON, RT_COLON);
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser);
-  c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
+  c_inhibit_evaluation_warnings -=
+    folded_logical_or_expr == truthvalue_true_node;
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (loc, logical_or_expr,
index f3b0cd059ded3173a986bbff57a0b9a8c914fabc..29046572b2cf8ac4f4f6367c0c5237467bb8012c 100644 (file)
@@ -6211,7 +6211,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
      to a non-type argument of "nullptr".  */
   if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
-    expr = convert (type, expr);
+    expr = fold_simple (convert (type, expr));
 
   /* In C++11, integral or enumeration non-type template arguments can be
      arbitrary constant expressions.  Pointer and pointer to
index db37e85e1415d1c310b10d6a1bfba03843fec245..67f8590f63865a44db4139f1d4371b52c4d2ae3b 100644 (file)
@@ -2562,9 +2562,26 @@ finish_unary_op_expr (location_t loc, enum tree_code code, tree expr,
                      tsubst_flags_t complain)
 {
   tree result = build_x_unary_op (loc, code, expr, complain);
-  if ((complain & tf_warning)
-      && TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
-    overflow_warning (input_location, result);
+  tree result_ovl, expr_ovl;
+
+  if (!(complain & tf_warning))
+    return result;
+
+  result_ovl = result;
+  expr_ovl = expr;
+
+  if (!processing_template_decl)
+    expr_ovl = cp_fully_fold (expr_ovl);
+
+  if (!CONSTANT_CLASS_P (expr_ovl)
+      || TREE_OVERFLOW_P (expr_ovl))
+    return result;
+
+  if (!processing_template_decl)
+    result_ovl = cp_fully_fold (result_ovl);
+
+  if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (input_location, result_ovl);
 
   return result;
 }
@@ -4476,6 +4493,11 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     low_bound = mark_rvalue_use (low_bound);
   if (length)
     length = mark_rvalue_use (length);
+  /* We need to reduce to real constant-values for checks below.  */
+  if (length)
+    length = fold_simple (length);
+  if (low_bound)
+    low_bound = fold_simple (low_bound);
   if (low_bound
       && TREE_CODE (low_bound) == INTEGER_CST
       && TYPE_PRECISION (TREE_TYPE (low_bound))
@@ -7440,6 +7462,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   if (init && EXPR_HAS_LOCATION (init))
     elocus = EXPR_LOCATION (init);
 
+  cond = cp_fully_fold (cond);
   switch (TREE_CODE (cond))
     {
     case GT_EXPR:
@@ -7475,6 +7498,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
                            ERROR_MARK, iter, ERROR_MARK, NULL,
                            tf_warning_or_error);
+  diff = cp_fully_fold (diff);
   if (error_operand_p (diff))
     return true;
   if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
@@ -7536,7 +7560,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
                  if (TREE_CODE (rhs) == MINUS_EXPR)
                    {
                      incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
-                     incr = fold_if_not_in_template (incr);
+                     incr = fold_simple (incr);
                    }
                  if (TREE_CODE (incr) != INTEGER_CST
                      && (TREE_CODE (incr) != NOP_EXPR
index bd5caf735bc72898e0bbe62a9286ba3c8ccdb1f9..d2db31a628a0c796d8c2a317560a5d1d0f3448e5 100644 (file)
@@ -303,9 +303,19 @@ xvalue_p (const_tree ref)
 bool
 builtin_valid_in_constant_expr_p (const_tree decl)
 {
-  /* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
-     in constant-expressions.  We may want to add other builtins later. */
-  return DECL_IS_BUILTIN_CONSTANT_P (decl);
+  if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)))
+    /* Not a built-in.  */
+    return false;
+  switch (DECL_FUNCTION_CODE (decl))
+    {
+    case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
+      /* These have constant results even if their operands are
+        non-constant.  */
+      return true;
+    default:
+      return false;
+    }
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
@@ -681,8 +691,8 @@ convert_bitfield_to_declared_type (tree expr)
 
   bitfield_type = is_bitfield_expr_with_lowered_type (expr);
   if (bitfield_type)
-    expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
-                              expr);
+    expr = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type),
+                                     expr);
   return expr;
 }
 
@@ -3479,10 +3489,13 @@ handle_init_priority_attribute (tree* node,
 
   STRIP_NOPS (initp_expr);
   initp_expr = default_conversion (initp_expr);
+  if (initp_expr)
+    initp_expr = maybe_constant_value (initp_expr);
 
   if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
     {
       error ("requested init_priority is not an integer constant");
+      cxx_constant_value (initp_expr);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -4257,26 +4270,6 @@ stabilize_init (tree init, tree *initp)
   return !TREE_SIDE_EFFECTS (init);
 }
 
-/* Like "fold", but should be used whenever we might be processing the
-   body of a template.  */
-
-tree
-fold_if_not_in_template (tree expr)
-{
-  /* In the body of a template, there is never any need to call
-     "fold".  We will call fold later when actually instantiating the
-     template.  Integral constant expressions in templates will be
-     evaluated via instantiate_non_dependent_expr, as necessary.  */
-  if (processing_template_decl)
-    return expr;
-
-  /* Fold C++ front-end specific tree codes.  */
-  if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
-    return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
-
-  return fold (expr);
-}
-
 /* Returns true if a cast to TYPE may appear in an integral constant
    expression.  */
 
index 90c95fb29770400fbf8183ef7e84e34aecade1e1..6541e97cca5efe67483decc94af4d6a8df5ec25a 100644 (file)
@@ -1945,8 +1945,6 @@ decay_conversion (tree exp,
 
   code = TREE_CODE (type);
 
-  /* FIXME remove for delayed folding.  */
-  exp = scalar_constant_value (exp);
   if (error_operand_p (exp))
     return error_mark_node;
 
@@ -2439,7 +2437,6 @@ build_class_member_access_expr (tree object, tree member,
 
       result = build3_loc (input_location, COMPONENT_REF, member_type,
                           object, member, NULL_TREE);
-      result = fold_if_not_in_template (result);
 
       /* Mark the expression const or volatile, as appropriate.  Even
         though we've dealt with the type above, we still have to mark the
@@ -2852,9 +2849,9 @@ build_simple_component_ref (tree object, tree member)
 {
   tree type = cp_build_qualified_type (TREE_TYPE (member),
                                       cp_type_quals (TREE_TYPE (object)));
-  return fold_build3_loc (input_location,
-                         COMPONENT_REF, type,
-                         object, member, NULL_TREE);
+  return build3_loc (input_location,
+                    COMPONENT_REF, type,
+                    object, member, NULL_TREE);
 }
 
 /* Return an expression for the MEMBER_NAME field in the internal
@@ -3173,8 +3170,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
        |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
        |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
-                                         complain);
+      ret = require_complete_type_sfinae (rval, complain);
       protected_set_expr_location (ret, loc);
       if (non_lvalue)
        ret = non_lvalue_loc (loc, ret);
@@ -3921,7 +3917,6 @@ build_vec_cmp (tree_code code, tree type,
   tree minus_one_vec = build_minus_one_cst (type);
   tree cmp_type = build_same_sized_truth_vector_type(type);
   tree cmp = build2 (code, cmp_type, arg0, arg1);
-  cmp = fold_if_not_in_template (cmp);
   return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
 }
 
@@ -3976,7 +3971,7 @@ cp_build_binary_op (location_t location,
      convert it to this type.  */
   tree final_type = 0;
 
-  tree result;
+  tree result, result_ovl;
   tree orig_type = NULL;
 
   /* Nonzero if this is an operation like MIN or MAX which can
@@ -4599,7 +4594,7 @@ cp_build_binary_op (location_t location,
              op0 = cp_build_binary_op (location,
                                        TRUTH_ANDIF_EXPR, e1, e2,
                                        complain);
-             op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); 
+             op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain);
            }
          else 
            {
@@ -4640,10 +4635,12 @@ cp_build_binary_op (location_t location,
            op1 = save_expr (op1);
 
          pfn0 = pfn_from_ptrmemfunc (op0);
+         pfn0 = cp_fully_fold (pfn0);
          /* Avoid -Waddress warnings (c++/64877).  */
          if (TREE_CODE (pfn0) == ADDR_EXPR)
            TREE_NO_WARNING (pfn0) = 1;
          pfn1 = pfn_from_ptrmemfunc (op1);
+         pfn1 = cp_fully_fold (pfn1);
          delta0 = delta_from_ptrmemfunc (op0);
          delta1 = delta_from_ptrmemfunc (op1);
          if (TARGET_PTRMEMFUNC_VBIT_LOCATION
@@ -4997,10 +4994,7 @@ cp_build_binary_op (location_t location,
                  gcc_unreachable();
                }
            }
-         real = fold_if_not_in_template (real);
-         imag = fold_if_not_in_template (imag);
          result = build2 (COMPLEX_EXPR, result_type, real, imag);
-         result = fold_if_not_in_template (result);
          return result;
        }
 
@@ -5028,20 +5022,12 @@ cp_build_binary_op (location_t location,
 
       if (short_compare)
        {
-         /* Don't write &op0, etc., because that would prevent op0
-            from being kept in a register.
-            Instead, make copies of the our local variables and
-            pass the copies by reference, then copy them back afterward.  */
-         tree xop0 = op0, xop1 = op1, xresult_type = result_type;
+         /* We call shorten_compare only for diagnostic-reason.  */
+         tree xop0 = fold_simple (op0), xop1 = fold_simple (op1),
+              xresult_type = result_type;
          enum tree_code xresultcode = resultcode;
-         tree val
-           = shorten_compare (location, &xop0, &xop1, &xresult_type,
+         shorten_compare (location, &xop0, &xop1, &xresult_type,
                               &xresultcode);
-         if (val != 0)
-           return cp_convert (boolean_type_node, val, complain);
-         op0 = xop0, op1 = xop1;
-         converted = 1;
-         resultcode = xresultcode;
        }
 
       if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
@@ -5060,9 +5046,9 @@ cp_build_binary_op (location_t location,
          tree oop1 = maybe_constant_value (orig_op1);
 
          if (TREE_CODE (oop0) != INTEGER_CST)
-           oop0 = orig_op0;
+           oop0 = cp_fully_fold (orig_op0);
          if (TREE_CODE (oop1) != INTEGER_CST)
-           oop1 = orig_op1;
+           oop1 = cp_fully_fold (orig_op1);
          warn_for_sign_compare (location, oop0, oop1, op0, op1, 
                                 result_type, resultcode);
        }
@@ -5117,18 +5103,30 @@ cp_build_binary_op (location_t location,
     }
 
   result = build2 (resultcode, build_type, op0, op1);
-  result = fold_if_not_in_template (result);
   if (final_type != 0)
     result = cp_convert (final_type, result, complain);
 
-  if (TREE_OVERFLOW_P (result) 
-      && !TREE_OVERFLOW_P (op0) 
-      && !TREE_OVERFLOW_P (op1))
-    overflow_warning (location, result);
-
   if (instrument_expr != NULL)
-    result = fold_build2 (COMPOUND_EXPR, TREE_TYPE (result),
-                         instrument_expr, result);
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
+                    instrument_expr, result);
+
+  if (!processing_template_decl)
+    {
+      op0 = cp_fully_fold (op0);
+      /* Only consider the second argument if the first isn't overflowed.  */
+      if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0))
+       return result;
+      op1 = cp_fully_fold (op1);
+      if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1))
+       return result;
+    }
+  else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1)
+          || TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1))
+    return result;
+
+  result_ovl = fold_build2 (resultcode, build_type, op0, op1);
+  if (TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (location, result_ovl);
 
   return result;
 }
@@ -5178,8 +5176,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop,
   complete_type (TREE_TYPE (res_type));
 
   return pointer_int_sum (input_location, resultcode, ptrop,
-                         fold_if_not_in_template (intop),
-                         complain & tf_warning_or_error);
+                         intop, complain & tf_warning_or_error);
 }
 
 /* Return a tree for the difference of pointers OP0 and OP1.
@@ -5255,7 +5252,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain)
 
   result = build2 (EXACT_DIV_EXPR, restype, op0,
                   cp_convert (restype, op1, complain));
-  return fold_if_not_in_template (result);
+  return result;
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -5771,6 +5768,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
            /* Make sure the result is not an lvalue: a unary plus or minus
               expression is always a rvalue.  */
            arg = rvalue (arg);
+
+           if (code == NEGATE_EXPR && CONSTANT_CLASS_P (arg))
+             /* Immediately fold negation of a constant.  */
+             return fold_build1 (code, TREE_TYPE (arg), arg);
          }
       }
       break;
@@ -5835,10 +5836,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       arg = build_real_imag_expr (input_location, code, arg);
-      if (arg == error_mark_node)
-       return arg;
-      else
-       return fold_if_not_in_template (arg);
+      return arg;
 
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -6005,7 +6003,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     {
       if (argtype == 0)
        argtype = TREE_TYPE (arg);
-      return fold_if_not_in_template (build1 (code, argtype, arg));
+      return build1 (code, argtype, arg);
     }
 
   if (complain & tf_error)
@@ -6999,7 +6997,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
     return rvalue (expr);
   else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
           || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
   else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
           || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
@@ -7027,7 +7025,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
       if (warn_strict_aliasing <= 2)
        strict_aliasing_warning (intype, type, sexpr);
 
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
           || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
@@ -7038,13 +7036,13 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
        warning (OPT_Wconditionally_supported,
                 "casting between pointer-to-function and pointer-to-object "
                 "is conditionally-supported");
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if (VECTOR_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_vector (type, expr));
+    return convert_to_vector (type, expr);
   else if (VECTOR_TYPE_P (intype)
           && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_integer (type, expr));
+    return convert_to_integer_nofold (type, expr);
   else
     {
       if (valid_p)
@@ -7896,8 +7894,7 @@ get_delta_difference (tree from, tree to,
       }
   }
 
-  return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
-                                                     result));
+  return convert_to_integer (ptrdiff_type_node, result);
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -8078,41 +8075,35 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
         fn; the call will do the opposite adjustment.  */
       tree orig_class = DECL_CONTEXT (fn);
       tree binfo = binfo_or_else (orig_class, fn_class);
-      *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-                      *delta, BINFO_OFFSET (binfo));
-      *delta = fold_if_not_in_template (*delta);
+      *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                           *delta, BINFO_OFFSET (binfo));
 
       /* We set PFN to the vtable offset at which the function can be
         found, plus one (unless ptrmemfunc_vbit_in_delta, in which
         case delta is shifted left, and then incremented).  */
       *pfn = DECL_VINDEX (fn);
-      *pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
-                    TYPE_SIZE_UNIT (vtable_entry_type));
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_build2 (MULT_EXPR, integer_type_node, *pfn,
+                         TYPE_SIZE_UNIT (vtable_entry_type));
 
       switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
        {
        case ptrmemfunc_vbit_in_pfn:
-         *pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
-                        integer_one_node);
-         *pfn = fold_if_not_in_template (*pfn);
+         *pfn = fold_build2 (PLUS_EXPR, integer_type_node, *pfn,
+                             integer_one_node);
          break;
 
        case ptrmemfunc_vbit_in_delta:
-         *delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
-                          *delta, integer_one_node);
-         *delta = fold_if_not_in_template (*delta);
-         *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-                          *delta, integer_one_node);
-         *delta = fold_if_not_in_template (*delta);
+         *delta = fold_build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+                               *delta, integer_one_node);
+         *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+                               *delta, integer_one_node);
          break;
 
        default:
          gcc_unreachable ();
        }
 
-      *pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_convert (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
     }
 }
 
index cfc76c456d0d1f7bc069a5477f470f0c564dd614..839091c565ec473e0864fb0597c5c089174b5298 100644 (file)
@@ -738,6 +738,7 @@ split_nonconstant_init (tree dest, tree init)
     init = TARGET_EXPR_INITIAL (init);
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
+      init = cp_fully_fold (init);
       code = push_stmt_list ();
       if (split_nonconstant_init_1 (dest, init))
        init = NULL_TREE;
@@ -828,6 +829,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
       TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
     }
+  value = cp_fully_fold (value);
 
   if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
     /* Handle aggregate NSDMI in non-constant initializers, too.  */
@@ -926,19 +928,35 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
        }
     }
 
+  bool almost_ok = ok;
+  if (!ok && !CONSTANT_CLASS_P (init) && (complain & tf_warning_or_error))
+    {
+      tree folded = cp_fully_fold (init);
+      if (TREE_CONSTANT (folded) && check_narrowing (type, folded, tf_none))
+       almost_ok = true;
+    }
+
   if (!ok)
     {
+      location_t loc = EXPR_LOC_OR_LOC (init, input_location);
       if (cxx_dialect == cxx98)
-       warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-                   "narrowing conversion of %qE from %qT to %qT inside { } "
-                   "is ill-formed in C++11", init, ftype, type);
-      else if (!TREE_CONSTANT (init))
+       {
+         if (complain & tf_warning)
+           warning_at (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+                       "from %qT to %qT inside { } is ill-formed in C++11",
+                       init, ftype, type);
+         ok = true;
+       }
+      else if (!CONSTANT_CLASS_P (init))
        {
          if (complain & tf_warning_or_error)
            {
-             pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-                      "narrowing conversion of %qE from %qT to %qT inside { }",
-                      init, ftype, type);
+             if (!almost_ok || pedantic)
+               pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+                        "from %qT to %qT inside { }", init, ftype, type);
+             if (pedantic && almost_ok)
+               inform (loc, " the expression has a constant value but is not "
+                       "a C++ constant-expression");
              ok = true;
            }
        }
@@ -946,7 +964,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
        {
          int savederrorcount = errorcount;
          global_dc->pedantic_errors = 1;
-         pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
+         pedwarn (loc, OPT_Wnarrowing,
                   "narrowing conversion of %qE from %qT to %qT "
                   "inside { }", init, ftype, type);
          if (errorcount == savederrorcount)
@@ -955,7 +973,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
        }
     }
 
-  return cxx_dialect == cxx98 || ok; 
+  return ok;
 }
 
 /* Process the initializer INIT for a variable of type TYPE, emitting
index 999d57ad8adf5892ae80e268907e4c937e608d82..7bec6306872c6908948d9523edca63620ba854f3 100644 (file)
@@ -1,3 +1,7 @@
+2015-11-13  Jason Merrill  <jason@redhat.com>
+
+       * config-lang.in (gtfiles): Add cp-gimplify.c.
+
 2015-11-11  Andrew MacLeod  <amacleod@redhat.com>
 
        * objcp-decl.c: Remove unused header files.
index 9b2cea75a95cab14f75c6775bd045b6fd2f11d58..5f3f4e09c8a696856cf99c0485f5ba58154463e5 100644 (file)
@@ -45,6 +45,6 @@ subdir_requires="objc cp"
 
 # This list is separated in two parts: the first one is identical to
 # the C++ one, the second one contains our ObjC++ additions.
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/except.c \$(srcdir)/cp/vtable-class-hierarchy.c \$(srcdir)/cp/constexpr.c \$(srcdir)/cp/cp-gimplify.c \
 \$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
 
index 5d803ade8d12860a21788a8ffcab5d419f4f151d..8f1403456086bc7397ed9a2d4408097ec2126983 100644 (file)
@@ -47,3 +47,5 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
index fc89af1ba4bf28971dba1fe02eaf51094b46df29..55523a531f570f939da3436e62e410b065430451 100644 (file)
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
index bf9b1a07bb78317bf0a67730b8a6cfb3b627bb91..1295b725569bdd3fbb1a51dcafc7f1161e1aa60e 100644 (file)
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
index 85fbd0e35253f3bd7f23623999a6d352bc08f7ef..3088220ffa738a010f4a0a65d48bae91242b7384 100644 (file)
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
index 1b9c3885e9242c207d3fac0d705fa936b741e9e6..a658ff15e49fedc355ee119931a97698e6ccbd81 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c } } } */
 /* { dg-options "-fdump-tree-original" } */
 /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
 
index 26c92937f4742564860ba01adf4ae01446a134df..a5e3c1f109d0741506f5753657709042cb85d794 100644 (file)
@@ -18,7 +18,7 @@ public:
   {
     /* I am surprised this is considered a constexpr */
     return *((Inner *)4);
-  } // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
+  } // { dg-error "reinterpret_cast" "" }
 };
 
 B B::instance;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr53792.C b/gcc/testsuite/g++.dg/cpp0x/pr53792.C
new file mode 100644 (file)
index 0000000..deb5c1a
--- /dev/null
@@ -0,0 +1,29 @@
+// PR c++/53792
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump "return 0" "optimized" } }
+
+struct entry {
+  char const* label;
+  int         value;
+};
+
+constexpr bool same(char const *x, char const *y) {
+  return !*x && !*y ? true
+    : /* default */    (*x == *y && same(x+1, y+1));
+}
+
+constexpr int keyToValue(char const *label, entry const *entries) {
+  return !entries->label ? entries->value
+       : same(entries->label, label) ? entries->value
+       : /*default*/                   keyToValue(label, entries+1);
+}
+
+constexpr entry foo[] = {{"Foo", 0}, {"Bar", 1}, {"FooBar", 2}, {0, -1}};
+
+int
+bar()
+{
+  int result = keyToValue("Foo", foo);
+  return result;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp b/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
new file mode 100644 (file)
index 0000000..afa7edb
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int f(void *) { return 0; }
+constexpr int f(...) { return 1; }
+constexpr int g1() { return f(0); }
+constexpr int g2(int n) { return f(n); }
+constexpr int g3(int n) { return f(n*0); }
+
+int main()
+{
+    static_assert(g1() == 0, "g1 failed");
+    static_assert(g2(0) == 1, "g2 failed");
+    static_assert(g3(0) == 1, "g3 failed");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
new file mode 100644 (file)
index 0000000..e340de4
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MIN; }
+
+int main()
+{
+  return -f(); // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
new file mode 100644 (file)
index 0000000..6b5dff8
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MAX; }
+
+int main()
+{
+  return f() + 2; // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
new file mode 100644 (file)
index 0000000..39b3557
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+
+#define MAK (fl < 0 ? 1 : (fl ? -1 : 0))
+
+int foo (int sz)
+{
+  if (MAK) return 1;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
new file mode 100644 (file)
index 0000000..fa91a4f
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+extern int arr[];
+
+#define MAK (fl < 0 ? 1 : (fl ? 2 : 0))
+
+int foo (int sz)
+{
+  unsigned i;
+  int r = 0;
+  for (i = 0; i < MAK; i++)
+    r += arr[i];
+  return r;
+}
+
index c8ec07d5107a46be9bc61199a1b695f2731dd869..0c5df6d29421cac0739e36708da6e14456c7dd24 100644 (file)
@@ -5,8 +5,8 @@
 
 template<typename T>
 void type_alignment(const T&) {
-  struct { char c; T t; } s;
-  SA((char*)&s.t - (char*)&s.c == 1);
+  struct { char c; T t; } s;
+  SA(__builtin_offsetof (S,t) - __builtin_offsetof (S,c) == 1);
 }
 
 template <class T> struct A { char c; T t; };
@@ -17,7 +17,8 @@ int main() {
 
   A<aligned> a;                        // { dg-warning "ignoring attributes" }
 
-  SA((char*)&a.t - (char*)&a.c == 1);
+  SA(  __builtin_offsetof (__typeof(a),t)
+     - __builtin_offsetof (__typeof(a),c) == 1);
 
   aligned z;
   type_alignment(z);           // { dg-warning "ignoring attributes" "" { xfail *-*-* } }
index 1468c0a7c06864ef7fb969f9b105313936c85692..23f3537c74555a50ccd36b7482c4a672c39b2f1f 100644 (file)
@@ -1,6 +1,7 @@
 // PR c++/27601
 // Origin: Patrik Hägglund  <patrik.hagglund@bredband.net>
 // { dg-do compile }
+// { dg-options "-Wno-pointer-arith" }
 
 struct bar {
   static int foo;
@@ -10,7 +11,7 @@ struct bar {
 int a = __builtin_offsetof(bar, foo);  // { dg-error "static data member" }
 int av = __builtin_offsetof(volatile bar, foo);  // { dg-error "static data member" }
 int b = __builtin_offsetof(bar, baz);  // { dg-error "member function" }
-int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "function" }
+int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "single identifier nor|member function" }
 int bv0 = __builtin_offsetof(volatile bar, baz[0]);  // { dg-error "function" }
 int c = __builtin_offsetof(bar, ~bar);  // { dg-error "member function" }
 
index dbc60b34e7b11573edaf274be538aef7ff3f9179..e1f31bccf7cf9b3ebacbe16cac76d3d6d912d91a 100644 (file)
@@ -1,9 +1,9 @@
 // { dg-do compile }
-// { dg-options "-fdump-tree-gimple" }
+// { dg-options "-fdump-tree-gimple -pedantic" }
 
 struct s { int x, y; };
 short offsets[1] = {
-  ((char*) &(((struct s*)16)->y) - (char *)16),
+  ((char*) &(((struct s*)16)->y) - (char *)16), // { dg-message "narrowing" "" { target c++11 } }
 };
 
 // This ensures that we get a dump whether or not the bug is present.
index dd37c8e609d93f3c235f095f5c46790b626d228b..7620833c9b8d3b4df5fb7393ef8cae8a2335422d 100644 (file)
@@ -10,7 +10,7 @@ void f(__SIZE_TYPE__) {
 
 int main()
 {
-  int* const savepos = sizeof(*savepos) ? 0 : 0;
+  int* const savepos = sizeof(*savepos) ? 0 : 0;  /* { dg-error "invalid conversion" "convert" { target c++11 }  } */
 
   f (sizeof (*savepos));
 
index 225dcae8214d9527238b2ad7922e538d03b48b46..eba0746ef2b43515e9b1bae02b73deff298ab765 100644 (file)
@@ -5,5 +5,5 @@ extern "C" double fabs (double);
 
 void foo (double x)
 {
-  fabs (x) (); // { dg-error "__builtin_abs" }
+  fabs (x) (); // { dg-error "function" }
 }
index 54343c502111f71322c0992073c12ccf0457d0af..e5e6a4fa338932eaf1fb2c730f0b602c3676e738 100644 (file)
@@ -8,6 +8,6 @@ void
 bar (int i, int j, double k)
 {
   foo (i && j) ();     // { dg-error "\\(\\(?i != 0\\)? \\&\\& \\(?j != 0\\)?\\)" }
-  foo (!i || !j) ();   // { dg-error "\\(\\(?i == 0\\)? \\|\\| \\(?j == 0\\)?\\)" }
-  foo (!i == !j) ();   // { dg-error "\\(\\(?i != 0\\)? \\^ \\(?j == 0\\)?\\)" }
+  foo (!i || !j) ();   // { dg-error "function" }
+  foo (!i == !j) ();   // { dg-error "function" }
 }
index fb2c8b7276de4710ff76c0a4b9c1a05614a5034b..ffe2728054bfec6f408fb13fe7a1ed99bc8616ad 100644 (file)
@@ -2,5 +2,5 @@
 
 void foo(__complex__ double x)
 {
-  __builtin_conj(x)(); // { dg-error "~x" }
+  __builtin_conj(x)(); // { dg-error "function" }
 }
index 355ed6133b4586103456c94cc826ca4cb485b2fe..3c833472d69b409963bbdabe19b2dd5f995462c1 100644 (file)
@@ -14,7 +14,7 @@ extern void bar (char *, char *);
 void
 foo (void)
 {
-  char g[(char *) &((struct S *) 0)->b - (char *) 0];
-  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];
+  char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
+  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];              // { dg-error "constant" "" { xfail *-*-* } }
   bar (g, h);
 }
index 946f2e615f5675e84130ffe81340429ddd856049..80147054e88801479c76d81adaa371056b43cd3e 100644 (file)
@@ -1,14 +1,10 @@
 /* { dg-do compile } */
 /* { dg-options "-fsanitize=integer-divide-by-zero" } */
 
-/* TODO: We expect an error on the invalid case here, because that
-   must be a constant-expression.  This will be fixed when we have
-   proper delayed folding.  */
-
 void
 foo (int i)
 {
   switch (i)
   case 0 * (1 / 0): /* { dg-warning "division by zero" } */
-    ;  /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */
+    ;  /* { dg-error "is not a constant.expression" "" { target *-*-* } 8 } */
 }
index 05e049e82ea9a6390e2f1b012e67f7095cdeba31..493a55c2b5ecaa0a31d1a2e101e2678bf713627c 100644 (file)
@@ -8,10 +8,10 @@ foo (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case 1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case 1 >> -1: /* { dg-error "operand of shift" "" } */
+    case -1 >> -1: /* { dg-error "operand of shift" "" } */
+    case 1 << -1: /* { dg-error "operand of shift" "" } */
+    case -1 << -1: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
@@ -23,8 +23,8 @@ bar (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case -1 >> 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case -1 >> 200: /* { dg-error "operand of shift" "" } */
+    case 1 << 200: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
index 7cd76e74c7afb26607a642dea6de959cb71d8bd3..a10e15b98118bed775db289475972957cd20bc64 100644 (file)
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -126,3 +126,11 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target *-*-* } 56 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 58 } */
+/* { dg-error "is not a constant expression" "const" { target *-*-* } 65 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 65 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
index 73c0e006f56c862d6ab89537264080fe46860f28..c73a28c3277aafb8f5f6316a19c38f9f776e0ca5 100644 (file)
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -56,7 +56,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
+/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -65,7 +65,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 67 }  */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 69 } */
       ;
@@ -128,3 +128,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 60 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 67 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
index 24b3959a03494ae0720128d917b49a610c2bf448..23a2585e5323dbc940f9b070f60b29c43fc31fe8 100644 (file)
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */
@@ -59,7 +59,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */
+/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 61 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -68,7 +68,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 70 } */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */
       ;
@@ -131,3 +131,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "invalid conversion from" "convert" { target c++11 } 63 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 34 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 70 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 34 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 34 } */
index ff1d0669b698d0137cdfaaceb1acf91fc4c0e157..96691d3a2cc8b39660e3648256ebe22d864bd364 100644 (file)
@@ -3,5 +3,5 @@
 void x()
 {
  int* p = 1==0;        // { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
-// { dg-error "cannot convert" "" { target c++11 } 5 } 
+// { dg-error "cannot convert" "" { target { c++11 } } 5 }
 }