OSDN Git Service

PR c/39556
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 7fc55e2..b2d2109 100644 (file)
@@ -110,7 +110,6 @@ static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
 static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
-static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree);
 \f
@@ -2286,8 +2285,8 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
           && ! TREE_PUBLIC (ref)
           && DECL_CONTEXT (ref) != current_function_decl)
-    pedwarn (loc, 0, "%qD is static but used in inline function %qD "
-            "which is not static", ref, current_function_decl);
+    record_inline_static (loc, current_function_decl, ref,
+                         csi_internal);
 
   return ref;
 }
@@ -2392,8 +2391,18 @@ c_expr_sizeof_type (struct c_type_name *t)
   ret.value = c_sizeof (type);
   ret.original_code = ERROR_MARK;
   ret.original_type = NULL;
-  if (type_expr && c_vla_type_p (type))
-    {
+  if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
+      && c_vla_type_p (type))
+    {
+      /* If the type is a [*] array, it is a VLA but is represented as
+        having a size of zero.  In such a case we must ensure that
+        the result of sizeof does not get folded to a constant by
+        c_fully_fold, because if the size is evaluated the result is
+        not constant and so constraints on zero or negative size
+        arrays must not be applied when this sizeof call is inside
+        another array declarator.  */
+      if (!type_expr)
+       type_expr = integer_zero_node;
       ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
                          type_expr, ret.value);
       C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
@@ -3210,6 +3219,9 @@ build_unary_op (location_t location,
        }
       arg = c_objc_common_truthvalue_conversion (location, arg);
       ret = invert_truthvalue (arg);
+      /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
+      if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
+       location = EXPR_LOCATION (ret);
       goto return_build_unary_op;
 
     case REALPART_EXPR:
@@ -3503,7 +3515,7 @@ build_unary_op (location_t location,
    Lvalues can be assigned, unless their type has TYPE_READONLY.
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
-static int
+bool
 lvalue_p (const_tree ref)
 {
   const enum tree_code code = TREE_CODE (ref);
@@ -4290,6 +4302,8 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
 }
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
+   If LHS_ORIGTYPE is not NULL, it is the original type of LHS, which
+   may differ from TREE_TYPE (LHS) for an enum bitfield.
    MODIFYCODE is the code for a binary operator that we use
    to combine the old value of LHS with RHS to get the new value.
    Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
@@ -4299,9 +4313,8 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
    LOCATION is the location of the MODIFYCODE operator.  */
 
 tree
-build_modify_expr (location_t location,
-                  tree lhs, enum tree_code modifycode, tree rhs,
-                  tree rhs_origtype)
+build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
+                  enum tree_code modifycode, tree rhs, tree rhs_origtype)
 {
   tree result;
   tree newrhs;
@@ -4331,7 +4344,8 @@ build_modify_expr (location_t location,
   if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
     {
       tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
-                                     modifycode, rhs, rhs_origtype);
+                                     lhs_origtype, modifycode, rhs,
+                                     rhs_origtype);
       if (inner == error_mark_node)
        return error_mark_node;
       result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
@@ -4391,6 +4405,23 @@ build_modify_expr (location_t location,
       TREE_TYPE (lhs) = lhstype;
     }
 
+  /* Issue -Wc++-compat warnings about an assignment to an enum type
+     when LHS does not have its original type.  This happens for,
+     e.g., an enum bitfield in a struct.  */
+  if (warn_cxx_compat
+      && lhs_origtype != NULL_TREE
+      && lhs_origtype != lhstype
+      && TREE_CODE (lhs_origtype) == ENUMERAL_TYPE)
+    {
+      tree checktype = (rhs_origtype != NULL_TREE
+                       ? rhs_origtype
+                       : TREE_TYPE (rhs));
+      if (checktype != error_mark_node
+         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
+       warning_at (location, OPT_Wc___compat,
+                   "enum conversion in assignment is invalid in C++");
+    }
+
   /* Convert new value to destination type.  Fold it first, then
      restore any excess precision information, for the sake of
      conversion warnings.  */
@@ -4551,9 +4582,9 @@ convert_for_assignment (tree type, tree rhs, tree origtype,
          && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
        {
          /* FIXME: Until the gcc source code is converted, we only
-            warn about parameter passing.  We will add the other
-            cases when bootstrap succeeds with them.  */
-         if (errtype == ic_argpass)
+            warn about assignment and parameter passing.  We will add
+            the other cases when bootstrap succeeds with them.  */
+         if (errtype == ic_argpass || errtype == ic_assign)
            {
              WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
                                   G_("enum conversion when passing argument "
@@ -6401,6 +6432,24 @@ set_init_index (tree first, tree last)
     }
 
   if (TREE_CODE (first) != INTEGER_CST)
+    {
+      first = c_fully_fold (first, false, NULL);
+      if (TREE_CODE (first) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_pedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (last && TREE_CODE (last) != INTEGER_CST)
+    {
+      last = c_fully_fold (last, false, NULL);
+      if (TREE_CODE (last) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_pedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (TREE_CODE (first) != INTEGER_CST)
     error_init ("nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
     error_init ("nonconstant array index in initializer");
@@ -7285,7 +7334,8 @@ process_init_element (struct c_expr value, bool implicit)
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
        process_init_element (pop_init_level (1), true);
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+      else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
+               || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
@@ -7357,7 +7407,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE))
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7448,7 +7498,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE))
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7489,7 +7539,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
-                      || eltcode == UNION_TYPE))
+                      || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7538,9 +7588,13 @@ process_init_element (struct c_expr value, bool implicit)
 
          /* Now output the actual element.  */
          if (value.value)
-           output_init_element (value.value, value.original_type,
-                                strict_string, elttype,
-                                constructor_index, 1, implicit);
+           {
+             if (TREE_CODE (value.value) == VECTOR_CST)
+               elttype = TYPE_MAIN_VARIANT (constructor_type);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, elttype,
+                                  constructor_index, 1, implicit);
+           }
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);