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");
unsigned int formal_prec = TYPE_PRECISION (type);
+ if (!warn_conversion && !warn_sign_conversion)
+ return;
+
if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
{
/* Warn for real constant that is not an exact integer converted
&& !int_fits_type_p (expr, type))
{
if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
- warning (OPT_Wconversion,
- "negative integer implicitly converted to unsigned type");
- else
- give_warning = true;
+ warning (OPT_Wsign_conversion,
+ "negative integer implicitly converted to unsigned type");
+ else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
+ warning (OPT_Wsign_conversion,
+ "conversion of unsigned constant value to negative integer");
+ else
+ give_warning = true;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
&& TREE_CODE (type) == INTEGER_TYPE)
{
/* Warn for integer types converted to smaller integer types. */
- if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))
- /* When they are the same width but different signedness,
- then the value may change. */
- || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
- && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type))
- /* Even when converted to a bigger type, if the type is
- unsigned but expr is signed, then negative values
- will be changed. */
- || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))))
- give_warning = true;
+ if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ give_warning = true;
+
+ /* When they are the same width but different signedness,
+ then the value may change. */
+ else if ((formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
+ && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type))
+ /* Even when converted to a bigger type, if the type is
+ unsigned but expr is signed, then negative values
+ will be changed. */
+ || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))))
+ warning (OPT_Wsign_conversion,
+ "conversion to %qT from %qT may change the sign of the result",
+ type, TREE_TYPE (expr));
}
/* Warn for integer types converted to real types if and only if
if (!int_fits_type_p (expr, c_common_signed_type (type)))
warning (OPT_Woverflow,
"large integer implicitly truncated to unsigned type");
- else if (warn_conversion)
+ else
conversion_warning (type, expr);
}
else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
warning (OPT_Woverflow,
"overflow in implicit constant conversion");
- else if (warn_conversion)
+ else
conversion_warning (type, expr);
}
else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result))
warning (OPT_Woverflow,
"overflow in implicit constant conversion");
- else if (warn_conversion)
+ else
conversion_warning (type, expr);
}
result = convert (type, expr);
- if (!skip_evaluation && !TREE_OVERFLOW_P (expr))
+ if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
warnings_for_convert_and_check (type, expr, result);
return result;
return 0;
}
-/* Return an unsigned type the same as TYPE in other respects. */
tree
c_common_unsigned_type (tree type)
{
- tree type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == signed_char_type_node || type1 == char_type_node)
- return unsigned_char_type_node;
- if (type1 == integer_type_node)
- return unsigned_type_node;
- if (type1 == short_integer_type_node)
- return short_unsigned_type_node;
- if (type1 == long_integer_type_node)
- return long_unsigned_type_node;
- if (type1 == long_long_integer_type_node)
- return long_long_unsigned_type_node;
- if (type1 == widest_integer_literal_type_node)
- return widest_unsigned_literal_type_node;
-#if HOST_BITS_PER_WIDE_INT >= 64
- if (type1 == intTI_type_node)
- return unsigned_intTI_type_node;
-#endif
- if (type1 == intDI_type_node)
- return unsigned_intDI_type_node;
- if (type1 == intSI_type_node)
- return unsigned_intSI_type_node;
- if (type1 == intHI_type_node)
- return unsigned_intHI_type_node;
- if (type1 == intQI_type_node)
- return unsigned_intQI_type_node;
-
return c_common_signed_or_unsigned_type (1, type);
}
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);
}
tree
c_common_signed_or_unsigned_type (int unsignedp, tree type)
{
- if (!INTEGRAL_TYPE_P (type)
- || TYPE_UNSIGNED (type) == unsignedp)
- return type;
+ tree type1;
+
+ /* This block of code emulates the behavior of the old
+ c_common_unsigned_type. In particular, it returns
+ long_unsigned_type_node if passed a long, even when a int would
+ have the same size. This is necessary for warnings to work
+ correctly in archs where sizeof(int) == sizeof(long) */
+
+ type1 = TYPE_MAIN_VARIANT (type);
+ if (type1 == signed_char_type_node || type1 == char_type_node || type1 == unsigned_char_type_node)
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (type1 == integer_type_node || type1 == unsigned_type_node)
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
+ return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
+ if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
+ return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+ if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+ if (type1 == intSI_type_node || type1 == unsigned_intSI_type_node)
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+ if (type1 == intHI_type_node || type1 == unsigned_intHI_type_node)
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+ if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
/* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
the precision; they have precision set to match their range, but
types, and producing a signed or unsigned variant of an
ENUMERAL_TYPE may cause other problems as well. */
+ if (!INTEGRAL_TYPE_P (type)
+ || TYPE_UNSIGNED (type) == unsignedp)
+ return type;
+
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
&& (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
}
\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.
if (TREE_CODE (primop0) != INTEGER_CST)
{
if (val == truthvalue_false_node)
- warning (0, "comparison is always false due to limited range of data type");
+ warning (OPT_Wtype_limits, "comparison is always false due to limited range of data type");
if (val == truthvalue_true_node)
- warning (0, "comparison is always true due to limited range of data type");
+ warning (OPT_Wtype_limits, "comparison is always true due to limited range of data type");
}
if (val != 0)
switch (code)
{
case GE_EXPR:
- /* All unsigned values are >= 0, so we warn if extra warnings
- are requested. However, if OP0 is a constant that is
- >= 0, the signedness of the comparison isn't an issue,
- so suppress the warning. */
- if (extra_warnings && !in_system_header
+ /* All unsigned values are >= 0, so we warn. However,
+ if OP0 is a constant that is >= 0, the signedness of
+ the comparison isn't an issue, so suppress the
+ warning. */
+ if (warn_type_limits && !in_system_header
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (0, "comparison of unsigned expression >= 0 is always true");
+ warning (OPT_Wtype_limits,
+ "comparison of unsigned expression >= 0 is always true");
value = truthvalue_true_node;
break;
case LT_EXPR:
- if (extra_warnings && !in_system_header
+ if (warn_type_limits && !in_system_header
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (0, "comparison of unsigned expression < 0 is always false");
+ warning (OPT_Wtype_limits,
+ "comparison of unsigned expression < 0 is always false");
value = truthvalue_false_node;
break;
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 ();
}
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