OSDN Git Service

* trans-stmt.c (gfc_trans_forall_1): Prefer to use smaller logical
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index f68c853..91fba52 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -47,6 +47,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-mudflap.h"
 #include "opts.h"
 #include "real.h"
+#include "cgraph.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -191,11 +192,6 @@ cpp_reader *parse_in;              /* Declared in c-pragma.h.  */
 */
 
 tree c_global_trees[CTI_MAX];
-
-/* TRUE if a code represents a statement.  The front end init
-   langhook should take care of initialization of this array.  */
-
-bool statement_code_p[MAX_TREE_CODES];
 \f
 /* Switches common to the C front ends.  */
 
@@ -284,18 +280,17 @@ int warn_unknown_pragmas; /* Tri state variable.  */
 
 int warn_format;
 
+/* Warn about using __null (as NULL in C++) as sentinel.  For code compiled
+   with GCC this doesn't matter as __null is guaranteed to have the right
+   size.  */
+
+int warn_strict_null_sentinel;
+
 /* Zero means that faster, ...NonNil variants of objc_msgSend...
    calls will be used in ObjC; passing nil receivers to such calls
    will most likely result in crashes.  */
 int flag_nil_receivers = 1;
 
-/* Nonzero means that we will allow new ObjC exception syntax (@throw,
-   @try, etc.) in source code.  */
-int flag_objc_exceptions = 0;
-
-/* Nonzero means that we generate NeXT setjmp based exceptions.  */
-int flag_objc_sjlj_exceptions = -1;
-
 /* Nonzero means that code generation will be altered to support
    "zero-link" execution.  This currently affects ObjC only, but may
    affect other languages in the future.  */
@@ -520,6 +515,8 @@ static tree handle_always_inline_attribute (tree *, tree, tree, int,
                                            bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_externally_visible_attribute (tree *, tree, tree, int,
+                                                bool *);
 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
 static tree handle_transparent_union_attribute (tree *, tree, tree,
                                                int, bool *);
@@ -586,6 +583,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_used_attribute },
   { "unused",                 0, 0, false, false, false,
                              handle_unused_attribute },
+  { "externally_visible",     0, 0, true,  false, false,
+                             handle_externally_visible_attribute },
   /* The same comments as for noreturn attributes apply to const ones.  */
   { "const",                  0, 0, true,  false, false,
                              handle_const_attribute },
@@ -913,7 +912,7 @@ overflow_warning (tree value)
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("integer overflow in expression");
+       warning (0, "integer overflow in expression");
     }
   else if ((TREE_CODE (value) == REAL_CST
            || (TREE_CODE (value) == COMPLEX_CST
@@ -922,13 +921,13 @@ overflow_warning (tree value)
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("floating point overflow in expression");
+       warning (0, "floating point overflow in expression");
     }
   else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value))
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("vector overflow in expression");
+       warning (0, "vector overflow in expression");
     }
 }
 
@@ -950,9 +949,10 @@ unsigned_conversion_warning (tree result, tree operand)
     {
       if (!int_fits_type_p (operand, c_common_signed_type (type)))
        /* This detects cases like converting -129 or 256 to unsigned char.  */
-       warning ("large integer implicitly truncated to unsigned type");
-      else if (warn_conversion)
-       warning ("negative integer implicitly converted to unsigned type");
+       warning (0, "large integer implicitly truncated to unsigned type");
+      else
+       warning (OPT_Wconversion,
+                "negative integer implicitly converted to unsigned type");
     }
 }
 
@@ -1010,7 +1010,7 @@ convert_and_check (tree type, tree expr)
                 || !constant_fits_type_p (expr,
                                           c_common_unsigned_type (type)))
                && skip_evaluation == 0)
-             warning ("overflow in implicit constant conversion");
+             warning (0, "overflow in implicit constant conversion");
        }
       else
        unsigned_conversion_warning (t, expr);
