OSDN Git Service

PR middle-end/24998
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 4b1f9e7..82fe613 100644 (file)
@@ -340,7 +340,7 @@ int flag_gen_declaration;
 
 int print_struct_values;
 
-/* ???.  Undocumented.  */
+/* Tells the compiler what is the constant string class for Objc.  */
 
 const char *constant_string_class_name;
 
@@ -520,6 +520,7 @@ static tree handle_section_attribute (tree *, tree, tree, int, bool *);
 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
+static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_visibility_attribute (tree *, tree, tree, int,
                                         bool *);
 static tree handle_tls_model_attribute (tree *, tree, tree, int,
@@ -599,6 +600,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_weak_attribute },
   { "alias",                  1, 1, true,  false, false,
                              handle_alias_attribute },
+  { "weakref",                0, 1, true,  false, false,
+                             handle_weakref_attribute },
   { "no_instrument_function", 0, 0, true,  false, false,
                              handle_no_instrument_function_attribute },
   { "malloc",                 0, 0, true,  false, false,
@@ -951,6 +954,42 @@ unsigned_conversion_warning (tree result, tree operand)
     }
 }
 
+/* Print a warning about casts that might indicate violation
+   of strict aliasing rules if -Wstrict-aliasing is used and
+   strict aliasing mode is in effect. otype is the original
+   TREE_TYPE of expr, and type the type we're casting to. */
+
+void
+strict_aliasing_warning(tree otype, tree type, tree expr)
+{
+  if (flag_strict_aliasing && warn_strict_aliasing
+      && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
+      && TREE_CODE (expr) == ADDR_EXPR
+      && (DECL_P (TREE_OPERAND (expr, 0))
+          || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
+      && !VOID_TYPE_P (TREE_TYPE (type)))
+    {
+      /* Casting the address of an object to non void pointer. Warn
+         if the cast breaks type based aliasing.  */
+      if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+        warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+                 "might break strict-aliasing rules");
+      else
+        {
+          HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+          HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+
+          if (!alias_sets_conflict_p (set1, set2))
+            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+                     "pointer will break strict-aliasing rules");
+          else if (warn_strict_aliasing > 1
+                  && !alias_sets_might_conflict_p (set1, set2))
+            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+                     "pointer might break strict-aliasing rules");
+        }
+    }
+}
+
 /* Nonzero if constant C has a value that is permissible
    for type TYPE (an INTEGER_TYPE).  */
 
@@ -972,6 +1011,8 @@ vector_types_convertible_p (tree t1, tree t2)
   return targetm.vector_opaque_p (t1)
         || targetm.vector_opaque_p (t2)
          || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+            && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE || 
+                TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
             && INTEGRAL_TYPE_P (TREE_TYPE (t1))
                == INTEGRAL_TYPE_P (TREE_TYPE (t2)));
 }
@@ -3586,25 +3627,27 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
     {
       low_value = check_case_value (low_value);
       low_value = convert_and_check (type, low_value);
+      if (low_value == error_mark_node)
+       goto error_out;
     }
   if (high_value)
     {
       high_value = check_case_value (high_value);
       high_value = convert_and_check (type, high_value);
+      if (high_value == error_mark_node)
+       goto error_out;
     }
 
