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,
{ NULL, 0, 0, false, false, false, NULL }
};
-/* Functions called automatically at the beginning and end of execution. */
-
-tree static_ctors;
-tree static_dtors;
-
/* Push current bindings for the function name VAR_DECLS. */
void
strict aliasing mode is in effect. OTYPE is the original
TREE_TYPE of EXPR, and TYPE the type we're casting to. */
-void
+bool
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
+ if (!(flag_strict_aliasing && POINTER_TYPE_P (type)
+ && POINTER_TYPE_P (otype) && !VOID_TYPE_P (TREE_TYPE (type))))
+ return false;
+
+ if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR
&& (DECL_P (TREE_OPERAND (expr, 0))
- || handled_component_p (TREE_OPERAND (expr, 0)))
- && !VOID_TYPE_P (TREE_TYPE (type)))
+ || handled_component_p (TREE_OPERAND (expr, 0))))
{
/* 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");
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2)
+ {
+ warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+ "might break strict-aliasing rules");
+ return true;
+ }
else
{
- HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ /* warn_strict_aliasing >= 3. This includes the default (3).
+ Only warn if the cast is dereferenced immediately. */
+ 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");
+ {
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
+ return true;
+ }
+ else if (warn_strict_aliasing == 2
+ && !alias_sets_must_conflict_p (set1, set2))
+ {
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
+ return true;
+ }
}
}
+ else
+ if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype)))
+ {
+ /* At this level, warn for any conversions, even if an address is
+ not taken in the same statement. This will likely produce many
+ false positives, but could be useful to pinpoint problems that
+ are not revealed at higher levels. */
+ 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_must_conflict_p (set1, set2))
+ {
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
+ return true;
+ }
+ }
+
+ return false;
}
/* Print a warning about if (); or if () .. else; constructs
block. */
void
-empty_body_warning (tree inner_then, tree inner_else)
+empty_if_body_warning (tree inner_then, tree inner_else)
{
- if (warn_empty_body)
- {
- if (TREE_CODE (inner_then) == STATEMENT_LIST
- && STATEMENT_LIST_TAIL (inner_then))
- inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt;
+ if (TREE_CODE (inner_then) == STATEMENT_LIST
+ && STATEMENT_LIST_TAIL (inner_then))
+ inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt;
- if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST
- && STATEMENT_LIST_TAIL (inner_else))
- inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt;
+ if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST
+ && STATEMENT_LIST_TAIL (inner_else))
+ inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt;
- if (IS_EMPTY_STMT (inner_then) && !inner_else)
- warning (OPT_Wempty_body, "%Hempty body in an if-statement",
- EXPR_LOCUS (inner_then));
+ if (IS_EMPTY_STMT (inner_then) && !inner_else)
+ warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
+ "in an %<if%> statement", EXPR_LOCUS (inner_then));
- if (inner_else && IS_EMPTY_STMT (inner_else))
- warning (OPT_Wempty_body, "%Hempty body in an else-statement",
- EXPR_LOCUS (inner_else));
- }
+ else if (inner_else && IS_EMPTY_STMT (inner_else))
+ warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
+ "in an %<else%> statement", EXPR_LOCUS (inner_else));
}
/* Warn for unlikely, improbable, or stupid DECL declarations
}
/* Warns if the conversion of EXPR to TYPE may alter a value.
- This function is called from convert_and_check. */
+ This is a helper function for warnings_for_convert_and_check. */
static void
conversion_warning (tree type, tree expr)
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
}
}
-/* Convert EXPR to TYPE, warning about conversion problems with constants.
- Invoke this function on every expression that is converted implicitly,
- i.e. because of language rules and not because of an explicit cast. */
+/* Produce warnings after a conversion. RESULT is the result of
+ converting EXPR to TYPE. This is a helper function for
+ convert_and_check and cp_convert_and_check. */
-tree
-convert_and_check (tree type, tree expr)
+void
+warnings_for_convert_and_check (tree type, tree expr, tree result)
{
- tree result;
-
- if (TREE_TYPE (expr) == type)
- return expr;
-
- result = convert (type, expr);
-
- if (skip_evaluation || TREE_OVERFLOW_P (expr))
- return result;
-
if (TREE_CODE (expr) == INTEGER_CST
&& (TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
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);
+}
+
+
+/* Convert EXPR to TYPE, warning about conversion problems with constants.
+ Invoke this function on every expression that is converted implicitly,
+ i.e. because of language rules and not because of an explicit cast. */
+
+tree
+convert_and_check (tree type, tree expr)
+{
+ tree result;
+
+ if (TREE_TYPE (expr) == type)
+ return expr;
+ result = convert (type, expr);
+
+ if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
+ warnings_for_convert_and_check (type, expr, result);
+
return result;
}
\f
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 ();
}
if (!t)
{
+ tree domain = TYPE_DOMAIN (type);
+
t = build_variant_type_copy (type);
TREE_TYPE (t) = element_type;
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
+ || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (element_type) != element_type
+ || (domain && TYPE_CANONICAL (domain) != domain))
+ {
+ tree unqualified_canon
+ = build_array_type (TYPE_CANONICAL (element_type),
+ domain? TYPE_CANONICAL (domain)
+ : NULL_TREE);
+ TYPE_CANONICAL (t)
+ = c_build_qualified_type (unqualified_canon, type_quals);
+ }
+ else
+ TYPE_CANONICAL (t) = t;
}
return 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
}
/* 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 ();
}
return t;
}
+/* Recursively remove pointer or array type from TYPE. */
+tree
+strip_pointer_or_array_types (tree t)
+{
+ while (TREE_CODE (t) == ARRAY_TYPE || POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return t;
+}
+
/* Used to compare case labels. K1 and K2 are actually tree nodes
representing case labels, or NULL_TREE for a `default' label.
Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
void
c_expand_body (tree fndecl)
{
-
- if (!DECL_INITIAL (fndecl)
- || DECL_INITIAL (fndecl) == error_mark_node)
- return;
-
tree_rest_of_compilation (fndecl);
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
- decl_init_priority_lookup (fndecl));
- if (DECL_STATIC_DESTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
- decl_fini_priority_lookup (fndecl));
}
/* Hook used by staticp to handle language-specific tree codes. */
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. */
if (TREE_CODE (position) != INTEGER_CST)
{
- warning (0, "requested position is not an integer constant");
+ warning (OPT_Wattributes,
+ "requested position is not an integer constant");
*no_add_attrs = true;
}
else
{
if (tree_int_cst_lt (position, integer_zero_node))
{
- warning (0, "requested position is less than zero");
+ warning (OPT_Wattributes,
+ "requested position is less than zero");
*no_add_attrs = true;
}
}
/* 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
}
}
-/* If FNDECL is a static constructor or destructor, add it to the list
- of functions to be called by the file scope initialization
- function. */
-
-void
-c_record_cdtor_fn (tree fndecl)
-{
- if (targetm.have_ctors_dtors)
- return;
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl))
- static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
- if (DECL_STATIC_DESTRUCTOR (fndecl))
- static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-}
-
-/* Synthesize a function which calls all the global ctors or global
- dtors in this file. This is only used for targets which do not
- support .ctors/.dtors sections. FIXME: Migrate into cgraph. */
-static void
-build_cdtor (int method_type, tree cdtors)
-{
- tree body = 0;
-
- if (!cdtors)
- return;
-
- for (; cdtors; cdtors = TREE_CHAIN (cdtors))
- append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
- &body);
-
- cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
-}
+#ifndef TARGET_HAS_TARGETCM
+struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
+#endif
-/* Generate functions to call static constructors and destructors
- for targets that do not support .ctors/.dtors sections. These
- functions have magic names which are detected by collect2. */
+/* Warn for division by zero according to the value of DIVISOR. */
void
-c_build_cdtor_fns (void)
+warn_for_div_by_zero (tree divisor)
{
- if (!targetm.have_ctors_dtors)
- {
- build_cdtor ('I', static_ctors);
- static_ctors = NULL_TREE;
- build_cdtor ('D', static_dtors);
- static_dtors = NULL_TREE;
- }
- else
- {
- gcc_assert (!static_ctors);
- gcc_assert (!static_dtors);
- }
+ /* If DIVISOR is zero, and has integral type, issue a warning about
+ division by zero. Do not issue a warning if DIVISOR has a
+ floating-point type, since we consider 0.0/0.0 a valid way of
+ generating a NaN. */
+ if (skip_evaluation == 0 && integer_zerop (divisor))
+ warning (OPT_Wdiv_by_zero, "division by zero");
}
-#ifndef TARGET_HAS_TARGETCM
-struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
-#endif
-
#include "gt-c-common.h"