@@ -1146,7 +1146,7 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
          && DECL_NAME (list->expr))
        {
          warned_ids = new_tlist (warned_ids, written, NULL_TREE);
-         warning ("operation on %qE may be undefined", list->expr);
+         warning (0, "operation on %qE may be undefined", list->expr);
        }
       list = list->next;
     }
@@ -1450,7 +1450,7 @@ check_case_value (tree value)
    if the case is not a case range.
    The caller has to make sure that we are not called with NULL for
    CASE_LOW_P (i.e. the default case).
-   Returns true if the case label is in range of ORIG_TYPE (satured or
+   Returns true if the case label is in range of ORIG_TYPE (saturated or
    untouched) or false if the label is out of range.  */
 
 static bool
@@ -1472,7 +1472,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, min_value) < 0
       && tree_int_cst_compare (case_high, min_value) < 0)
     {
-      warning ("case label value is less than minimum value for type");
+      warning (0, "case label value is less than minimum value for type");
       return false;
     }
 
@@ -1480,7 +1480,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, max_value) > 0
       && tree_int_cst_compare (case_high, max_value) > 0)
     {
-      warning ("case label value exceeds maximum value for type");
+      warning (0, "case label value exceeds maximum value for type");
       return false;
     }
 
@@ -1488,7 +1488,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_high, min_value) >= 0
       && tree_int_cst_compare (case_low, min_value) < 0)
     {
-      warning ("lower value in case label range"
+      warning (0, "lower value in case label range"
               " less than minimum value for type");
       case_low = min_value;
     }
@@ -1497,7 +1497,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, max_value) <= 0
       && tree_int_cst_compare (case_high, max_value) > 0)
     {
-      warning ("upper value in case label range"
+      warning (0, "upper value in case label range"
               " exceeds maximum value for type");
       case_high = max_value;
     }
@@ -2120,9 +2120,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       if (TREE_CODE (primop0) != INTEGER_CST)
        {
          if (val == truthvalue_false_node)
-           warning ("comparison is always false due to limited range of data type");
+           warning (0, "comparison is always false due to limited range of data type");
          if (val == truthvalue_true_node)
-           warning ("comparison is always true due to limited range of data type");
+           warning (0, "comparison is always true due to limited range of data type");
        }
 
       if (val != 0)
@@ -2192,7 +2192,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning ("comparison of unsigned expression >= 0 is always true");
+               warning (0, "comparison of unsigned expression >= 0 is always true");
              value = truthvalue_true_node;
              break;
 
@@ -2201,7 +2201,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning ("comparison of unsigned expression < 0 is always false");
+               warning (0, "comparison of unsigned expression < 0 is always false");
              value = truthvalue_false_node;
              break;
 
@@ -2381,7 +2381,7 @@ c_common_truthvalue_conversion (tree expr)
          {
            /* Common Ada/Pascal programmer's mistake.  We always warn
               about this since it is so bad.  */
-           warning ("the address of %qD, will always evaluate as %<true%>",
+           warning (0, "the address of %qD, will always evaluate as %<true%>",
                     TREE_OPERAND (expr, 0));
            return truthvalue_true_node;
          }
@@ -2461,12 +2461,12 @@ c_common_truthvalue_conversion (tree expr)
         two objects.  */
       if (TREE_TYPE (TREE_OPERAND (expr, 0))
          == TREE_TYPE (TREE_OPERAND (expr, 1)))
-       return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
-                               TREE_OPERAND (expr, 1), 1);
-      return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
-                             fold (build1 (NOP_EXPR,
-                                           TREE_TYPE (TREE_OPERAND (expr, 0)),
-                                           TREE_OPERAND (expr, 1))), 1);
+       return fold_build2 (NE_EXPR, truthvalue_type_node,
+                           TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+      return fold_build2 (NE_EXPR, truthvalue_type_node,
+                         TREE_OPERAND (expr, 0),
+                         fold_convert (TREE_TYPE (TREE_OPERAND (expr, 0)),
+                                       TREE_OPERAND (expr, 1)));
 
     case BIT_AND_EXPR:
       if (integer_onep (TREE_OPERAND (expr, 1))
@@ -2476,8 +2476,9 @@ c_common_truthvalue_conversion (tree expr)
       break;
 
     case MODIFY_EXPR:
-      if (warn_parentheses && !TREE_NO_WARNING (expr))
-       warning ("suggest parentheses around assignment used as truth value");
+      if (!TREE_NO_WARNING (expr))
+       warning (OPT_Wparentheses,
+                "suggest parentheses around assignment used as truth value");
       break;
 
     default:
@@ -2786,19 +2787,19 @@ c_common_get_alias_set (tree t)
    second parameter indicates which OPERATOR is being applied.  The COMPLAIN
    flag controls whether we should diagnose possibly ill-formed
    constructs or not.  */
+
 tree
-c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
+c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
 {
   const char *op_name;
   tree value = NULL;
   enum tree_code type_code = TREE_CODE (type);
 
-  gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
-  op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
+  op_name = is_sizeof ? "sizeof" : "__alignof__";
 
   if (type_code == FUNCTION_TYPE)
     {
-      if (op == SIZEOF_EXPR)
+      if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
            pedwarn ("invalid application of %<sizeof%> to a function type");
@@ -2823,7 +2824,7 @@ c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
     }
   else
     {
-      if (op == (enum tree_code) SIZEOF_EXPR)
+      if (is_sizeof)
        /* Convert in case a char is more than one unit.  */
        value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
                            size_int (TYPE_PRECISION (char_type_node)
@@ -3242,8 +3243,9 @@ c_common_nodes_and_builtins (void)
     {                                                                  \
       tree decl;                                                       \
                                                                        \
-      gcc_assert (!strncmp (NAME, "__builtin_",                                \
-                           strlen ("__builtin_")));                    \
+      gcc_assert ((!BOTH_P && !FALLBACK_P)                             \
+                 || !strncmp (NAME, "__builtin_",                      \
+                              strlen ("__builtin_")));                 \
                                                                        \
       if (!BOTH_P)                                                     \
        decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE],  \
@@ -3278,6 +3280,11 @@ c_common_nodes_and_builtins (void)
     mudflap_init ();
 
   main_identifier_node = get_identifier ("main");
+
+  /* Create the built-in __null node.  It is important that this is
+     not shared.  */
+  null_node = make_node (INTEGER_CST);
+  TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
 }
 
 /* Look up the function in built_in_decls that corresponds to DECL
@@ -3547,7 +3554,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
     high_value = NULL_TREE;
   if (low_value && high_value
       && !tree_int_cst_lt (low_value, high_value))
-    warning ("empty range specified");
+    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,
@@ -3634,7 +3641,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
  error_out:
   /* Add a label so that the back-end doesn't think that the beginning of
      the switch is unreachable.  Note that we do not add a case label, as
-     that just leads to duplicates and thence to aborts later on.  */
+     that just leads to duplicates and thence to failure later on.  */
   if (!cases->root)
     {
       tree t = create_artificial_label ();
@@ -3666,10 +3673,10 @@ match_case_to_enum_1 (tree key, tree type, tree label)
              TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
 
   if (TYPE_NAME (type) == 0)
-    warning ("%Jcase value %qs not in enumerated type",
+    warning (0, "%Jcase value %qs not in enumerated type",
             CASE_LABEL (label), buf);
   else
-    warning ("%Jcase value %qs not in enumerated type %qT",
+    warning (0, "%Jcase value %qs not in enumerated type %qT",
             CASE_LABEL (label), buf, type);
 }
 
@@ -3708,11 +3715,16 @@ match_case_to_enum (splay_tree_node node, void *data)
   return 0;
 }
 
-/* Common code for -Wswitch*.  */
+/* Handle -Wswitch*.  Called from the front end after parsing the
+   switch construct.  */
+/* ??? Should probably be somewhere generic, since other languages
+   besides C and C++ would want this.  At the moment, however, C/C++
+   are the only tree-ssa languages that support enumerations at all,
+   so the point is moot.  */
 
-static void
-c_do_switch_warnings_1 (splay_tree cases, location_t switch_location,
-                       tree type, tree cond)
+void
+c_do_switch_warnings (splay_tree cases, location_t switch_location,
+                     tree type, tree cond)
 {
   splay_tree_node default_node;
 
@@ -3720,8 +3732,9 @@ c_do_switch_warnings_1 (splay_tree cases, location_t switch_location,
     return;
 
   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
-  if (warn_switch_default && !default_node)
-    warning ("%Hswitch missing default case", &switch_location);
+  if (!default_node)
+    warning (OPT_Wswitch_default, "%Hswitch missing default case",
+            &switch_location);
 
   /* If the switch expression was an enumerated type, check that
      exactly all enumeration literals are covered by the cases.
@@ -3755,7 +3768,7 @@ c_do_switch_warnings_1 (splay_tree cases, location_t switch_location,
            {
              /* Warn if there are enumerators that don't correspond to
                 case expressions.  */
-             warning ("%Henumeration value %qE not handled in switch",
+             warning (0, "%Henumeration value %qE not handled in switch",
                       &switch_location, TREE_PURPOSE (chain));
            }
        }
@@ -3773,45 +3786,6 @@ c_do_switch_warnings_1 (splay_tree cases, location_t switch_location,
     }
 }
 
-/* Handle -Wswitch* for a SWITCH_STMT.  Called from the front end
-   after parsing the switch construct.  */
-/* ??? Should probably be somewhere generic, since other languages besides
-   C and C++ would want this.  We'd want to agree on the data structure,
-   however, which is a problem.  Alternately, we operate on gimplified
-   switch_exprs, which I don't especially like.  At the moment, however,
-   C/C++ are the only tree-ssa languages that support enumerations at all,
-   so the point is moot.  */
-
-void
-c_do_switch_warnings (splay_tree cases, tree switch_stmt)
-{
-  location_t switch_location;
-
-  if (EXPR_HAS_LOCATION (switch_stmt))
-    switch_location = EXPR_LOCATION (switch_stmt);
-  else
-    switch_location = input_location;
-  c_do_switch_warnings_1 (cases, switch_location,
-                         SWITCH_STMT_TYPE (switch_stmt),
-                         SWITCH_STMT_COND (switch_stmt));
-}
-
-/* Like c_do_switch_warnings, but takes a SWITCH_EXPR rather than a
-   SWITCH_STMT.  */
-
-void
-c_do_switch_expr_warnings (splay_tree cases, tree switch_expr)
-{
-  location_t switch_location;
-
-  if (EXPR_HAS_LOCATION (switch_expr))
-    switch_location = EXPR_LOCATION (switch_expr);
-  else
-    switch_location = input_location;
-  c_do_switch_warnings_1 (cases, switch_location, TREE_TYPE (switch_expr),
-                         SWITCH_COND (switch_expr));
-}
-
 /* Finish an expression taking the address of LABEL (an
    IDENTIFIER_NODE).  Returns an expression for the address.  */
 
@@ -3990,7 +3964,7 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
      that changes what the typedef is typing.  */
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4009,7 +3983,7 @@ handle_nocommon_attribute (tree *node, tree name,
     DECL_COMMON (*node) = 0;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4027,7 +4001,7 @@ handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_COMMON (*node) = 1;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4054,7 +4028,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TYPE_READONLY (TREE_TYPE (type)), 1));
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4073,7 +4047,7 @@ handle_noinline_attribute (tree *node, tree name,
     DECL_UNINLINABLE (*node) = 1;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4096,7 +4070,7 @@ handle_always_inline_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4120,7 +4094,7 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
     }
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4146,7 +4120,7 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
        TREE_USED (decl) = 1;
       else
        {
-         warning ("%qE attribute ignored", name);
+         warning (OPT_Wattributes, "%qE attribute ignored", name);
          *no_add_attrs = true;
        }
     }
@@ -4160,6 +4134,47 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle a "externally_visible" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_externally_visible_attribute (tree *pnode, tree name,
+                                    tree ARG_UNUSED (args),
+                                    int ARG_UNUSED (flags),
+                                    bool *no_add_attrs)
+{
+  tree node = *pnode;
+
+  if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL)
+      || !TREE_PUBLIC (node))
+    {
+      warning (OPT_Wattributes,
+              "%qE attribute have effect only on public objects", name);
+      *no_add_attrs = true;
+    }
+  else if (TREE_CODE (node) == FUNCTION_DECL)
+    {
+      struct cgraph_node *n = cgraph_node (node);
+      n->local.externally_visible = true;
+      if (n->local.finalized)
+       cgraph_mark_needed_node (n);
+    }
+  else if (TREE_CODE (node) == VAR_DECL)
+    {
+      struct cgraph_varpool_node *n = cgraph_varpool_node (node);
+      n->externally_visible = true;
+      if (n->finalized)
+       cgraph_varpool_mark_needed_node (n);
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "const" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -4180,7 +4195,7 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TREE_THIS_VOLATILE (TREE_TYPE (type))));
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4224,7 +4239,7 @@ handle_transparent_union_attribute (tree *node, tree name,
     DECL_TRANSPARENT_UNION (decl) = 1;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4252,7 +4267,7 @@ handle_constructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4280,7 +4295,7 @@ handle_destructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4299,7 +4314,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
   *no_add_attrs = true;
 
   if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
-    warning ("%qE attribute ignored", name);
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
     {
       int j;
@@ -4357,9 +4372,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
        case MODE_VECTOR_INT:
        case MODE_VECTOR_FLOAT:
-         warning ("specifying vector types with __attribute__ ((mode)) "
-                  "is deprecated");
-         warning ("use __attribute__ ((vector_size)) instead");
+         warning (OPT_Wattributes, "specifying vector types with "
+                  "__attribute__ ((mode)) is deprecated");
+         warning (OPT_Wattributes,
+                  "use __attribute__ ((vector_size)) instead");
          valid_mode = vector_mode_valid_p (mode);
          break;
 
@@ -4624,7 +4640,7 @@ handle_alias_attribute (tree *node, tree name, tree args,
     }
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4648,13 +4664,14 @@ handle_visibility_attribute (tree *node, tree name, tree args,
     {
       if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
        {
-         warning ("%qE attribute ignored on non-class types", name);
+         warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
+                 name);
          return NULL_TREE;
        }
     }
   else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
@@ -4672,7 +4689,7 @@ handle_visibility_attribute (tree *node, tree name, tree args,
         return NULL_TREE;
       if (TREE_CODE (decl) == IDENTIFIER_NODE)
        {
-          warning ("%qE attribute ignored on types",
+          warning (OPT_Wattributes, "%qE attribute ignored on types",
                    name);
           return NULL_TREE;
        }
@@ -4746,7 +4763,7 @@ handle_tls_model_attribute (tree *node, tree name, tree args,
 
   if (!DECL_THREAD_LOCAL (decl))
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
   else
@@ -4813,7 +4830,7 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_IS_MALLOC (*node) = 1;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4831,7 +4848,7 @@ handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_IS_RETURNS_TWICE (*node) = 1;
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4877,7 +4894,7 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4945,9 +4962,9 @@ handle_deprecated_attribute (tree *node, tree name,
            what = DECL_NAME (TYPE_NAME (type));
        }
       if (what)
-       warning ("%qE attribute ignored for %qE", name, what);
+       warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
       else
-       warning ("%qE attribute ignored", name);
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
     }
 
   return NULL_TREE;
@@ -4971,7 +4988,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 
   if (!host_integerp (size, 1))
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
@@ -5133,7 +5150,7 @@ check_function_sentinel (tree attrs, tree params)
   if (attr)
     {
       if (!params)
-       warning ("missing sentinel in function call");
+       warning (0, "missing sentinel in function call");
       else
         {
          tree sentinel, end;
@@ -5155,7 +5172,7 @@ check_function_sentinel (tree attrs, tree params)
            }
          if (pos > 0)
            {
-             warning ("not enough arguments to fit a sentinel");
+             warning (0, "not enough arguments to fit a sentinel");
              return;
            }
 
@@ -5167,9 +5184,16 @@ check_function_sentinel (tree attrs, tree params)
            }
 
          /* Validate the sentinel.  */
-         if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
-             || !integer_zerop (TREE_VALUE (sentinel)))
-           warning ("missing sentinel in function call");
+         if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
+              || !integer_zerop (TREE_VALUE (sentinel)))
+             /* Although __null (in C++) is only an integer we allow it
+                nevertheless, as we are guaranteed that it's exactly
+                as wide as a pointer, and we don't want to force
+                users to cast the NULL they have written there.
+                We warn with -Wstrict-null-sentinel, though.  */
+              && (warn_strict_null_sentinel
+                 || null_node != TREE_VALUE (sentinel)))
+           warning (0, "missing sentinel in function call");
        }
     }
 }
