OSDN Git Service

* config/pa/fptr.c: Update license header.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 48dcd5d..b884be9 100644 (file)
@@ -406,10 +406,9 @@ int flag_access_control = 1;
 
 int flag_check_new;
 
-/* Nonzero if we want to allow the use of experimental features that
-   are likely to become part of C++0x. */
+/* The C++ dialect being used. C++98 is the default.  */
 
-int flag_cpp0x = 0;
+enum cxx_dialect cxx_dialect = cxx98;
 
 /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
@@ -556,6 +555,7 @@ static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -650,6 +650,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_warn_unused_result_attribute },
   { "sentinel",               0, 1, false, true, true,
                              handle_sentinel_attribute },
+  { "alloc_size",            1, 2, false, true, true,
+                             handle_alloc_size_attribute },
   { "cold",                   0, 0, true,  false, false,
                              handle_cold_attribute },
   { "hot",                    0, 0, true,  false, false,
@@ -1048,7 +1050,7 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
              return true;
            }
           else if (warn_strict_aliasing == 2
-                  && !alias_sets_might_conflict_p (set1, set2))
+                  && !alias_sets_must_conflict_p (set1, set2))
            {
              warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
                       "pointer might break strict-aliasing rules");
@@ -1066,7 +1068,7 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
         HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (otype));
         HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
         if (!COMPLETE_TYPE_P(type)
-            || !alias_sets_might_conflict_p (set1, set2))
+            || !alias_sets_must_conflict_p (set1, set2))
          {
             warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
                      "pointer might break strict-aliasing rules");
@@ -1340,7 +1342,7 @@ warnings_for_convert_and_check (tree type, tree expr, tree result)
           else
             conversion_warning (type, expr);
         }
-      else if (!int_fits_type_p (expr, unsigned_type_for (type))) 
+      else if (!int_fits_type_p (expr, c_common_unsigned_type (type))) 
        warning (OPT_Woverflow,
                 "overflow in implicit constant conversion");
       /* No warning for converting 0x80000000 to int.  */
@@ -2035,37 +2037,17 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
   return 0;
 }
 
+tree
+c_common_unsigned_type (tree type)
+{
+  return c_common_signed_or_unsigned_type (1, type);
+}
+
 /* Return a signed type the same as TYPE in other respects.  */
 
 tree
 c_common_signed_type (tree type)
 {
-  tree type1 = TYPE_MAIN_VARIANT (type);
-  if (type1 == unsigned_char_type_node || type1 == char_type_node)
-    return signed_char_type_node;
-  if (type1 == unsigned_type_node)
-    return integer_type_node;
-  if (type1 == short_unsigned_type_node)
-    return short_integer_type_node;
-  if (type1 == long_unsigned_type_node)
-    return long_integer_type_node;
-  if (type1 == long_long_unsigned_type_node)
-    return long_long_integer_type_node;
-  if (type1 == widest_unsigned_literal_type_node)
-    return widest_integer_literal_type_node;
-#if HOST_BITS_PER_WIDE_INT >= 64
-  if (type1 == unsigned_intTI_type_node)
-    return intTI_type_node;
-#endif
-  if (type1 == unsigned_intDI_type_node)
-    return intDI_type_node;
-  if (type1 == unsigned_intSI_type_node)
-    return intSI_type_node;
-  if (type1 == unsigned_intHI_type_node)
-    return intHI_type_node;
-  if (type1 == unsigned_intQI_type_node)
-    return intQI_type_node;
-
   return c_common_signed_or_unsigned_type (0, type);
 }
 
@@ -2230,10 +2212,10 @@ min_precision (tree value, int unsignedp)
 }
 \f
 /* Print an error message for invalid operands to arith operation
-   CODE.  */
+   CODE with TYPE0 for operand 0, and TYPE1 for operand 1.  */
 
 void
-binary_op_error (enum tree_code code)
+binary_op_error (enum tree_code code, tree type0, tree type1)
 {
   const char *opname;
 
@@ -2284,7 +2266,8 @@ binary_op_error (enum tree_code code)
     default:
       gcc_unreachable ();
     }
-  error ("invalid operands to binary %s", opname);
+  error ("invalid operands to binary %s (have %qT and %qT)", opname,
+        type0, type1);
 }
 \f
 /* Subroutine of build_binary_op, used for comparison operations.
@@ -2511,8 +2494,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
              default:
                break;
              }
-         /* unsigned_type_for doesn't support C bit fields */
-         type = c_common_signed_or_unsigned_type (1, type);
+         type = c_common_unsigned_type (type);
        }
 
       if (TREE_CODE (primop0) != INTEGER_CST)
