OSDN Git Service

* c-decl.c (finish_decl): Apply pending #pragma weak regardless of
[pf3gnuchains/gcc-fork.git] / gcc / gimplify.c
index 341ca7b..23713df 100644 (file)
@@ -1744,7 +1744,9 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
   decl = get_callee_fndecl (*expr_p);
   if (decl && DECL_BUILT_IN (decl))
     {
-      tree new = fold_builtin (*expr_p, !want_value);
+      tree fndecl = get_callee_fndecl (*expr_p);
+      tree arglist = TREE_OPERAND (*expr_p, 1);
+      tree new = fold_builtin (fndecl, arglist, !want_value);
 
       if (new && new != *expr_p)
        {
@@ -1758,8 +1760,6 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
          && DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
         {
-         tree arglist = TREE_OPERAND (*expr_p, 1);
-         
          if (!arglist || !TREE_CHAIN (arglist))
            {
              error ("too few arguments to function %<va_start%>");
@@ -1802,7 +1802,9 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
   /* Try this again in case gimplification exposed something.  */
   if (ret != GS_ERROR && decl && DECL_BUILT_IN (decl))
     {
-      tree new = fold_builtin (*expr_p, !want_value);
+      tree fndecl = get_callee_fndecl (*expr_p);
+      tree arglist = TREE_OPERAND (*expr_p, 1);
+      tree new = fold_builtin (fndecl, arglist, !want_value);
 
       if (new && new != *expr_p)
        {
@@ -2071,10 +2073,6 @@ gimple_boolify (tree expr)
   if (TREE_CODE (type) == BOOLEAN_TYPE)
     return expr;
 
-  /* If this is the predicate of a COND_EXPR, it might not even be a
-     truthvalue yet.  */
-  expr = lang_hooks.truthvalue_conversion (expr);
-
   switch (TREE_CODE (expr))
     {
     case TRUTH_AND_EXPR:
@@ -2123,7 +2121,8 @@ gimple_boolify (tree expr)
      *EXPR_P should be stored.  */
 
 static enum gimplify_status
-gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target)
+gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target,
+                   fallback_t fallback)
 {
   tree expr = *expr_p;
   tree tmp, tmp2, type;
@@ -2137,18 +2136,40 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target)
      the arms.  */
   else if (! VOID_TYPE_P (type))
     {
+      tree result;
+
       if (target)
        {
          ret = gimplify_expr (&target, pre_p, post_p,
                               is_gimple_min_lval, fb_lvalue);
          if (ret != GS_ERROR)
            ret = GS_OK;
-         tmp = target;
+         result = tmp = target;
          tmp2 = unshare_expr (target);
        }
+      else if ((fallback & fb_lvalue) == 0)
+       {
+         result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
+         ret = GS_ALL_DONE;
+       }
       else
        {
-         tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
+         tree type = build_pointer_type (TREE_TYPE (expr));
+
+         if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
+           TREE_OPERAND (expr, 1) =
+             build_fold_addr_expr (TREE_OPERAND (expr, 1));
+
+         if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
+           TREE_OPERAND (expr, 2) =
+             build_fold_addr_expr (TREE_OPERAND (expr, 2));
+         
+         tmp2 = tmp = create_tmp_var (type, "iftmp");
+
+         expr = build (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0),
+                       TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2));
+
+         result = build_fold_indirect_ref (tmp);
          ret = GS_ALL_DONE;
        }
 
@@ -2169,7 +2190,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target)
       /* Move the COND_EXPR to the prequeue.  */
       gimplify_and_add (expr, pre_p);
 
-      *expr_p = tmp;
+      *expr_p = result;
       return ret;
     }
 
@@ -2907,7 +2928,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
        if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
          {
            *expr_p = *from_p;
-           return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p);
+           return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p,
+                                      fb_rvalue);
          }
        else
          ret = GS_UNHANDLED;
@@ -3786,11 +3808,30 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          break;
 
        case COND_EXPR:
-         ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE);
+         ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE,
+                                   fallback);
+         /* C99 code may assign to an array in a structure value of a
+            conditional expression, and this has undefined behavior
+            only on execution, so create a temporary if an lvalue is
+            required.  */
+         if (fallback == fb_lvalue)
+           {
+             *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
+             lang_hooks.mark_addressable (*expr_p);
+           }
          break;
 
        case CALL_EXPR:
          ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
+         /* C99 code may assign to an array in a structure returned
+            from a function, and this has undefined behavior only on
+            execution, so create a temporary if an lvalue is
+            required.  */
+         if (fallback == fb_lvalue)
+           {
+             *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
+             lang_hooks.mark_addressable (*expr_p);
+           }
          break;
 
        case TREE_LIST:
@@ -4041,12 +4082,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
 
        case WITH_SIZE_EXPR:
          {
-           enum gimplify_status r0, r1;
-           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
-                               post_p == &internal_post ? NULL : post_p,
-                               gimple_test_f, fallback);
-           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
-                               is_gimple_val, fb_rvalue);
+           gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                          post_p == &internal_post ? NULL : post_p,
+                          gimple_test_f, fallback);
+           gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
+                          is_gimple_val, fb_rvalue);
          }
          break;
 
@@ -4388,7 +4428,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
 {
   /* We don't do anything if the value isn't there, is constant, or contains
      A PLACEHOLDER_EXPR.  We also don't want to do anything if it's already
-     a VAR_DECL.  If it's a VAR_DECL from another function, the gimplfier
+     a VAR_DECL.  If it's a VAR_DECL from another function, the gimplifier
      will want to replace it with a new variable, but that will cause problems
      if this type is from outside the function.  It's OK to have that here.  */
   if (*expr_p == NULL_TREE || TREE_CONSTANT (*expr_p)