-  /* If an error has occurred, bail out now.  */
-  if (low_value == error_mark_node || high_value == error_mark_node)
-    goto error_out;
-
-  /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
-     really a case range, even though it was written that way.  Remove
-     the HIGH_VALUE to simplify later processing.  */
-  if (tree_int_cst_equal (low_value, high_value))
-    high_value = NULL_TREE;
-  if (low_value && high_value
-      && !tree_int_cst_lt (low_value, high_value))
-    warning (0, "empty range specified");
+  if (low_value && high_value)
+    {
+      /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+         really a case range, even though it was written that way.
+         Remove the HIGH_VALUE to simplify later processing.  */
+      if (tree_int_cst_equal (low_value, high_value))
+       high_value = NULL_TREE;
+      else if (!tree_int_cst_lt (low_value, high_value))
+       warning (0, "empty range specified");
+    }
 
   /* See if the case is in range of the type of the original testing
      expression.  If both low_value and high_value are out of range,
@@ -4307,39 +4350,43 @@ handle_transparent_union_attribute (tree *node, tree name,
                                    tree ARG_UNUSED (args), int flags,
                                    bool *no_add_attrs)
 {
-  tree decl = NULL_TREE;
-  tree *type = NULL;
-  int is_type = 0;
+  tree type = NULL;
+
+  *no_add_attrs = true;
 
   if (DECL_P (*node))
     {
-      decl = *node;
-      type = &TREE_TYPE (decl);
-      is_type = TREE_CODE (*node) == TYPE_DECL;
+      if (TREE_CODE (*node) != TYPE_DECL)
+       goto ignored;
+      node = &TREE_TYPE (*node);
+      type = *node;
     }
   else if (TYPE_P (*node))
-    type = node, is_type = 1;
+    type = *node;
+  else
+    goto ignored;
 
-  if (is_type
-      && TREE_CODE (*type) == UNION_TYPE
-      && (decl == 0
-         || (TYPE_FIELDS (*type) != 0
-             && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
+  if (TREE_CODE (type) == UNION_TYPE)
     {
+      /* When IN_PLACE is set, leave the check for FIELDS and MODE to
+        the code in finish_struct.  */
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *type = build_variant_type_copy (*type);
-      TYPE_TRANSPARENT_UNION (*type) = 1;
-    }
-  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
-          && TREE_CODE (*type) == UNION_TYPE
-          && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
-    DECL_TRANSPARENT_UNION (decl) = 1;
-  else
-    {
-      warning (OPT_Wattributes, "%qE attribute ignored", name);
-      *no_add_attrs = true;
+       {
+         if (TYPE_FIELDS (type) == NULL_TREE
+             || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type)))
+           goto ignored;
+
+         /* A type variant isn't good enough, since we don't a cast
+            to such a type removed as a no-op.  */
+         *node = type = build_duplicate_type (type);
+       }
+
+      TYPE_TRANSPARENT_UNION (type) = 1;
+      return NULL_TREE;
     }
 
+ ignored:
+  warning (OPT_Wattributes, "%qE attribute ignored", name);
   return NULL_TREE;
 }
 
@@ -4734,7 +4781,10 @@ handle_alias_attribute (tree *node, tree name, tree args,
        DECL_INITIAL (decl) = error_mark_node;
       else
        {
-         DECL_EXTERNAL (decl) = 0;
+         if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+           DECL_EXTERNAL (decl) = 1;
+         else
+           DECL_EXTERNAL (decl) = 0;
          TREE_STATIC (decl) = 1;
        }
     }
@@ -4747,6 +4797,40 @@ handle_alias_attribute (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 
+/* Handle a "weakref" attribute; arguments as in struct
+   attribute_spec.handler.  */
+
+static tree
+handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+                         int flags, bool *no_add_attrs)
+{
+  tree attr = NULL_TREE;
+
+  /* The idea here is that `weakref("name")' mutates into `weakref,
+     alias("name")', and weakref without arguments, in turn,
+     implicitly adds weak. */
+
+  if (args)
+    {
+      attr = tree_cons (get_identifier ("alias"), args, attr);
+      attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
+
+      *no_add_attrs = true;
+    }
+  else
+    {
+      if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
+       error ("%Jweakref attribute must appear before alias attribute",
+              *node);
+
+      attr = tree_cons (get_identifier ("weak"), NULL_TREE, attr);
+    }
+
+  decl_attributes (node, attr, flags);
+
+  return NULL_TREE;
+}
+
 /* Handle an "visibility" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -5116,7 +5200,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
   orig_mode = TYPE_MODE (type);
 
   if (TREE_CODE (type) == RECORD_TYPE
-      || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
+      || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT)
       || !host_integerp (TYPE_SIZE_UNIT (type), 1))
     {
@@ -6236,4 +6320,20 @@ check_missing_format_attribute (tree ltype, tree rtype)
     return false;
 }
 
+/* Subscripting with type char is likely to lose on a machine where
+   chars are signed.  So warn on any machine, but optionally.  Don't
+   warn for unsigned char since that type is safe.  Don't warn for
+   signed char because anyone who uses that must have done so
+   deliberately. Furthermore, we reduce the false positive load by
+   warning only for non-constant value of type char.  */
+
+void
+warn_array_subscript_with_type_char (tree index)
+{
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
+      && TREE_CODE (index) != INTEGER_CST)
+    warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
+}
+
+
 #include "gt-c-common.h"