@@ -2645,7 +2627,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
   tree size_exp, ret;
 
   /* The result is a pointer of the same type that is being added.  */
-
   tree result_type = TREE_TYPE (ptrop);
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
@@ -2679,7 +2660,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      contains a constant term, apply distributive law
      and multiply that constant term separately.
      This helps produce common subexpressions.  */
-
   if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
       && !TREE_CONSTANT (intop)
       && TREE_CONSTANT (TREE_OPERAND (intop, 1))
@@ -2708,7 +2688,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 
   /* Convert the integer argument to a type the same size as sizetype
      so the multiply won't overflow spuriously.  */
-
   if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
       || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
     intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
@@ -2716,14 +2695,16 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 
   /* Replace the integer argument with a suitable product by the object size.
      Do this multiplication as signed, then convert to the appropriate
-     pointer type (actually unsigned integral).  */
-
-  intop = convert (result_type,
+     type for the pointer operation.  */
+  intop = convert (sizetype,
                   build_binary_op (MULT_EXPR, intop,
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
-  ret = fold_build2 (resultcode, result_type, ptrop, intop);
+  if (resultcode == MINUS_EXPR)
+    intop = fold_build1 (NEGATE_EXPR, sizetype, intop);
+
+  ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
 
   fold_undefer_and_ignore_overflow_warnings ();
 
@@ -3161,16 +3142,16 @@ c_common_get_alias_set (tree t)
       tree t2;
       /* Find bottom type under any nested POINTERs.  */
       for (t2 = TREE_TYPE (t);
-     TREE_CODE (t2) == POINTER_TYPE;
-     t2 = TREE_TYPE (t2))
-  ;
+          TREE_CODE (t2) == POINTER_TYPE;
+          t2 = TREE_TYPE (t2))
+       ;
       if (TREE_CODE (t2) != RECORD_TYPE
-    && TREE_CODE (t2) != ENUMERAL_TYPE
-    && TREE_CODE (t2) != QUAL_UNION_TYPE
-    && TREE_CODE (t2) != UNION_TYPE)
-  return -1;
+         && TREE_CODE (t2) != ENUMERAL_TYPE
+         && TREE_CODE (t2) != QUAL_UNION_TYPE
+         && TREE_CODE (t2) != UNION_TYPE)
+       return -1;
       if (TYPE_SIZE (t2) == 0)
-  return -1;
+       return -1;
     }
   /* These are the only cases that need special handling.  */
   if (TREE_CODE (t) != RECORD_TYPE
@@ -3264,16 +3245,16 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
 }
 
 /* Implement the __alignof keyword: Return the minimum required
-   alignment of EXPR, measured in bytes.  For VAR_DECL's and
-   FIELD_DECL's return DECL_ALIGN (which can be set from an
-   "aligned" __attribute__ specification).  */
+   alignment of EXPR, measured in bytes.  For VAR_DECLs,
+   FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
+   from an "aligned" __attribute__ specification).  */
 
 tree
 c_alignof_expr (tree expr)
 {
   tree t;
 
-  if (TREE_CODE (expr) == VAR_DECL)
+  if (VAR_OR_FUNCTION_DECL_P (expr))
     t = size_int (DECL_ALIGN_UNIT (expr));
 
   else if (TREE_CODE (expr) == COMPONENT_REF
@@ -3487,9 +3468,10 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
 #include "builtins.def"
 #undef DEF_BUILTIN
 
+  targetm.init_builtins ();
+
   build_common_builtin_nodes ();
 
-  targetm.init_builtins ();
   if (flag_mudflap)
     mudflap_init ();
 }
@@ -3681,7 +3663,7 @@ c_common_nodes_and_builtins (void)
   else
     {
       signed_wchar_type_node = c_common_signed_type (wchar_type_node);
-      unsigned_wchar_type_node = unsigned_type_for (wchar_type_node);
+      unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);
     }
 
   /* This is for wide string constants.  */
@@ -3699,7 +3681,7 @@ c_common_nodes_and_builtins (void)
   default_function_type = build_function_type (integer_type_node, NULL_TREE);
   ptrdiff_type_node
     = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
-  unsigned_ptrdiff_type_node = unsigned_type_for (ptrdiff_type_node);
+  unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
 
   lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
