/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
-#include "varray.h"
-#include "expr.h"
+#include "expr.h" /* For vector_mode_valid_p */
#include "c-common.h"
#include "tm_p.h"
#include "obstack.h"
#include "real.h"
#include "cgraph.h"
#include "target-def.h"
-#include "gimple.h"
#include "fixed-value.h"
#include "libfuncs.h"
int flag_isoc94;
-/* Nonzero means use the ISO C99 dialect of C. */
+/* Nonzero means use the ISO C99 (or C1X) dialect of C. */
int flag_isoc99;
+/* Nonzero means use the ISO C1X dialect of C. */
+
+int flag_isoc1x;
+
/* Nonzero means that we have builtin functions, and main is an int. */
int flag_hosted = 1;
int flag_pretty_templates = 1;
-/* Nonzero means warn about implicit declarations. */
-
-int warn_implicit = 1;
-
/* Maximum template instantiation depth. This limit exists to limit the
time it takes to notice infinite template instantiations; the default
value of 1024 is likely to be in the next C++ standard. */
static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fnspec_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);
{ "_Fract", RID_FRACT, D_CONLY | D_EXT },
{ "_Accum", RID_ACCUM, D_CONLY | D_EXT },
{ "_Sat", RID_SAT, D_CONLY | D_EXT },
+ { "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 },
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 },
{ "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN },
{ "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN },
{ "new", RID_NEW, D_CXXONLY | D_CXXWARN },
+ { "nullptr", RID_NULLPTR, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN },
{ "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN },
{ "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN },
{ "inout", RID_INOUT, D_OBJC },
{ "oneway", RID_ONEWAY, D_OBJC },
{ "out", RID_OUT, D_OBJC },
+
+#ifdef TARGET_ADDR_SPACE_KEYWORDS
+ /* Any address space keywords recognized by the target. */
+ TARGET_ADDR_SPACE_KEYWORDS,
+#endif
};
const unsigned int num_c_common_reswords =
handle_target_attribute },
{ "optimize", 1, -1, true, false, false,
handle_optimize_attribute },
+ /* For internal use (marking of builtins and runtime functions) only.
+ The name contains space to prevent its usage in source code. */
+ { "fn spec", 1, 1, false, true, true,
+ handle_fnspec_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
{ NULL, 0, 0, false, false, false, NULL }
};
+/* Return identifier for address space AS. */
+const char *
+c_addr_space_name (addr_space_t as)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_c_common_reswords; i++)
+ if (c_common_reswords[i].rid == RID_FIRST_ADDR_SPACE + as)
+ return c_common_reswords[i].word;
+
+ gcc_unreachable ();
+}
+
/* Push current bindings for the function name VAR_DECLS. */
void
op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (op0 != orig_op0)
ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
if (ret != expr)
op3 = TREE_OPERAND (expr, 3);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1)
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != MODIFY_EXPR
&& code != PREDECREMENT_EXPR
&& code != PREINCREMENT_EXPR
if (code != MODIFY_EXPR)
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
ret = in_init
orig_op0 = op0 = TREE_OPERAND (expr, 0);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
op0 = decl_constant_value_for_optimization (op0);
if (op0 != orig_op0 || in_init)
orig_op0 = op0 = TREE_OPERAND (expr, 0);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ STRIP_TYPE_NOPS (op0);
unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
? truthvalue_false_node
: truthvalue_true_node));
c_inhibit_evaluation_warnings += unused_p;
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
c_inhibit_evaluation_warnings -= unused_p;
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
orig_op2 = op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ STRIP_TYPE_NOPS (op0);
c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+ STRIP_TYPE_NOPS (op2);
c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
void
constant_expression_warning (tree value)
{
- if (warn_overflow && pedantic
+ if (warn_overflow && pedantic
&& (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
|| TREE_CODE (value) == FIXED_CST
|| TREE_CODE (value) == VECTOR_CST
case INTEGER_CST:
warning_at (loc, OPT_Woverflow, "integer overflow in expression");
break;
-
+
case REAL_CST:
warning_at (loc, OPT_Woverflow,
"floating point overflow in expression");
break;
-
+
case FIXED_CST:
warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
break;
case VECTOR_CST:
warning_at (loc, OPT_Woverflow, "vector overflow in expression");
break;
-
+
case COMPLEX_CST:
if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
warning_at (loc, OPT_Woverflow,
had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */
void
warn_logical_operator (location_t location, enum tree_code code, tree type,
- enum tree_code code_left, tree op_left,
+ enum tree_code code_left, tree op_left,
enum tree_code ARG_UNUSED (code_right), tree op_right)
{
int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
-
+
/* If this is an OR operation, invert both sides; we will invert
again at the end. */
if (or_op)
in0_p = !in0_p, in1_p = !in1_p;
-
+
/* If both expressions are the same, if we can merge the ranges, and we
can build the range test, return it or it inverted. */
if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
}
else
{
- /* warn_strict_aliasing >= 3. This includes the default (3).
+ /* warn_strict_aliasing >= 3. This includes the default (3).
Only warn if the cast is dereferenced immediately. */
alias_set_type set1 =
get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
+ pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
decl);
break;
both args are zero-extended or both are sign-extended.
Otherwise, we might change the result.
Eg, (short)-1 | (unsigned short)-1 is (int)-1
- but calculated in (unsigned short) it would be (unsigned short)-1.
+ but calculated in (unsigned short) it would be (unsigned short)-1.
*/
tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
{
from signed char and that RESULT_TYPE is long long int.
If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
like
-
+
(long long int) (unsigned int) signed_char
which get_narrower would narrow down to
-
+
(unsigned int) signed char
-
+
If we do not cast OP0 first, get_narrower would return
signed_char, which is inconsistent with the case of the
explicit cast. */
/* Handle the case that OP0 (or OP1) does not *contain* a conversion
but it *requires* conversion to FINAL_TYPE. */
-
+
if ((TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& TREE_TYPE (op0) != result_type)
== TYPE_PRECISION (TREE_TYPE (arg1)))
&& TREE_TYPE (op1) != result_type)
unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
-
+
/* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
-
+
/* For bitwise operations, signedness of nominal type
does not matter. Consider only how operands were extended. */
if (bitwise)
uns = unsigned0;
-
+
/* Note that in all three cases below we refrain from optimizing
an unsigned operation on sign-extended args.
That would not be valid. */
-
+
/* Both args variable: if both extended in same way
from same width, do it in that width.
Do it unsigned if args were zero-extended. */
/* Conversion from boolean to a signed:1 bit-field (which only
can hold the values 0 and -1) doesn't lose information - but
it does change the value. */
- if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
+ if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
warning (OPT_Wconversion,
"conversion to %qT from boolean expression", type);
return;
&& TREE_CODE (type) == INTEGER_TYPE
&& !int_fits_type_p (expr, type))
{
- if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
+ if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
&& tree_int_cst_sgn (expr) < 0)
warning (OPT_Wsign_conversion,
"negative integer implicitly converted to unsigned type");
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
- if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
+ if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
|| TREE_CODE (op1) == COND_EXPR)
&& (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
|| TREE_CODE (op2) == COND_EXPR))
expr_type = TREE_TYPE (expr);
/* Don't warn for short y; short x = ((int)y & 0xff); */
- if (TREE_CODE (expr) == BIT_AND_EXPR
- || TREE_CODE (expr) == BIT_IOR_EXPR
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ || TREE_CODE (expr) == BIT_IOR_EXPR
|| TREE_CODE (expr) == BIT_XOR_EXPR)
{
/* If both args were extended from a shortest type,
use that type if that is safe. */
- expr_type = shorten_binary_op (expr_type,
- TREE_OPERAND (expr, 0),
- TREE_OPERAND (expr, 1),
+ expr_type = shorten_binary_op (expr_type,
+ TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1),
/* bitwise */1);
if (TREE_CODE (expr) == BIT_AND_EXPR)
&& int_fits_type_p (op0, c_common_unsigned_type (type)))
|| (TREE_CODE (op1) == INTEGER_CST
&& int_fits_type_p (op1, c_common_signed_type (type))
- && int_fits_type_p (op1,
+ && int_fits_type_p (op1,
c_common_unsigned_type (type))))
return;
/* If constant is unsigned and fits in the target
type, then the result will also fit. */
else if ((TREE_CODE (op0) == INTEGER_CST
- && unsigned0
+ && unsigned0
&& int_fits_type_p (op0, type))
|| (TREE_CODE (op1) == INTEGER_CST
&& unsigned1
}
}
/* Warn for integer types converted to smaller integer types. */
- if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
give_warning = true;
/* When they are the same width but different signedness,
else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == REAL_TYPE)
{
- tree type_low_bound = TYPE_MIN_VALUE (expr_type);
- tree type_high_bound = TYPE_MAX_VALUE (expr_type);
- REAL_VALUE_TYPE real_low_bound
- = real_value_from_int_cst (0, type_low_bound);
- REAL_VALUE_TYPE real_high_bound
- = real_value_from_int_cst (0, type_high_bound);
+ tree type_low_bound, type_high_bound;
+ REAL_VALUE_TYPE real_low_bound, real_high_bound;
+
+ /* Don't warn about char y = 0xff; float x = (int) y; */
+ expr = get_unwidened (expr, 0);
+ expr_type = TREE_TYPE (expr);
+
+ type_low_bound = TYPE_MIN_VALUE (expr_type);
+ type_high_bound = TYPE_MAX_VALUE (expr_type);
+ real_low_bound = real_value_from_int_cst (0, type_low_bound);
+ real_high_bound = real_value_from_int_cst (0, type_high_bound);
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
|| !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
else
conversion_warning (type, expr);
}
- else if (!int_fits_type_p (expr, c_common_unsigned_type (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. */
if (TREE_TYPE (expr) == type)
return expr;
-
+
result = convert (type, expr);
if (c_inhibit_evaluation_warnings == 0
{
call_expr_arg_iterator iter;
tree arg;
- tmp_before = tmp_nosp = 0;
+ tmp_before = tmp_nosp = 0;
verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE);
FOR_EACH_CALL_EXPR_ARG (arg, iter, x)
{
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (OPT_Wtype_limits,
+ warning (OPT_Wtype_limits,
"comparison of unsigned expression >= 0 is always true");
value = truthvalue_true_node;
break;
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (OPT_Wtype_limits,
+ warning (OPT_Wtype_limits,
"comparison of unsigned expression < 0 is always false");
value = truthvalue_false_node;
break;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer of type %<void *%> used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
{
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to a function used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
{
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to member function used in arithmetic");
size_exp = integer_one_node;
}
TYPE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
- Do this multiplication as signed, then convert to the appropriate
- type for the pointer operation. */
- intop = convert (sizetype,
- build_binary_op (loc,
- MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
+ Do this multiplication as signed, then convert to the appropriate type
+ for the pointer operation and disregard an overflow that occured only
+ because of the sign-extension change in the latter conversion. */
+ {
+ tree t = build_binary_op (loc,
+ MULT_EXPR, intop,
+ convert (TREE_TYPE (intop), size_exp), 1);
+ intop = convert (sizetype, t);
+ if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
+ intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
+ TREE_INT_CST_HIGH (intop));
+ }
/* Create the sum or difference. */
if (resultcode == MINUS_EXPR)
return ret;
}
\f
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+ and if NON_CONST is known not to be permitted in an evaluated part
+ of a constant expression. */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+ bool nowarning = TREE_NO_WARNING (expr);
+ location_t loc = EXPR_LOCATION (expr);
+
+ /* This should never be called for C++. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING. */
+ STRIP_TYPE_NOPS (expr);
+ expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+ if (nowarning)
+ TREE_NO_WARNING (expr) = 1;
+ protected_set_expr_location (expr, loc);
+
+ return expr;
+}
+
/* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
around the SAVE_EXPR if needed so that c_fully_fold does not need
expr = c_fully_fold (expr, false, &maybe_const);
expr = save_expr (expr);
if (!maybe_const)
- {
- expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
- C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
- }
+ expr = c_wrap_maybe_const (expr, true);
return expr;
}
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
expr = build2 (TREE_CODE (expr), truthvalue_type_node,
- c_common_truthvalue_conversion (location,
+ c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 0)),
c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 1)));
{
expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion
+ c_common_truthvalue_conversion
(location, TREE_OPERAND (expr, 0)));
goto ret;
}
tree u;
PTR *slot;
+ /* For VLAs, use the alias set of the element type rather than the
+ default of alias set 0 for types compared structurally. */
+ if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t))
+ {
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ return get_alias_set (TREE_TYPE (t));
+ return -1;
+ }
+
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
permit taking the address of a union member and then storing
if (is_sizeof)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %<sizeof%> to a function type");
else if (!complain)
return error_mark_node;
{
if (type_code == VOID_TYPE
&& complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %qs to a void type", op_name);
else if (!complain)
return error_mark_node;
if (complain)
error_at (loc, "invalid application of %qs to incomplete type %qT ",
op_name, type);
- value = size_zero_node;
+ return error_mark_node;
}
else
{
/* Only supported decimal floating point extension if the target
actually supports underlying modes. */
- if (targetm.scalar_mode_supported_p (SDmode)
+ if (targetm.scalar_mode_supported_p (SDmode)
&& targetm.scalar_mode_supported_p (DDmode)
&& targetm.scalar_mode_supported_p (TDmode))
{
/* Case ranges are a GNU extension. */
if (high_value)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"range expressions in switch statements are non-standard");
type = TREE_TYPE (cond);
{
TREE_USED (label) = 1;
result = build1 (ADDR_EXPR, ptr_type_node, label);
- /* The current function in not necessarily uninlinable.
+ /* The current function is not necessarily uninlinable.
Computed gotos are incompatible with inlining, but the value
here could be used only in a diagnostic, for example. */
protected_set_expr_location (result, loc);
#undef DEF_ATTR_TREE_LIST
}
+/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
+ identifier as an argument, so the front end shouldn't look it up. */
+
+bool
+attribute_takes_identifier_p (const_tree attr_id)
+{
+ if (is_attribute_p ("mode", attr_id)
+ || is_attribute_p ("format", attr_id)
+ || is_attribute_p ("cleanup", attr_id))
+ return true;
+ else
+ return targetm.attribute_takes_identifier_p (attr_id);
+}
+
/* Attribute handlers common to C front ends. */
/* Handle a "packed" attribute; arguments as in
{
TREE_USED (node) = 1;
DECL_PRESERVE_P (node) = 1;
+ if (TREE_CODE (node) == VAR_DECL)
+ DECL_READ_P (node) = 1;
}
else
{
|| TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == LABEL_DECL
|| TREE_CODE (decl) == TYPE_DECL)
- TREE_USED (decl) = 1;
+ {
+ TREE_USED (decl) = 1;
+ if (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ DECL_READ_P (decl) = 1;
+ }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
*node = type = build_duplicate_type (type);
}
- TYPE_TRANSPARENT_UNION (type) = 1;
+ TYPE_TRANSPARENT_AGGR (type) = 1;
return NULL_TREE;
}
if (!args)
return DEFAULT_INIT_PRIORITY;
-
+
if (!SUPPORTS_INIT_PRIORITY)
{
if (is_destructor)
if (is_destructor)
warning (0,
"destructor priorities from 0 to %d are reserved "
- "for the implementation",
+ "for the implementation",
MAX_RESERVED_INIT_PRIORITY);
else
warning (0,
"constructor priorities from 0 to %d are reserved "
- "for the implementation",
+ "for the implementation",
MAX_RESERVED_INIT_PRIORITY);
}
return pri;
if (POINTER_TYPE_P (type))
{
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
tree (*fn)(tree, enum machine_mode, bool);
- if (!targetm.valid_pointer_mode (mode))
+ if (!targetm.addr_space.valid_pointer_mode (mode, as))
{
error ("invalid pointer mode %qs", p);
return NULL_TREE;
&& current_function_decl != NULL_TREE
&& !TREE_STATIC (decl))
{
- error_at (DECL_SOURCE_LOCATION (decl),
+ error_at (DECL_SOURCE_LOCATION (decl),
"section attribute cannot be specified for "
"local variables");
*no_add_attrs = true;
}
else if (is_type)
{
+ if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ /* OK, modify the type in place. */;
/* If we have a TYPE_DECL, then copy the type, so that we
don't accidentally modify a builtin type. See pushdecl. */
- if (decl && TREE_TYPE (decl) != error_mark_node
- && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
+ else if (decl && TREE_TYPE (decl) != error_mark_node
+ && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
{
tree tt = TREE_TYPE (decl);
*type = build_variant_type_copy (*type);
TREE_USED (*type) = TREE_USED (decl);
TREE_TYPE (decl) = *type;
}
- else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ else
*type = build_variant_type_copy (*type);
TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT;
*no_add_attrs = true;
}
else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || (TREE_CODE (decl) != FUNCTION_DECL
+ || (TREE_CODE (decl) != FUNCTION_DECL
&& TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
/* A static variable declaration is always a tentative definition,
but the alias is a non-tentative definition which overrides. */
- || (TREE_CODE (decl) != FUNCTION_DECL
+ || (TREE_CODE (decl) != FUNCTION_DECL
&& ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
{
error ("%q+D defined both normally and as an alias", decl);
tree position = TREE_VALUE (args);
if (TREE_CODE (position) != INTEGER_CST
- || TREE_INT_CST_HIGH (position)
+ || TREE_INT_CST_HIGH (position)
|| TREE_INT_CST_LOW (position) < 1
|| TREE_INT_CST_LOW (position) > arg_count )
{
- warning (OPT_Wattributes,
+ warning (OPT_Wattributes,
"alloc_size parameter outside range");
*no_add_attrs = true;
return NULL_TREE;
return NULL_TREE;
}
+/* Handle a "fn spec" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
+ tree args, int ARG_UNUSED (flags),
+ bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+ gcc_assert (args
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+ && !TREE_CHAIN (args));
+ return NULL_TREE;
+}
+
/* Handle a "returns_twice" attribute; arguments as in
struct attribute_spec.handler. */
if (TREE_CODE (position) != INTEGER_CST)
{
- warning (OPT_Wattributes,
+ warning (OPT_Wattributes,
"requested position is not an integer constant");
*no_add_attrs = true;
}
bool * ARG_UNUSED (no_add_attrs))
{
tree params;
-
+
/* Ensure we have a function type. */
gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
+
params = TYPE_ARG_TYPES (*node);
while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
params = TREE_CHAIN (params);
/* Now parse the options. */
decode_options (opt_argc, opt_argv);
+ targetm.override_options_after_change();
+
/* Don't allow changing -fstrict-aliasing. */
flag_strict_aliasing = saved_flag_strict_aliasing;
(*callback) (ctx, param, param_num);
}
-/* Checks the number of arguments NARGS against the required number
- REQUIRED and issues an error if there is a mismatch. Returns true
- if the number of arguments is correct, otherwise false. */
+/* Checks for a builtin function FNDECL that the number of arguments
+ NARGS against the required number REQUIRED and issues an error if
+ there is a mismatch. Returns true if the number of arguments is
+ correct, otherwise false. */
static bool
-validate_nargs (tree fndecl, int nargs, int required)
+builtin_function_validate_nargs (tree fndecl, int nargs, int required)
{
if (nargs < required)
{
- error ("not enough arguments to function %qE", fndecl);
+ error_at (input_location,
+ "not enough arguments to function %qE", fndecl);
return false;
}
else if (nargs > required)
{
- error ("too many arguments to function %qE", fndecl);
+ error_at (input_location,
+ "too many arguments to function %qE", fndecl);
return false;
}
return true;
switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_CONSTANT_P:
- return validate_nargs (fndecl, nargs, 1);
+ return builtin_function_validate_nargs (fndecl, nargs, 1);
case BUILT_IN_ISFINITE:
case BUILT_IN_ISINF:
case BUILT_IN_ISINF_SIGN:
case BUILT_IN_ISNAN:
case BUILT_IN_ISNORMAL:
- if (validate_nargs (fndecl, nargs, 1))
+ if (builtin_function_validate_nargs (fndecl, nargs, 1))
{
if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE)
{
case BUILT_IN_ISLESSEQUAL:
case BUILT_IN_ISLESSGREATER:
case BUILT_IN_ISUNORDERED:
- if (validate_nargs (fndecl, nargs, 2))
+ if (builtin_function_validate_nargs (fndecl, nargs, 2))
{
enum tree_code code0, code1;
code0 = TREE_CODE (TREE_TYPE (args[0]));
return false;
case BUILT_IN_FPCLASSIFY:
- if (validate_nargs (fndecl, nargs, 6))
+ if (builtin_function_validate_nargs (fndecl, nargs, 6))
{
unsigned i;
-
+
for (i=0; i<5; i++)
if (TREE_CODE (args[i]) != INTEGER_CST)
{
TOKEN, which had the associated VALUE. */
void
-c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
tree value, unsigned char token_flags)
{
#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
if (token_type == CPP_EOF)
message = catenate_messages (gmsgid, " at end of input");
- else if (token_type == CPP_CHAR
- || token_type == CPP_WCHAR
+ else if (token_type == CPP_CHAR
+ || token_type == CPP_WCHAR
|| token_type == CPP_CHAR16
|| token_type == CPP_CHAR32)
{
free (message);
message = NULL;
}
- else if (token_type == CPP_STRING
- || token_type == CPP_WSTRING
+ else if (token_type == CPP_STRING
+ || token_type == CPP_WSTRING
|| token_type == CPP_STRING16
- || token_type == CPP_STRING32)
+ || token_type == CPP_STRING32
+ || token_type == CPP_UTF8STRING)
message = catenate_messages (gmsgid, " before string constant");
else if (token_type == CPP_NUMBER)
message = catenate_messages (gmsgid, " before numeric constant");
#undef catenate_messages
}
+/* Mapping for cpp message reasons to the options that enable them. */
+
+struct reason_option_codes_t
+{
+ const int reason; /* cpplib message reason. */
+ const int option_code; /* gcc option that controls this message. */
+};
+
+static const struct reason_option_codes_t option_codes[] = {
+ {CPP_W_DEPRECATED, OPT_Wdeprecated},
+ {CPP_W_COMMENTS, OPT_Wcomments},
+ {CPP_W_TRIGRAPHS, OPT_Wtrigraphs},
+ {CPP_W_MULTICHAR, OPT_Wmultichar},
+ {CPP_W_TRADITIONAL, OPT_Wtraditional},
+ {CPP_W_LONG_LONG, OPT_Wlong_long},
+ {CPP_W_ENDIF_LABELS, OPT_Wendif_labels},
+ {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros},
+ {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined},
+ {CPP_W_UNDEF, OPT_Wundef},
+ {CPP_W_UNUSED_MACROS, OPT_Wunused_macros},
+ {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat},
+ {CPP_W_NORMALIZE, OPT_Wnormalized_},
+ {CPP_W_INVALID_PCH, OPT_Winvalid_pch},
+ {CPP_W_WARNING_DIRECTIVE, OPT_Wcpp},
+ {CPP_W_NONE, 0}
+};
+
+/* Return the gcc option code associated with the reason for a cpp
+ message, or 0 if none. */
+
+static int
+c_option_controlling_cpp_error (int reason)
+{
+ const struct reason_option_codes_t *entry;
+
+ for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
+ {
+ if (entry->reason == reason)
+ return entry->option_code;
+ }
+ return 0;
+}
+
/* Callback from cpp_error for PFILE to print diagnostics from the
- preprocessor. The diagnostic is of type LEVEL, at location
+ preprocessor. The diagnostic is of type LEVEL, with REASON set
+ to the reason code if LEVEL is represents a warning, at location
LOCATION unless this is after lexing and the compiler's location
should be used instead, with column number possibly overridden by
COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
otherwise. */
bool
-c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
location_t location, unsigned int column_override,
const char *msg, va_list *ap)
{
location, dlevel);
if (column_override)
diagnostic_override_column (&diagnostic, column_override);
+ diagnostic_override_option_index (&diagnostic,
+ c_option_controlling_cpp_error (reason));
ret = report_diagnostic (&diagnostic);
if (level == CPP_DL_WARNING_SYSHDR)
warn_system_headers = save_warn_system_headers;
error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
return error_mark_node;
- case INTEGER_CST:
- gcc_assert (integer_zerop (expr));
- return size_zero_node;
-
case NOP_EXPR:
case INDIRECT_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
- gcc_assert (base == error_mark_node || base == size_zero_node);
- return base;
+ if (!integer_zerop (TREE_OPERAND (expr, 0)))
+ {
+ error ("cannot apply %<offsetof%> to a non constant address");
+ return error_mark_node;
+ }
+ return size_zero_node;
case COMPONENT_REF:
base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
}
t = convert (sizetype, t);
off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+
+ /* Check if the offset goes beyond the upper bound of the array. */
+ if (code == PLUS_EXPR && TREE_CODE (t) == INTEGER_CST)
+ {
+ tree upbound = array_ref_up_bound (expr);
+ if (upbound != NULL_TREE
+ && TREE_CODE (upbound) == INTEGER_CST
+ && !tree_int_cst_equal (upbound,
+ TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+ {
+ upbound = size_binop (PLUS_EXPR, upbound,
+ build_int_cst (TREE_TYPE (upbound), 1));
+ if (tree_int_cst_lt (upbound, t))
+ {
+ tree v;
+
+ for (v = TREE_OPERAND (expr, 0);
+ TREE_CODE (v) == COMPONENT_REF;
+ v = TREE_OPERAND (v, 0))
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ {
+ tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
+ for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
+ if (TREE_CODE (fld_chain) == FIELD_DECL)
+ break;
+
+ if (fld_chain)
+ break;
+ }
+ /* Don't warn if the array might be considered a poor
+ man's flexible array member with a very permissive
+ definition thereof. */
+ if (TREE_CODE (v) == ARRAY_REF
+ || TREE_CODE (v) == COMPONENT_REF)
+ warning (OPT_Warray_bounds,
+ "index %E denotes an offset "
+ "greater than size of %qT",
+ t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ }
+ }
break;
case COMPOUND_EXPR:
if (quals == 0)
unqual_elt = elt;
else
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+ unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
/* Using build_distinct_type_copy and modifying things afterward instead
of using build_array_type to create a new type preserves all of the
/* Make sure we have the canonical MAIN_TYPE. */
hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode);
- hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
+ hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
hashcode);
main_type = type_hash_canon (hashcode, main_type);
else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
|| (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
!= TYPE_DOMAIN (main_type)))
- TYPE_CANONICAL (main_type)
+ TYPE_CANONICAL (main_type)
= build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
else
{
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
tree ptype;
- int number;
unsigned int parmnum;
/* We've declared the implementation functions to use "volatile void *"
call to check_function_arguments what ever type the user used. */
arg_types = TREE_CHAIN (arg_types);
ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
- 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. */
VEC_replace (tree, params, parmnum, val);
arg_types = TREE_CHAIN (arg_types);
- number++;
}
/* The definition of these primitives is variadic, with the remaining
|| ((CODE) != INTEGER_CST \
&& (integer_onep (ARG) || integer_zerop (ARG))))
- switch (code)
+ switch (code)
{
case LSHIFT_EXPR:
if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
The arguments of this function map directly to local variables
of build_binary_op. */
-void
+void
warn_for_sign_compare (location_t location,
- tree orig_op0, tree orig_op1,
- tree op0, tree op1,
+ tree orig_op0, tree orig_op1,
+ tree op0, tree op1,
tree result_type, enum tree_code resultcode)
{
int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
int unsignedp0, unsignedp1;
-
+
/* In C++, check for comparison of different enum types. */
if (c_dialect_cxx()
&& TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
if (op0_signed)
sop = orig_op0, uop = orig_op1;
- else
+ else
sop = orig_op1, uop = orig_op0;
- STRIP_TYPE_NOPS (sop);
+ STRIP_TYPE_NOPS (sop);
STRIP_TYPE_NOPS (uop);
base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
? TREE_TYPE (result_type) : result_type);
&& int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
c_common_signed_type (base_type)))
/* OK */;
- else
+ else
warning_at (location,
- OPT_Wsign_compare,
+ OPT_Wsign_compare,
"comparison between signed and unsigned integer expressions");
}
-
+
/* Warn if two unsigned values are being compared in a size larger
than their original size, and one (and only one) is the result of
a `~' operator. This comparison will always fail.
-
+
Also warn if one operand is a constant, and the constant does not
have all bits set that are set in the ~ operand when it is
extended. */
op0 = get_narrower (op0, &unsignedp0);
op1 = get_narrower (op1, &unsignedp1);
-
+
if ((TREE_CODE (op0) == BIT_NOT_EXPR)
^ (TREE_CODE (op1) == BIT_NOT_EXPR))
{
HOST_WIDE_INT constant, mask;
int unsignedp;
unsigned int bits;
-
+
if (host_integerp (op0, 0))
{
primop = op1;
unsignedp = unsignedp0;
constant = tree_low_cst (op1, 0);
}
-
+
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_LONG && unsignedp)
if ((mask & constant) != mask)
{
if (constant == 0)
- warning (OPT_Wsign_compare,
+ warning (OPT_Wsign_compare,
"promoted ~unsigned is always non-zero");
else
- warning_at (location, OPT_Wsign_compare,
+ warning_at (location, OPT_Wsign_compare,
"comparison of promoted ~unsigned with constant");
}
}