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.
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);
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,
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");
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");
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. */
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);
}
}
\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;
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.
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)
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)
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))
/* 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),
/* 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 ();
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
}
/* 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
#include "builtins.def"
#undef DEF_BUILTIN
+ targetm.init_builtins ();
+
build_common_builtin_nodes ();
- targetm.init_builtins ();
if (flag_mudflap)
mudflap_init ();
}
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. */
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"),
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)
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)))
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;
}
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;
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))
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. */
/* 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