@@ -4366,7 +4348,7 @@ tree
 boolean_increment (enum tree_code code, tree arg)
 {
   tree val;
-  tree true_res = boolean_true_node;
+  tree true_res = build_int_cst (TREE_TYPE (arg), 1);
 
   arg = stabilize_reference (arg);
   switch (code)
@@ -4993,6 +4975,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
        mode = word_mode;
       else if (!strcmp (p, "pointer"))
        mode = ptr_mode;
+      else if (!strcmp (p, "libgcc_cmp_return"))
+       mode = targetm.libgcc_cmp_return_mode ();
+      else if (!strcmp (p, "libgcc_shift_count"))
+       mode = targetm.libgcc_shift_count_mode ();
       else
        for (j = 0; j < NUM_MACHINE_MODES; j++)
          if (!strcmp (p, GET_MODE_NAME (j)))
@@ -5220,12 +5206,24 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
       TYPE_USER_ALIGN (*type) = 1;
     }
-  else if (TREE_CODE (decl) != VAR_DECL
+  else if (! VAR_OR_FUNCTION_DECL_P (decl)
           && TREE_CODE (decl) != FIELD_DECL)
     {
       error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
+  else if (TREE_CODE (decl) == FUNCTION_DECL
+          && DECL_ALIGN (decl) > (1 << i) * BITS_PER_UNIT)
+    {
+      if (DECL_USER_ALIGN (decl))
+       error ("alignment for %q+D was previously specified as %d "
+              "and may not be decreased", decl,
+              DECL_ALIGN (decl) / BITS_PER_UNIT);
+      else
+       error ("alignment for %q+D must be at least %d", decl,
+              DECL_ALIGN (decl) / BITS_PER_UNIT);
+      *no_add_attrs = true;
+    }
   else
     {
       DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
@@ -5432,11 +5430,22 @@ handle_visibility_attribute (tree *node, tree name, tree args,
     }
 
   if (DECL_VISIBILITY_SPECIFIED (decl)
-      && vis != DECL_VISIBILITY (decl)
-      && lookup_attribute ("visibility", (TYPE_P (*node)
-                                         ? TYPE_ATTRIBUTES (*node)
-                                         : DECL_ATTRIBUTES (decl))))
-    error ("%qD redeclared with different visibility", decl);
+      && vis != DECL_VISIBILITY (decl))
+    {
+      tree attributes = (TYPE_P (*node)
+                        ? TYPE_ATTRIBUTES (*node)
+                        : DECL_ATTRIBUTES (decl));
+      if (lookup_attribute ("visibility", attributes))
+       error ("%qD redeclared with different visibility", decl);
+      else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+              && lookup_attribute ("dllimport", attributes))
+       error ("%qD was declared %qs which implies default visibility",
+              decl, "dllimport");
+      else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+              && lookup_attribute ("dllexport", attributes))
+       error ("%qD was declared %qs which implies default visibility",
+              decl, "dllexport");
+    }
 
   DECL_VISIBILITY (decl) = vis;
   DECL_VISIBILITY_SPECIFIED (decl) = 1;
@@ -5469,18 +5478,12 @@ c_determine_visibility (tree decl)
      to distinguish the use of an attribute from the use of a "#pragma
      GCC visibility push(...)"; in the latter case we still want other
      considerations to be able to overrule the #pragma.  */
-  if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
+  if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))
+      || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+         && (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
+             || lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))))
     return true;
 
-  /* Anything that is exported must have default visibility.  */
-  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-      && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
-    {
-      DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
-      DECL_VISIBILITY_SPECIFIED (decl) = 1;
-      return true;
-    }
-
   /* Set default visibility to whatever the user supplied with
      visibility_specified depending on #pragma GCC visibility.  */
   if (!DECL_VISIBILITY_SPECIFIED (decl))
@@ -5579,6 +5582,37 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle a "alloc_size" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+                            int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree params = TYPE_ARG_TYPES (*node);
+  unsigned arg_count = 0;
+
+  for (; TREE_CHAIN (params); params = TREE_CHAIN (params))
+    arg_count ++;
+
+  for (; args; args = TREE_CHAIN (args))
+    {
+      tree position = TREE_VALUE (args);
+
+      if (TREE_CODE (position) != INTEGER_CST
+         || TREE_INT_CST_HIGH (position) 
+         || TREE_INT_CST_LOW (position) < 1
+         || TREE_INT_CST_LOW (position) > arg_count )
+       {
+         warning (OPT_Wattributes, 
+                  "alloc_size parameter outside range");
+         *no_add_attrs = true;
+         return NULL_TREE;
+       }
+    }
+  return NULL_TREE;
+}
+
 /* Handle a "returns_twice" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -6883,8 +6917,8 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2)
 
   /* Equality works here because c_common_signed_type uses
      TYPE_MAIN_VARIANT.  */
-  return lang_hooks.types.signed_type (t1)
-    == lang_hooks.types.signed_type (t2);
+  return c_common_signed_type (t1)
+    == c_common_signed_type (t2);
 }
 
 /* Check for missing format attributes on function pointers.  LTYPE is