int flag_hosted = 1;
-/* Warn if main is suspicious. */
-
-int warn_main;
-
/* ObjC language option variables. */
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
-static tree handle_option_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 void check_function_nonnull (tree, int, tree *);
If -fno-asm is used, D_ASM is added to the mask. If
-fno-gnu-keywords is used, D_EXT is added. If -fno-asm and C in
C89 mode, D_EXT89 is added for both -fno-asm and -fno-gnu-keywords.
- In C with -Wcxx-compat, we warn if D_CXXWARN is set. */
+ In C with -Wc++-compat, we warn if D_CXXWARN is set. */
const struct c_common_resword c_common_reswords[] =
{
{ "__volatile__", RID_VOLATILE, 0 },
{ "asm", RID_ASM, D_ASM },
{ "auto", RID_AUTO, 0 },
- { "bool", RID_BOOL, D_CXXONLY },
+ { "bool", RID_BOOL, D_CXXONLY | D_CXXWARN },
{ "break", RID_BREAK, 0 },
{ "case", RID_CASE, 0 },
- { "catch", RID_CATCH, D_CXX_OBJC },
+ { "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN },
{ "char", RID_CHAR, 0 },
- { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX0X },
- { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X },
- { "class", RID_CLASS, D_CXX_OBJC },
+ { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX0X | D_CXXWARN },
+ { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X | D_CXXWARN },
+ { "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
{ "const", RID_CONST, 0 },
{ "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
{ "continue", RID_CONTINUE, 0 },
- { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X },
+ { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "default", RID_DEFAULT, 0 },
- { "delete", RID_DELETE, D_CXXONLY },
+ { "delete", RID_DELETE, D_CXXONLY | D_CXXWARN },
{ "do", RID_DO, 0 },
{ "double", RID_DOUBLE, 0 },
{ "dynamic_cast", RID_DYNCAST, D_CXXONLY | D_CXXWARN },
{ "else", RID_ELSE, 0 },
{ "enum", RID_ENUM, 0 },
- { "explicit", RID_EXPLICIT, D_CXXONLY },
- { "export", RID_EXPORT, D_CXXONLY },
+ { "explicit", RID_EXPLICIT, D_CXXONLY | D_CXXWARN },
+ { "export", RID_EXPORT, D_CXXONLY | D_CXXWARN },
{ "extern", RID_EXTERN, 0 },
- { "false", RID_FALSE, D_CXXONLY },
+ { "false", RID_FALSE, D_CXXONLY | D_CXXWARN },
{ "float", RID_FLOAT, 0 },
{ "for", RID_FOR, 0 },
- { "friend", RID_FRIEND, D_CXXONLY },
+ { "friend", RID_FRIEND, D_CXXONLY | D_CXXWARN },
{ "goto", RID_GOTO, 0 },
{ "if", RID_IF, 0 },
{ "inline", RID_INLINE, D_EXT89 },
{ "int", RID_INT, 0 },
{ "long", RID_LONG, 0 },
{ "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN },
- { "namespace", RID_NAMESPACE, D_CXXONLY },
- { "new", RID_NEW, D_CXXONLY },
- { "operator", RID_OPERATOR, D_CXXONLY },
- { "private", RID_PRIVATE, D_CXX_OBJC },
- { "protected", RID_PROTECTED, D_CXX_OBJC },
- { "public", RID_PUBLIC, D_CXX_OBJC },
+ { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN },
+ { "new", RID_NEW, D_CXXONLY | 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 },
+ { "public", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN },
{ "register", RID_REGISTER, 0 },
{ "reinterpret_cast", RID_REINTCAST, D_CXXONLY | D_CXXWARN },
{ "restrict", RID_RESTRICT, D_CONLY | D_C99 },
{ "static_cast", RID_STATCAST, D_CXXONLY | D_CXXWARN },
{ "struct", RID_STRUCT, 0 },
{ "switch", RID_SWITCH, 0 },
- { "template", RID_TEMPLATE, D_CXXONLY },
- { "this", RID_THIS, D_CXXONLY },
- { "throw", RID_THROW, D_CXX_OBJC },
- { "true", RID_TRUE, D_CXXONLY },
- { "try", RID_TRY, D_CXX_OBJC },
+ { "template", RID_TEMPLATE, D_CXXONLY | D_CXXWARN },
+ { "this", RID_THIS, D_CXXONLY | D_CXXWARN },
+ { "throw", RID_THROW, D_CXX_OBJC | D_CXXWARN },
+ { "true", RID_TRUE, D_CXXONLY | D_CXXWARN },
+ { "try", RID_TRY, D_CXX_OBJC | D_CXXWARN },
{ "typedef", RID_TYPEDEF, 0 },
- { "typename", RID_TYPENAME, D_CXXONLY },
- { "typeid", RID_TYPEID, D_CXXONLY },
+ { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN },
+ { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN },
{ "typeof", RID_TYPEOF, D_ASM | D_EXT },
{ "union", RID_UNION, 0 },
{ "unsigned", RID_UNSIGNED, 0 },
- { "using", RID_USING, D_CXXONLY },
- { "virtual", RID_VIRTUAL, D_CXXONLY },
+ { "using", RID_USING, D_CXXONLY | D_CXXWARN },
+ { "virtual", RID_VIRTUAL, D_CXXONLY | D_CXXWARN },
{ "void", RID_VOID, 0 },
{ "volatile", RID_VOLATILE, 0 },
{ "wchar_t", RID_WCHAR, D_CXXONLY },
handle_error_attribute },
{ "error", 1, 1, true, false, false,
handle_error_attribute },
- { "option", 1, -1, true, false, false,
- handle_option_attribute },
+ { "target", 1, -1, true, false, false,
+ handle_target_attribute },
{ "optimize", 1, -1, true, false, false,
handle_optimize_attribute },
{ NULL, 0, 0, false, false, false, NULL }
return namep;
}
-/* Expand DECL if it declares an entity not handled by the
- common code. */
-
-int
-c_expand_decl (tree decl)
-{
- if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
- {
- /* Let the back-end know about this variable. */
- if (!anon_aggr_type_p (TREE_TYPE (decl)))
- emit_local_var (decl);
- else
- expand_anon_union_decl (decl, NULL_TREE,
- DECL_ANON_UNION_ELEMS (decl));
- }
- else
- return 0;
-
- return 1;
-}
-
-
/* Return the VAR_DECL for a const char array naming the current
function. If the VAR_DECL has not yet been created, create it
now. RID indicates how it should be formatted and IDENTIFIER_NODE
ID is its name (unfortunately C and C++ hold the RID values of
keywords in different places, so we can't derive RID from ID in
- this language independent code. */
+ this language independent code. LOC is the location of the
+ function. */
tree
-fname_decl (unsigned int rid, tree id)
+fname_decl (location_t loc, unsigned int rid, tree id)
{
unsigned ix;
tree decl = NULL_TREE;
input_location = saved_location;
}
if (!ix && !current_function_decl)
- pedwarn (0, "%qD is not defined outside of function scope", decl);
+ pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
return decl;
}
separate the %d from the 'C'. 'ISO' should not be
translated, but it may be moved after 'C%d' in languages
where modifiers follow nouns. */
- pedwarn (OPT_Woverlength_strings,
+ pedwarn (input_location, OPT_Woverlength_strings,
"string length %qd is greater than the length %qd "
"ISO C%d compilers are required to support",
nchars - 1, nchars_max, relevant_std);
|| TREE_CODE (value) == VECTOR_CST
|| TREE_CODE (value) == COMPLEX_CST)
&& TREE_OVERFLOW (value))
- pedwarn (OPT_Woverflow, "overflow in constant expression");
+ pedwarn (input_location, OPT_Woverflow, "overflow in constant expression");
}
/* The same as above but print an unconditional error. */
return false;
}
-/* Print a warning about if (); or if () .. else; constructs
- via the special empty statement node that we create. INNER_THEN
- and INNER_ELSE are the statement lists of the if and the else
- block. */
-
-void
-empty_if_body_warning (tree inner_then, tree inner_else)
-{
- 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 (IS_EMPTY_STMT (inner_then) && !inner_else)
- warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
- "in an %<if%> statement", EXPR_LOCUS (inner_then));
-
- 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
of `main'. */
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn (0, "first argument of %q+D should be %<int%>", decl);
+ pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
+ decl);
break;
case 2:
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn (0, "second argument of %q+D should be %<char **%>",
- decl);
+ pedwarn (input_location, OPT_Wmain, "second argument of %q+D should be %<char **%>",
+ decl);
break;
case 3:
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn (0, "third argument of %q+D should probably be "
- "%<char **%>", decl);
+ pedwarn (input_location, OPT_Wmain, "third argument of %q+D should probably be "
+ "%<char **%>", decl);
break;
}
}
argument because it's only mentioned in an appendix of the
standard. */
if (argct > 0 && (argct < 2 || argct > 3))
- pedwarn (0, "%q+D takes only zero or two arguments", decl);
+ pedwarn (input_location, OPT_Wmain, "%q+D takes only zero or two arguments", decl);
}
/* True if pointers to distinct types T1 and T2 can be converted to
if (emit_lax_note && !emitted_lax_note)
{
emitted_lax_note = true;
- inform ("use -flax-vector-conversions to permit "
+ inform (input_location, "use -flax-vector-conversions to permit "
"conversions between vectors with differing "
"element types or numbers of subparts");
}
{
bool give_warning = false;
- unsigned int formal_prec = TYPE_PRECISION (type);
+ int i;
+ const int expr_num_operands = TREE_OPERAND_LENGTH (expr);
+ tree expr_type = TREE_TYPE (expr);
if (!warn_conversion && !warn_sign_conversion)
return;
- if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+ /* If any operand is artificial, then this expression was generated
+ by the compiler and we do not warn. */
+ for (i = 0; i < expr_num_operands; i++)
+ {
+ tree op = TREE_OPERAND (expr, i);
+ if (op && DECL_P (op) && DECL_ARTIFICIAL (op))
+ return;
+ }
+
+ switch (TREE_CODE (expr))
{
+ case EQ_EXPR:
+ case NE_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ case TRUTH_NOT_EXPR:
+ /* 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))
+ warning (OPT_Wconversion,
+ "conversion to %qT from boolean expression", type);
+ return;
+
+ case REAL_CST:
+ case INTEGER_CST:
+
/* Warn for real constant that is not an exact integer converted
to integer type. */
- if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
{
- if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+ if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
give_warning = true;
}
/* Warn for an integer constant that does not fit into integer type. */
- else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE
&& !int_fits_type_p (expr, type))
{
- if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+ 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");
- else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
- warning (OPT_Wsign_conversion,
- "conversion of unsigned constant value to negative integer");
+ else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
+ warning (OPT_Wsign_conversion, "conversion of unsigned constant "
+ "value to negative integer");
else
give_warning = true;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
/* Warn for an integer constant that does not fit into real type. */
- if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE)
+ if (TREE_CODE (expr_type) == INTEGER_TYPE)
{
REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
}
/* Warn for a real constant that does not fit into a smaller
real type. */
- else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
- && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+ else if (TREE_CODE (expr_type) == REAL_TYPE
+ && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
{
REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
if (give_warning)
warning (OPT_Wconversion,
"conversion to %qT alters %qT constant value",
- type, TREE_TYPE (expr));
- }
- else /* 'expr' is not a constant. */
- {
- tree expr_type = TREE_TYPE (expr);
+ type, expr_type);
+
+ return;
+
+ case COND_EXPR:
+ {
+ /* In case of COND_EXPR, if both operands are constants or
+ COND_EXPR, then we do not care about the type of COND_EXPR,
+ only about the conversion of each operand. */
+ tree op1 = TREE_OPERAND (expr, 1);
+ tree op2 = TREE_OPERAND (expr, 2);
+
+ 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))
+ {
+ conversion_warning (type, op1);
+ conversion_warning (type, op2);
+ return;
+ }
+ /* Fall through. */
+ }
+
+ default: /* 'expr' is not a constant. */
/* Warn for real types converted to integer types. */
if (TREE_CODE (expr_type) == REAL_TYPE
/* Don't warn for short y; short x = ((int)y & 0xff); */
if (TREE_CODE (expr) == BIT_AND_EXPR
- || TREE_CODE (expr) == BIT_IOR_EXPR
+ || TREE_CODE (expr) == BIT_IOR_EXPR
|| TREE_CODE (expr) == BIT_XOR_EXPR)
{
- /* It both args were extended from a shortest type, use
- that type if that is safe. */
+ /* 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),
/* bitwise */1);
- /* If one of the operands is a non-negative constant
- that fits in the target type, then the type of the
- other operand does not matter. */
if (TREE_CODE (expr) == BIT_AND_EXPR)
{
tree op0 = TREE_OPERAND (expr, 0);
tree op1 = TREE_OPERAND (expr, 1);
+ bool unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+ bool unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+ /* If one of the operands is a non-negative constant
+ that fits in the target type, then the type of the
+ other operand does not matter. */
if ((TREE_CODE (op0) == INTEGER_CST
&& int_fits_type_p (op0, c_common_signed_type (type))
&& 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, c_common_unsigned_type (type))))
+ && int_fits_type_p (op1, c_common_signed_type (type))
+ && 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
+ && int_fits_type_p (op0, type))
+ || (TREE_CODE (op1) == INTEGER_CST
+ && unsigned1
+ && int_fits_type_p (op1, type)))
return;
}
}
/* Warn for integer types converted to smaller integer types. */
- if (formal_prec < TYPE_PRECISION (expr_type))
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
give_warning = true;
/* When they are the same width but different signedness,
then the value may change. */
- else if ((formal_prec == TYPE_PRECISION (expr_type)
+ else if ((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
&& TYPE_UNSIGNED (expr_type) != 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 (expr_type)))
- warning (OPT_Wsign_conversion,
- "conversion to %qT from %qT may change the sign of the result",
+ warning (OPT_Wsign_conversion, "conversion to %qT from %qT "
+ "may change the sign of the result",
type, expr_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);
+ 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);
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
|| !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
/* Warn for real types converted to smaller real types. */
else if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == REAL_TYPE
- && formal_prec < TYPE_PRECISION (expr_type))
+ && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
give_warning = true;
&& DECL_NAME (list->expr))
{
warned_ids = new_tlist (warned_ids, written, NULL_TREE);
- warning (OPT_Wsequence_point, "operation on %qE may be undefined",
- list->expr);
+ warning_at (EXPR_HAS_LOCATION (writer)
+ ? EXPR_LOCATION (writer) : input_location,
+ OPT_Wsequence_point, "operation on %qE may be undefined",
+ list->expr);
}
list = list->next;
}
return;
}
+ case ADDR_EXPR:
+ x = TREE_OPERAND (x, 0);
+ if (DECL_P (x))
+ return;
+ writer = 0;
+ goto restart;
+
default:
/* For other expressions, simply recurse on their operands.
Manual tail recursion for unary expressions.
registered_builtin_types = tree_cons (0, type, registered_builtin_types);
}
-
-\f
-/* Return the minimum number of bits needed to represent VALUE in a
- signed or unsigned type, UNSIGNEDP says which. */
-
-unsigned int
-min_precision (tree value, int unsignedp)
-{
- int log;
-
- /* If the value is negative, compute its negative minus 1. The latter
- adjustment is because the absolute value of the largest negative value
- is one larger than the largest positive value. This is equivalent to
- a bit-wise negation, so use that operation instead. */
-
- if (tree_int_cst_sgn (value) < 0)
- value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
-
- /* Return the number of bits needed, taking into account the fact
- that we need one more bit for a signed than unsigned type. */
-
- if (integer_zerop (value))
- log = 0;
- else
- log = tree_floor_log2 (value);
-
- return log + 1 + !unsignedp;
-}
\f
/* Print an error message for invalid operands to arith operation
- CODE with TYPE0 for operand 0, and TYPE1 for operand 1. */
+ CODE with TYPE0 for operand 0, and TYPE1 for operand 1.
+ LOCATION is the location of the message. */
void
-binary_op_error (enum tree_code code, tree type0, tree type1)
+binary_op_error (location_t location, enum tree_code code,
+ tree type0, tree type1)
{
const char *opname;
default:
gcc_unreachable ();
}
- error ("invalid operands to binary %s (have %qT and %qT)", opname,
- type0, type1);
+ error_at (location,
+ "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 (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (input_location, 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 (pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (input_location, 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 (pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to member function used in arithmetic");
size_exp = integer_one_node;
}
/* Convert both subexpression types to the type of intop,
because weird cases involving pointer arithmetic
can result in a sum or difference with different type args. */
- ptrop = build_binary_op (subcode, ptrop,
+ ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
+ subcode, ptrop,
convert (int_type, TREE_OPERAND (intop, 1)), 1);
intop = convert (int_type, TREE_OPERAND (intop, 0));
}
Do this multiplication as signed, then convert to the appropriate
type for the pointer operation. */
intop = convert (sizetype,
- build_binary_op (MULT_EXPR, intop,
+ build_binary_op (EXPR_LOCATION (intop),
+ MULT_EXPR, intop,
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
have been validated to be of suitable type; otherwise, a bad
diagnostic may result.
+ The EXPR is located at LOCATION.
+
This preparation consists of taking the ordinary
representation of an expression expr and producing a valid tree
boolean expression describing whether expr is nonzero. We could
The resulting type should always be `truthvalue_type_node'. */
tree
-c_common_truthvalue_conversion (tree expr)
+c_common_truthvalue_conversion (location_t location, tree expr)
{
switch (TREE_CODE (expr))
{
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
return build2 (TREE_CODE (expr), truthvalue_type_node,
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)));
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)));
case TRUTH_NOT_EXPR:
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
return build1 (TREE_CODE (expr), truthvalue_type_node,
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)));
case ERROR_MARK:
return expr;
: truthvalue_false_node;
case FUNCTION_DECL:
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = build_unary_op (location, ADDR_EXPR, expr, 0);
/* Fall through. */
case ADDR_EXPR:
if (decl_with_nonnull_addr_p (inner))
{
/* Common Ada/Pascal programmer's mistake. */
- warning (OPT_Waddress,
- "the address of %qD will always evaluate as %<true%>",
- inner);
+ warning_at (location,
+ OPT_Waddress,
+ "the address of %qD will always evaluate as %<true%>",
+ inner);
return truthvalue_true_node;
}
}
case COMPLEX_EXPR:
- return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+ return build_binary_op (EXPR_LOCATION (expr),
+ (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)),
0);
case NEGATE_EXPR:
case ABS_EXPR:
case FLOAT_EXPR:
/* These don't change whether an object is nonzero or zero. */
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build2 (COMPOUND_EXPR, truthvalue_type_node,
TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ c_common_truthvalue_conversion
+ (location, TREE_OPERAND (expr, 0)));
else
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0));
case COND_EXPR:
/* Distribute the conversion into the arms of a COND_EXPR. */
return fold_build3 (COND_EXPR, truthvalue_type_node,
TREE_OPERAND (expr, 0),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)));
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 2)));
CASE_CONVERT:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0));
break;
case MODIFY_EXPR:
{
tree t = save_expr (expr);
return (build_binary_op
- ((TREE_SIDE_EFFECTS (expr)
+ (EXPR_LOCATION (expr),
+ (TREE_SIDE_EFFECTS (expr)
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
- c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+ c_common_truthvalue_conversion
+ (location,
+ build_unary_op (location, REALPART_EXPR, t, 0)),
+ c_common_truthvalue_conversion
+ (location,
+ build_unary_op (location, IMAGPART_EXPR, t, 0)),
0));
}
tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
FCONST0 (TYPE_MODE
(TREE_TYPE (expr))));
- return build_binary_op (NE_EXPR, expr, fixed_zero_node, 1);
+ return build_binary_op (EXPR_LOCATION (expr),
+ NE_EXPR, expr, fixed_zero_node, 1);
}
- return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
+ return build_binary_op (EXPR_LOCATION (expr),
+ NE_EXPR, expr, integer_zero_node, 1);
}
\f
static void def_builtin_1 (enum built_in_function fncode,
if (is_sizeof)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (input_location, 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 (pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %qs to a void type", op_name);
else if (!complain)
return error_mark_node;
/* Case ranges are a GNU extension. */
if (high_value)
- pedwarn (OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"range expressions in switch statements are non-standard");
type = TREE_TYPE (cond);
for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
{
tree value = TREE_VALUE (chain);
+ if (TREE_CODE (value) == CONST_DECL)
+ value = DECL_INITIAL (value);
node = splay_tree_lookup (cases, (splay_tree_key) value);
if (node)
{
}
/* Finish an expression taking the address of LABEL (an
- IDENTIFIER_NODE). Returns an expression for the address. */
+ IDENTIFIER_NODE). Returns an expression for the address.
+
+ LOC is the location for the expression returned. */
tree
-finish_label_address_expr (tree label)
+finish_label_address_expr (tree label, location_t loc)
{
tree result;
- pedwarn (OPT_pedantic, "taking the address of a label is non-standard");
+ pedwarn (input_location, OPT_pedantic, "taking the address of a label is non-standard");
if (label == error_mark_node)
return error_mark_node;
/* The current function in 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);
}
return result;
name, "cold");
*no_add_attrs = true;
}
- else
- {
- tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
- /* If we are not at -O3, but are optimizing, turn on -O3
- optimizations just for this one function. */
- if (((optimize > 0 && optimize < 3) || optimize_size)
- && targetm.target_option.hot_attribute_sets_optimization
- && (!old_opts || old_opts == optimization_default_node))
- {
- /* Create the hot optimization node if needed. */
- if (!optimization_hot_node)
- {
- struct cl_optimization current_options;
- static const char *os_argv[] = { NULL, "-O3", NULL };
-
- cl_optimization_save (¤t_options);
- decode_options (2, os_argv);
- optimization_hot_node = build_optimization_node ();
- cl_optimization_restore (¤t_options);
- }
-
- DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
- = optimization_hot_node;
- }
- /* Most of the rest of the hot processing is done later with
- lookup_attribute. */
- }
+ /* Most of the rest of the hot processing is done later with
+ lookup_attribute. */
}
else
{
name, "hot");
*no_add_attrs = true;
}
- else
- {
- tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
- /* If we are optimizing, but not optimizing for space, turn on -Os
- optimizations just for this one function. */
- if (optimize && !optimize_size
- && targetm.target_option.cold_attribute_sets_optimization
- && (!old_opts || old_opts == optimization_default_node))
- {
- /* Create the cold optimization node if needed. */
- if (!optimization_cold_node)
- {
- struct cl_optimization current_options;
- static const char *os_argv[] = { NULL, "-Os", NULL };
-
- cl_optimization_save (¤t_options);
- decode_options (2, os_argv);
- optimization_cold_node = build_optimization_node ();
- cl_optimization_restore (¤t_options);
- }
-
- DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
- = optimization_cold_node;
- }
- /* Most of the rest of the cold processing is done later with
- lookup_attribute. */
- }
+ /* Most of the rest of the cold processing is done later with
+ lookup_attribute. */
}
else
{
/* We must ignore the attribute when it is associated with
local-scoped decls, since attribute alias is ignored and many
such symbols do not even have a DECL_WEAK field. */
- if (decl_function_context (*node) || current_function_decl)
+ if (decl_function_context (*node)
+ || current_function_decl
+ || (TREE_CODE (*node) != VAR_DECL && TREE_CODE (*node) != FUNCTION_DECL))
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
return NULL_TREE;
}
-/* For handling "option" attribute. arguments as in
- struct attribute_spec.handler. */
+/* Handle a "target" attribute. */
static tree
-handle_option_attribute (tree *node, tree name, tree args, int flags,
+handle_target_attribute (tree *node, tree name, tree args, int flags,
bool *no_add_attrs)
{
/* Ensure we have a function type. */
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
}
- else if (targetm.target_option.valid_attribute_p
- == default_target_option_valid_attribute_p)
- {
- warning (OPT_Wattributes,
- "%qE attribute is not supported on this machine",
- name);
- *no_add_attrs = true;
- }
else if (! targetm.target_option.valid_attribute_p (*node, name, args,
flags))
*no_add_attrs = true;
/* This is a naked call, as opposed to a GIMPLE_CALL with an
LHS. All calls whose value is ignored should be
represented like this. Look for the attribute. */
- fdecl = gimple_call_fn (g);
- if (TREE_CODE (fdecl) == FUNCTION_DECL)
- ftype = TREE_TYPE (fdecl);
- else
- {
- ftype = TREE_TYPE (fdecl);
- /* Look past pointer-to-function to the function type itself. */
- ftype = TREE_TYPE (ftype);
- }
+ fdecl = gimple_call_fndecl (g);
+ ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{
return error_mark_node;
case CALL_EXPR:
+ case TARGET_EXPR:
error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
return error_mark_node;
/* Implement -Wparentheses for the unexpected C precedence rules, to
cover cases like x + y << z which readers are likely to
misinterpret. We have seen an expression in which CODE is a binary
- operator used to combine expressions headed by CODE_LEFT and
- CODE_RIGHT. CODE_LEFT and CODE_RIGHT may be ERROR_MARK, which
- means that that side of the expression was not formed using a
- binary operator, or it was enclosed in parentheses. */
+ operator used to combine expressions ARG_LEFT and ARG_RIGHT, which
+ before folding had CODE_LEFT and CODE_RIGHT. CODE_LEFT and
+ CODE_RIGHT may be ERROR_MARK, which means that that side of the
+ expression was not formed using a binary or unary operator, or it
+ was enclosed in parentheses. */
void
-warn_about_parentheses (enum tree_code code, enum tree_code code_left,
- enum tree_code code_right)
+warn_about_parentheses (enum tree_code code,
+ enum tree_code code_left, tree ARG_UNUSED (arg_left),
+ enum tree_code code_right, tree arg_right)
{
if (!warn_parentheses)
return;
- if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+ /* This macro tests that the expression ARG with original tree code
+ CODE appears to be a boolean expression. or the result of folding a
+ boolean expression. */
+#define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG) \
+ (truth_value_p (TREE_CODE (ARG)) \
+ || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE \
+ /* Folding may create 0 or 1 integers from other expressions. */ \
+ || ((CODE) != INTEGER_CST \
+ && (integer_onep (ARG) || integer_zerop (ARG))))
+
+ switch (code)
{
- if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
- || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+ case LSHIFT_EXPR:
+ if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around + or - inside shift");
- }
+ "suggest parentheses around %<+%> inside %<<<%>");
+ else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+ warning (OPT_Wparentheses,
+ "suggest parentheses around %<-%> inside %<<<%>");
+ return;
- if (code == TRUTH_ORIF_EXPR)
- {
- if (code_left == TRUTH_ANDIF_EXPR
- || code_right == TRUTH_ANDIF_EXPR)
+ case RSHIFT_EXPR:
+ if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around && within ||");
- }
+ "suggest parentheses around %<+%> inside %<>>%>");
+ else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+ warning (OPT_Wparentheses,
+ "suggest parentheses around %<-%> inside %<>>%>");
+ return;
- if (code == BIT_IOR_EXPR)
- {
+ case TRUTH_ORIF_EXPR:
+ if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
+ warning (OPT_Wparentheses,
+ "suggest parentheses around %<&&%> within %<||%>");
+ return;
+
+ case BIT_IOR_EXPR:
if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
|| code_left == PLUS_EXPR || code_left == MINUS_EXPR
|| code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around arithmetic in operand of |");
+ "suggest parentheses around arithmetic in operand of %<|%>");
/* Check cases like x|y==z */
- if (TREE_CODE_CLASS (code_left) == tcc_comparison
- || TREE_CODE_CLASS (code_right) == tcc_comparison)
+ else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+ || TREE_CODE_CLASS (code_right) == tcc_comparison)
warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of |");
- }
+ "suggest parentheses around comparison in operand of %<|%>");
+ /* Check cases like !x | y */
+ else if (code_left == TRUTH_NOT_EXPR
+ && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+ warning (OPT_Wparentheses, "suggest parentheses around operand of"
+ "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
+ return;
- if (code == BIT_XOR_EXPR)
- {
+ case BIT_XOR_EXPR:
if (code_left == BIT_AND_EXPR
|| code_left == PLUS_EXPR || code_left == MINUS_EXPR
|| code_right == BIT_AND_EXPR
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around arithmetic in operand of ^");
+ "suggest parentheses around arithmetic in operand of %<^%>");
/* Check cases like x^y==z */
- if (TREE_CODE_CLASS (code_left) == tcc_comparison
- || TREE_CODE_CLASS (code_right) == tcc_comparison)
+ else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+ || TREE_CODE_CLASS (code_right) == tcc_comparison)
warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of ^");
- }
+ "suggest parentheses around comparison in operand of %<^%>");
+ return;
- if (code == BIT_AND_EXPR)
- {
- if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
- || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+ case BIT_AND_EXPR:
+ if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around + or - in operand of &");
+ "suggest parentheses around %<+%> in operand of %<&%>");
+ else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+ warning (OPT_Wparentheses,
+ "suggest parentheses around %<-%> in operand of %<&%>");
/* Check cases like x&y==z */
- if (TREE_CODE_CLASS (code_left) == tcc_comparison
- || TREE_CODE_CLASS (code_right) == tcc_comparison)
+ else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+ || TREE_CODE_CLASS (code_right) == tcc_comparison)
warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of &");
- }
+ "suggest parentheses around comparison in operand of %<&%>");
+ /* Check cases like !x & y */
+ else if (code_left == TRUTH_NOT_EXPR
+ && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+ warning (OPT_Wparentheses, "suggest parentheses around operand of"
+ "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
+ return;
- if (code == EQ_EXPR || code == NE_EXPR)
- {
+ case EQ_EXPR:
if (TREE_CODE_CLASS (code_left) == tcc_comparison
|| TREE_CODE_CLASS (code_right) == tcc_comparison)
warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of %s",
- code == EQ_EXPR ? "==" : "!=");
- }
- else if (TREE_CODE_CLASS (code) == tcc_comparison)
- {
- if ((TREE_CODE_CLASS (code_left) == tcc_comparison
- && code_left != NE_EXPR && code_left != EQ_EXPR)
- || (TREE_CODE_CLASS (code_right) == tcc_comparison
- && code_right != NE_EXPR && code_right != EQ_EXPR))
- warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
+ "suggest parentheses around comparison in operand of %<==%>");
+ return;
+ case NE_EXPR:
+ if (TREE_CODE_CLASS (code_left) == tcc_comparison
+ || TREE_CODE_CLASS (code_right) == tcc_comparison)
+ warning (OPT_Wparentheses,
+ "suggest parentheses around comparison in operand of %<!=%>");
+ return;
+
+ default:
+ if (TREE_CODE_CLASS (code) == tcc_comparison
+ && ((TREE_CODE_CLASS (code_left) == tcc_comparison
+ && code_left != NE_EXPR && code_left != EQ_EXPR)
+ || (TREE_CODE_CLASS (code_right) == tcc_comparison
+ && code_right != NE_EXPR && code_right != EQ_EXPR)))
+ warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
"have their mathematical meaning");
+ return;
}
+#undef NOT_A_BOOLEAN_EXPR_P
}
/* If LABEL (a LABEL_DECL) has not been used, issue a warning. */
struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
#endif
-/* Warn for division by zero according to the value of DIVISOR. */
+/* Warn for division by zero according to the value of DIVISOR. LOC
+ is the location of the division operator. */
void
-warn_for_div_by_zero (tree divisor)
+warn_for_div_by_zero (location_t loc, tree divisor)
{
/* If DIVISOR is zero, and has integral or fixed-point type, issue a warning
about division by zero. Do not issue a warning if DIVISOR has a
generating a NaN. */
if (skip_evaluation == 0
&& (integer_zerop (divisor) || fixed_zerop (divisor)))
- warning (OPT_Wdiv_by_zero, "division by zero");
+ warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
+}
+
+/* Subroutine of build_binary_op. Give warnings for comparisons
+ between signed and unsigned quantities that may fail. Do the
+ checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
+ so that casts will be considered, but default promotions won't
+ be.
+
+ LOCATION is the location of the comparison operator.
+
+ The arguments of this function map directly to local variables
+ of build_binary_op. */
+
+void
+warn_for_sign_compare (location_t location,
+ 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
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
+ {
+ warning_at (location,
+ OPT_Wsign_compare, "comparison between types %qT and %qT",
+ TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
+ }
+
+ /* Do not warn if the comparison is being done in a signed type,
+ since the signed type will only be chosen if it can represent
+ all the values of the unsigned type. */
+ if (!TYPE_UNSIGNED (result_type))
+ /* OK */;
+ /* Do not warn if both operands are unsigned. */
+ else if (op0_signed == op1_signed)
+ /* OK */;
+ else
+ {
+ tree sop, uop;
+ bool ovf;
+
+ if (op0_signed)
+ sop = orig_op0, uop = orig_op1;
+ else
+ sop = orig_op1, uop = orig_op0;
+
+ STRIP_TYPE_NOPS (sop);
+ STRIP_TYPE_NOPS (uop);
+
+ /* Do not warn if the signed quantity is an unsuffixed integer
+ literal (or some static constant expression involving such
+ literals or a conditional expression involving such literals)
+ and it is non-negative. */
+ if (tree_expr_nonnegative_warnv_p (sop, &ovf))
+ /* OK */;
+ /* Do not warn if the comparison is an equality operation, the
+ unsigned quantity is an integral constant, and it would fit
+ in the result if the result were signed. */
+ else if (TREE_CODE (uop) == INTEGER_CST
+ && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
+ && int_fits_type_p (uop, c_common_signed_type (result_type)))
+ /* OK */;
+ /* In C, do not warn if the unsigned quantity is an enumeration
+ constant and its maximum value would fit in the result if the
+ result were signed. */
+ else if (!c_dialect_cxx() && TREE_CODE (uop) == INTEGER_CST
+ && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
+ && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
+ c_common_signed_type (result_type)))
+ /* OK */;
+ else
+ warning_at (location,
+ 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))
+ {
+ if (TREE_CODE (op0) == BIT_NOT_EXPR)
+ op0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
+ if (TREE_CODE (op1) == BIT_NOT_EXPR)
+ op1 = get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
+
+ if (host_integerp (op0, 0) || host_integerp (op1, 0))
+ {
+ tree primop;
+ HOST_WIDE_INT constant, mask;
+ int unsignedp;
+ unsigned int bits;
+
+ if (host_integerp (op0, 0))
+ {
+ primop = op1;
+ unsignedp = unsignedp1;
+ constant = tree_low_cst (op0, 0);
+ }
+ else
+ {
+ primop = op0;
+ 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)
+ {
+ mask = (~ (HOST_WIDE_INT) 0) << bits;
+ if ((mask & constant) != mask)
+ {
+ if (constant == 0)
+ warning (OPT_Wsign_compare,
+ "promoted ~unsigned is always non-zero");
+ else
+ warning_at (location, OPT_Wsign_compare,
+ "comparison of promoted ~unsigned with constant");
+ }
+ }
+ }
+ else if (unsignedp0 && unsignedp1
+ && (TYPE_PRECISION (TREE_TYPE (op0))
+ < TYPE_PRECISION (result_type))
+ && (TYPE_PRECISION (TREE_TYPE (op1))
+ < TYPE_PRECISION (result_type)))
+ warning_at (location, OPT_Wsign_compare,
+ "comparison of promoted ~unsigned with unsigned");
+ }
}
#include "gt-c-common.h"