@@ -5211,7 +5235,7 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
     return;
 
   if (integer_zerop (param))
-    warning ("null argument where non-null required (argument %lu)",
+    warning (0, "null argument where non-null required (argument %lu)",
             (unsigned long) param_num);
 }
 
@@ -5242,7 +5266,7 @@ handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5265,7 +5289,7 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
      we'd be missing too much, since we do have attribute constructor.  */
   if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -5304,7 +5328,7 @@ handle_warn_unused_result_attribute (tree *node, tree name,
   /* Ignore the attribute for functions not returning any value.  */
   if (VOID_TYPE_P (TREE_TYPE (*node)))
     {
-      warning ("%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5321,7 +5345,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
   if (!params)
     {
-      warning ("%qE attribute requires prototypes with named arguments", name);
+      warning (OPT_Wattributes,
+              "%qE attribute requires prototypes with named arguments", name);
       *no_add_attrs = true;
     }
   else
@@ -5331,7 +5356,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
       if (VOID_TYPE_P (TREE_VALUE (params)))
         {
-         warning ("%qE attribute only applies to variadic functions", name);
+         warning (OPT_Wattributes,
+                  "%qE attribute only applies to variadic functions", name);
          *no_add_attrs = true;
        }
     }
@@ -5342,14 +5368,14 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
       if (TREE_CODE (position) != INTEGER_CST)
         {
-         warning ("requested position is not an integer constant");
+         warning (0, "requested position is not an integer constant");
          *no_add_attrs = true;
        }
       else
         {
          if (tree_int_cst_lt (position, integer_zero_node))
            {
-             warning ("requested position is less than zero");
+             warning (0, "requested position is less than zero");
              *no_add_attrs = true;
            }
        }
@@ -5540,51 +5566,51 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
   return result;
 }
 
-/* Issue the error given by MSGID, indicating that it occurred before
+/* Issue the error given by GMSGID, indicating that it occurred before
    TOKEN, which had the associated VALUE.  */
 
 void
-c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
+c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
   char *message = NULL;
 
   if (token == CPP_EOF)
-    message = catenate_messages (msgid, " at end of input");
+    message = catenate_messages (gmsgid, " at end of input");
   else if (token == CPP_CHAR || token == CPP_WCHAR)
     {
       unsigned int val = TREE_INT_CST_LOW (value);
       const char *const ell = (token == CPP_CHAR) ? "" : "L";
       if (val <= UCHAR_MAX && ISGRAPH (val))
-        message = catenate_messages (msgid, " before %s'%c'");
+        message = catenate_messages (gmsgid, " before %s'%c'");
       else
-        message = catenate_messages (msgid, " before %s'\\x%x'");
+        message = catenate_messages (gmsgid, " before %s'\\x%x'");
 
       error (message, ell, val);
       free (message);
       message = NULL;
     }
   else if (token == CPP_STRING || token == CPP_WSTRING)
-    message = catenate_messages (msgid, " before string constant");
+    message = catenate_messages (gmsgid, " before string constant");
   else if (token == CPP_NUMBER)
-    message = catenate_messages (msgid, " before numeric constant");
+    message = catenate_messages (gmsgid, " before numeric constant");
   else if (token == CPP_NAME)
     {
-      message = catenate_messages (msgid, " before %qE");
+      message = catenate_messages (gmsgid, " before %qE");
       error (message, value);
       free (message);
       message = NULL;
     }
   else if (token < N_TTYPES)
     {
-      message = catenate_messages (msgid, " before %qs token");
+      message = catenate_messages (gmsgid, " before %qs token");
       error (message, cpp_type2name (token));
       free (message);
       message = NULL;
     }
   else
-    error (msgid);
+    error (gmsgid);
 
   if (message)
     {
@@ -5651,11 +5677,11 @@ c_warn_unused_result (tree *top_p)
       if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
        {
          if (fdecl)
-           warning ("%Hignoring return value of %qD, "
+           warning (0, "%Hignoring return value of %qD, "
                     "declared with attribute warn_unused_result",
                     EXPR_LOCUS (t), fdecl);
          else
-           warning ("%Hignoring return value of function "
+           warning (0, "%Hignoring return value of function "
                     "declared with attribute warn_unused_result",
                     EXPR_LOCUS (t));
        }
@@ -5870,4 +5896,199 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   return failure;
 }
 
+\f
+/* Used to help initialize the builtin-types.def table.  When a type of
+   the correct size doesn't exist, use error_mark_node instead of NULL.
+   The later results in segfaults even when a decl using the type doesn't
+   get invoked.  */
+
+tree
+builtin_type_for_size (int size, bool unsignedp)
+{
+  tree type = lang_hooks.types.type_for_size (size, unsignedp);
+  return type ? type : error_mark_node;
+}
+
+/* A helper function for resolve_overloaded_builtin in resolving the
+   overloaded __sync_ builtins.  Returns a positive power of 2 if the
+   first operand of PARAMS is a pointer to a supported data type.
+   Returns 0 if an error is encountered.  */
+
+static int
+sync_resolve_size (tree function, tree params)
+{
+  tree type;
+  int size;
+
+  if (params == NULL)
+    {
+      error ("too few arguments to function %qE", function);
+      return 0;
+    }
+
+  type = TREE_TYPE (TREE_VALUE (params));
+  if (TREE_CODE (type) != POINTER_TYPE)
+    goto incompatible;
+
+  type = TREE_TYPE (type);
+  if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+    goto incompatible;
+
+  size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+  if (size == 1 || size == 2 || size == 4 || size == 8)
+    return size;
+
+ incompatible:
+  error ("incompatible type for argument %d of %qE", 1, function);
+  return 0;
+}
+
+/* A helper function for resolve_overloaded_builtin.  Adds casts to 
+   PARAMS to make arguments match up with those of FUNCTION.  Drops
+   the variadic arguments at the end.  Returns false if some error
+   was encountered; true on success.  */
+
+static bool
+sync_resolve_params (tree orig_function, tree function, tree params)
+{
+  tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
+  tree ptype;
+  int number;
+
+  /* We've declared the implementation functions to use "volatile void *"
+     as the pointer parameter, so we shouldn't get any complaints from the
+     call to check_function_arguments what ever type the user used.  */
+  arg_types = TREE_CHAIN (arg_types);
+  ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  number = 2;
+
+  /* For the rest of the values, we need to cast these to FTYPE, so that we
+     don't get warnings for passing pointer types, etc.  */
+  while (arg_types != void_list_node)
+    {
+      tree val;
+
+      params = TREE_CHAIN (params);
+      if (params == NULL)
+       {
+         error ("too few arguments to function %qE", orig_function);
+         return false;
+       }
+
+      /* ??? Ideally for the first conversion we'd use convert_for_assignment
+        so that we get warnings for anything that doesn't match the pointer
+        type.  This isn't portable across the C and C++ front ends atm.  */
+      val = TREE_VALUE (params);
+      val = convert (ptype, val);
+      val = convert (TREE_VALUE (arg_types), val);
+      TREE_VALUE (params) = val;
+
+      arg_types = TREE_CHAIN (arg_types);
+      number++;
+    }
+
+  /* The definition of these primitives is variadic, with the remaining
+     being "an optional list of variables protected by the memory barrier".
+     No clue what that's supposed to mean, precisely, but we consider all
+     call-clobbered variables to be protected so we're safe.  */
+  TREE_CHAIN (params) = NULL;
+
+  return true;
+}
+
+/* A helper function for resolve_overloaded_builtin.  Adds a cast to 
+   RESULT to make it match the type of the first pointer argument in
+   PARAMS.  */
+
+static tree
+sync_resolve_return (tree params, tree result)
+{
+  tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  return convert (ptype, result);
+}
+
+/* Some builtin functions are placeholders for other expressions.  This
+   function should be called immediately after parsing the call expression
+   before surrounding code has committed to the type of the expression.
+
+   FUNCTION is the DECL that has been invoked; it is known to be a builtin.
+   PARAMS is the argument list for the call.  The return value is non-null
+   when expansion is complete, and null if normal processing should
+   continue.  */
+
+tree
+resolve_overloaded_builtin (tree function, tree params)
+{
+  enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
+  switch (DECL_BUILT_IN_CLASS (function))
+    {
+    case BUILT_IN_NORMAL:
+      break;
+    case BUILT_IN_MD:
+      if (targetm.resolve_overloaded_builtin)
+        return targetm.resolve_overloaded_builtin (function, params);
+      else
+        return NULL_TREE;
+    default:
+      return NULL_TREE;
+    }
+    
+  /* Handle BUILT_IN_NORMAL here.  */
+  switch (orig_code)
+    {
+    case BUILT_IN_FETCH_AND_ADD_N:
+    case BUILT_IN_FETCH_AND_SUB_N:
+    case BUILT_IN_FETCH_AND_OR_N:
+    case BUILT_IN_FETCH_AND_AND_N:
+    case BUILT_IN_FETCH_AND_XOR_N:
+    case BUILT_IN_FETCH_AND_NAND_N:
+    case BUILT_IN_ADD_AND_FETCH_N:
+    case BUILT_IN_SUB_AND_FETCH_N:
+    case BUILT_IN_OR_AND_FETCH_N:
+    case BUILT_IN_AND_AND_FETCH_N:
+    case BUILT_IN_XOR_AND_FETCH_N:
+    case BUILT_IN_NAND_AND_FETCH_N:
+    case BUILT_IN_BOOL_COMPARE_AND_SWAP_N:
+    case BUILT_IN_VAL_COMPARE_AND_SWAP_N:
+    case BUILT_IN_LOCK_TEST_AND_SET_N:
+    case BUILT_IN_LOCK_RELEASE_N:
+      {
+       int n = sync_resolve_size (function, params);
+       tree new_function, result;
+
+       if (n == 0)
+         return error_mark_node;
+
+       new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+       if (!sync_resolve_params (function, new_function, params))
+         return error_mark_node;
+
+       result = build_function_call (new_function, params);
+       if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
+           && orig_code != BUILT_IN_LOCK_RELEASE_N)
+         result = sync_resolve_return (params, result);
+
+       return result;
+      }
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* Ignoring their sign, return true if two scalar types are the same.  */
+bool
+same_scalar_type_ignoring_signedness (tree t1, tree t2)
+{
+  enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
+
+  gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE)
+             && (c2 == INTEGER_TYPE || c2 == REAL_TYPE));
+
+  /* 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);
+}
+
 #include "gt-c-common.h"