/* 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 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "varray.h"
#include "expr.h"
#include "c-common.h"
-#include "diagnostic.h"
#include "tm_p.h"
#include "obstack.h"
#include "cpplib.h"
#include "tree-inline.h"
#include "c-tree.h"
#include "toplev.h"
+#include "diagnostic.h"
#include "tree-iterator.h"
#include "hashtab.h"
#include "tree-mudflap.h"
#include "target-def.h"
#include "gimple.h"
#include "fixed-value.h"
+#include "libfuncs.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
#define PID_TYPE "int"
#endif
-#ifndef CHAR16_TYPE
+/* If GCC knows the exact uint_least16_t and uint_least32_t types from
+ <stdint.h>, use them for char16_t and char32_t. Otherwise, use
+ these guesses; getting the wrong type of a given width will not
+ affect C++ name mangling because in C++ these are distinct types
+ not typedefs. */
+
+#ifdef UINT_LEAST16_TYPE
+#define CHAR16_TYPE UINT_LEAST16_TYPE
+#else
#define CHAR16_TYPE "short unsigned int"
#endif
-#ifndef CHAR32_TYPE
+#ifdef UINT_LEAST32_TYPE
+#define CHAR32_TYPE UINT_LEAST32_TYPE
+#else
#define CHAR32_TYPE "unsigned int"
#endif
: "long long unsigned int"))
#endif
+/* There are no default definitions of these <stdint.h> types. */
+
+#ifndef SIG_ATOMIC_TYPE
+#define SIG_ATOMIC_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT8_TYPE
+#define INT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT16_TYPE
+#define INT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT32_TYPE
+#define INT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT64_TYPE
+#define INT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT8_TYPE
+#define UINT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT16_TYPE
+#define UINT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT32_TYPE
+#define UINT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT64_TYPE
+#define UINT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST8_TYPE
+#define INT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST16_TYPE
+#define INT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST32_TYPE
+#define INT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST64_TYPE
+#define INT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST8_TYPE
+#define UINT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST16_TYPE
+#define UINT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST32_TYPE
+#define UINT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST64_TYPE
+#define UINT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST8_TYPE
+#define INT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST16_TYPE
+#define INT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST32_TYPE
+#define INT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST64_TYPE
+#define INT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST8_TYPE
+#define UINT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST16_TYPE
+#define UINT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST32_TYPE
+#define UINT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST64_TYPE
+#define UINT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INTPTR_TYPE
+#define INTPTR_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINTPTR_TYPE
+#define UINTPTR_TYPE ((const char *) NULL)
+#endif
+
/* The following symbols are subsumed in the c_global_trees array, and
listed here individually for documentation purposes.
tree unsigned_char_type_node;
tree signed_char_type_node;
tree wchar_type_node;
- tree signed_wchar_type_node;
- tree unsigned_wchar_type_node;
tree char16_type_node;
tree char32_type_node;
This is a count, since unevaluated expressions can nest. */
int skip_evaluation;
+/* Whether lexing has been completed, so subsequent preprocessor
+ errors should use the compiler's input_location. */
+bool done_lexing = false;
+
/* Information about how a function name is generated. */
struct fname_var_t
{
{NULL, 0, 0},
};
+static tree c_fully_fold_internal (tree expr, bool, bool *, bool *);
static tree check_case_value (tree);
static bool check_case_bounds (tree, tree, tree *, tree *);
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 *);
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 (input_location, 0, "%qD is not defined outside of function scope", decl);
+ pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
return decl;
}
return value;
}
\f
+/* Fully fold EXPR, an expression that was not folded (beyond integer
+ constant expressions and null pointer constants) when being built
+ up. If IN_INIT, this is in a static initializer and certain
+ changes are made to the folding done. Clear *MAYBE_CONST if
+ MAYBE_CONST is not NULL and EXPR is definitely not a constant
+ expression because it contains an evaluated operator (in C99) or an
+ operator outside of sizeof returning an integer constant (in C90)
+ not permitted in constant expressions, or because it contains an
+ evaluated arithmetic overflow. (*MAYBE_CONST should typically be
+ set to true by callers before calling this function.) Return the
+ folded expression. Function arguments have already been folded
+ before calling this function, as have the contents of SAVE_EXPR,
+ TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
+ C_MAYBE_CONST_EXPR. */
+
+tree
+c_fully_fold (tree expr, bool in_init, bool *maybe_const)
+{
+ tree ret;
+ tree eptype = NULL_TREE;
+ bool dummy = true;
+ bool maybe_const_itself = true;
+
+ /* This function is not relevant to C++ because C++ folds while
+ parsing, and may need changes to be correct for C++ when C++
+ stops folding while parsing. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ if (!maybe_const)
+ maybe_const = &dummy;
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ {
+ eptype = TREE_TYPE (expr);
+ expr = TREE_OPERAND (expr, 0);
+ }
+ ret = c_fully_fold_internal (expr, in_init, maybe_const,
+ &maybe_const_itself);
+ if (eptype)
+ ret = fold_convert (eptype, ret);
+ *maybe_const &= maybe_const_itself;
+ return ret;
+}
+
+/* Internal helper for c_fully_fold. EXPR and IN_INIT are as for
+ c_fully_fold. *MAYBE_CONST_OPERANDS is cleared because of operands
+ not permitted, while *MAYBE_CONST_ITSELF is cleared because of
+ arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from
+ both evaluated and unevaluated subexpressions while
+ *MAYBE_CONST_ITSELF is carried from only evaluated
+ subexpressions). */
+
+static tree
+c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
+ bool *maybe_const_itself)
+{
+ tree ret = expr;
+ enum tree_code code = TREE_CODE (expr);
+ enum tree_code_class kind = TREE_CODE_CLASS (code);
+ location_t loc = EXPR_LOCATION (expr);
+ tree op0, op1, op2, op3;
+ tree orig_op0, orig_op1, orig_op2;
+ bool op0_const = true, op1_const = true, op2_const = true;
+ bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
+ bool nowarning = TREE_NO_WARNING (expr);
+
+ /* This function is not relevant to C++ because C++ folds while
+ parsing, and may need changes to be correct for C++ when C++
+ stops folding while parsing. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ /* Constants, declarations, statements, errors, SAVE_EXPRs and
+ anything else not counted as an expression cannot usefully be
+ folded further at this point. */
+ if (!IS_EXPR_CODE_CLASS (kind)
+ || kind == tcc_statement
+ || code == SAVE_EXPR)
+ return expr;
+
+ /* Operands of variable-length expressions (function calls) have
+ already been folded, as have __builtin_* function calls, and such
+ expressions cannot occur in constant expressions. */
+ if (kind == tcc_vl_exp)
+ {
+ *maybe_const_operands = false;
+ ret = fold (expr);
+ goto out;
+ }
+
+ if (code == C_MAYBE_CONST_EXPR)
+ {
+ tree pre = C_MAYBE_CONST_EXPR_PRE (expr);
+ tree inner = C_MAYBE_CONST_EXPR_EXPR (expr);
+ if (C_MAYBE_CONST_EXPR_NON_CONST (expr))
+ *maybe_const_operands = false;
+ if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr))
+ *maybe_const_itself = false;
+ if (pre && !in_init)
+ ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
+ else
+ ret = inner;
+ goto out;
+ }
+
+ /* Assignment, increment, decrement, function call and comma
+ operators, and statement expressions, cannot occur in constant
+ expressions if evaluated / outside of sizeof. (Function calls
+ were handled above, though VA_ARG_EXPR is treated like a function
+ call here, and statement expressions are handled through
+ C_MAYBE_CONST_EXPR to avoid folding inside them.) */
+ switch (code)
+ {
+ case MODIFY_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case COMPOUND_EXPR:
+ *maybe_const_operands = false;
+ break;
+
+ case VA_ARG_EXPR:
+ case TARGET_EXPR:
+ case BIND_EXPR:
+ case OBJ_TYPE_REF:
+ *maybe_const_operands = false;
+ ret = fold (expr);
+ goto out;
+
+ default:
+ break;
+ }
+
+ /* Fold individual tree codes as appropriate. */
+ switch (code)
+ {
+ case COMPOUND_LITERAL_EXPR:
+ /* Any non-constancy will have been marked in a containing
+ C_MAYBE_CONST_EXPR; there is no more folding to do here. */
+ goto out;
+
+ case COMPONENT_REF:
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ op1 = TREE_OPERAND (expr, 1);
+ op2 = TREE_OPERAND (expr, 2);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself);
+ if (op0 != orig_op0)
+ ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
+ if (ret != expr)
+ {
+ TREE_READONLY (ret) = TREE_READONLY (expr);
+ TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+ }
+ goto out;
+
+ case ARRAY_REF:
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ orig_op1 = op1 = TREE_OPERAND (expr, 1);
+ op2 = TREE_OPERAND (expr, 2);
+ op3 = TREE_OPERAND (expr, 3);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself);
+ op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+ maybe_const_itself);
+ 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);
+ if (ret != expr)
+ {
+ TREE_READONLY (ret) = TREE_READONLY (expr);
+ TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
+ TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+ }
+ ret = fold (ret);
+ goto out;
+
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case POINTER_PLUS_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case RDIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case COMPLEX_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ case UNORDERED_EXPR:
+ case ORDERED_EXPR:
+ case UNLT_EXPR:
+ case UNLE_EXPR:
+ case UNGT_EXPR:
+ case UNGE_EXPR:
+ case UNEQ_EXPR:
+ /* Binary operations evaluating both arguments (increment and
+ decrement are binary internally in GCC). */
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ orig_op1 = op1 = TREE_OPERAND (expr, 1);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself);
+ if (code != MODIFY_EXPR
+ && code != PREDECREMENT_EXPR
+ && code != PREINCREMENT_EXPR
+ && code != POSTDECREMENT_EXPR
+ && code != POSTINCREMENT_EXPR)
+ op0 = decl_constant_value_for_optimization (op0);
+ /* The RHS of a MODIFY_EXPR was fully folded when building that
+ expression for the sake of conversion warnings. */
+ if (code != MODIFY_EXPR)
+ op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+ maybe_const_itself);
+ op1 = decl_constant_value_for_optimization (op1);
+ if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+ ret = in_init
+ ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
+ : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+ else
+ ret = fold (expr);
+ goto out;
+
+ case INDIRECT_REF:
+ case FIX_TRUNC_EXPR:
+ case FLOAT_EXPR:
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case ADDR_EXPR:
+ case CONJ_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ /* Unary operations. */
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself);
+ if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
+ op0 = decl_constant_value_for_optimization (op0);
+ if (op0 != orig_op0 || in_init)
+ ret = in_init
+ ? fold_build1_initializer (code, TREE_TYPE (expr), op0)
+ : fold_build1 (code, TREE_TYPE (expr), op0);
+ else
+ ret = fold (expr);
+ if (code == INDIRECT_REF
+ && ret != expr
+ && TREE_CODE (ret) == INDIRECT_REF)
+ {
+ TREE_READONLY (ret) = TREE_READONLY (expr);
+ TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
+ TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+ }
+ goto out;
+
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ /* Binary operations not necessarily evaluating both
+ arguments. */
+ 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);
+ op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+ ret = in_init
+ ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
+ : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+ else
+ ret = fold (expr);
+ *maybe_const_operands &= op0_const;
+ *maybe_const_itself &= op0_const_self;
+ if (!(flag_isoc99
+ && op0_const
+ && op0_const_self
+ && (code == TRUTH_ANDIF_EXPR
+ ? op0 == truthvalue_false_node
+ : op0 == truthvalue_true_node)))
+ *maybe_const_operands &= op1_const;
+ if (!(op0_const
+ && op0_const_self
+ && (code == TRUTH_ANDIF_EXPR
+ ? op0 == truthvalue_false_node
+ : op0 == truthvalue_true_node)))
+ *maybe_const_itself &= op1_const_self;
+ goto out;
+
+ case COND_EXPR:
+ orig_op0 = op0 = TREE_OPERAND (expr, 0);
+ orig_op1 = op1 = TREE_OPERAND (expr, 1);
+ orig_op2 = op2 = TREE_OPERAND (expr, 2);
+ op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+ if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
+ ret = fold_build3 (code, TREE_TYPE (expr), op0, op1, op2);
+ else
+ ret = fold (expr);
+ *maybe_const_operands &= op0_const;
+ *maybe_const_itself &= op0_const_self;
+ if (!(flag_isoc99
+ && op0_const
+ && op0_const_self
+ && op0 == truthvalue_false_node))
+ *maybe_const_operands &= op1_const;
+ if (!(op0_const
+ && op0_const_self
+ && op0 == truthvalue_false_node))
+ *maybe_const_itself &= op1_const_self;
+ if (!(flag_isoc99
+ && op0_const
+ && op0_const_self
+ && op0 == truthvalue_true_node))
+ *maybe_const_operands &= op2_const;
+ if (!(op0_const
+ && op0_const_self
+ && op0 == truthvalue_true_node))
+ *maybe_const_itself &= op2_const_self;
+ goto out;
+
+ case EXCESS_PRECISION_EXPR:
+ /* Each case where an operand with excess precision may be
+ encountered must remove the EXCESS_PRECISION_EXPR around
+ inner operands and possibly put one around the whole
+ expression or possibly convert to the semantic type (which
+ c_fully_fold does); we cannot tell at this stage which is
+ appropriate in any particular case. */
+ gcc_unreachable ();
+
+ default:
+ /* Various codes may appear through folding built-in functions
+ and their arguments. */
+ goto out;
+ }
+
+ out:
+ /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
+ have been done by this point, so remove them again. */
+ nowarning |= TREE_NO_WARNING (ret);
+ STRIP_TYPE_NOPS (ret);
+ if (nowarning && !TREE_NO_WARNING (ret))
+ {
+ if (!CAN_HAVE_LOCATION_P (ret))
+ ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+ TREE_NO_WARNING (ret) = 1;
+ }
+ if (ret != expr)
+ protected_set_expr_location (ret, loc);
+ return ret;
+}
+
+/* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
+ return EXP. Otherwise, return either EXP or its known constant
+ value (if it has one), but return EXP if EXP has mode BLKmode. ???
+ Is the BLKmode test appropriate? */
+
+tree
+decl_constant_value_for_optimization (tree exp)
+{
+ tree ret;
+
+ /* This function is only used by C, for c_fully_fold and other
+ optimization, and may not be correct for C++. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ if (!optimize
+ || TREE_CODE (exp) != VAR_DECL
+ || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+ || DECL_MODE (exp) == BLKmode)
+ return exp;
+
+ ret = decl_constant_value (exp);
+ /* Avoid unwanted tree sharing between the initializer and current
+ function's body where the tree can be modified e.g. by the
+ gimplifier. */
+ if (ret != exp && TREE_STATIC (exp))
+ ret = unshare_expr (ret);
+ return ret;
+}
+
/* Print a warning if a constant expression had overflow in folding.
Invoke this function on every expression that the language
requires to be a constant expression.
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'. */
for (i = 0; i < expr_num_operands; i++)
{
tree op = TREE_OPERAND (expr, i);
- if (DECL_P (op) && DECL_ARTIFICIAL (op))
+ if (op && DECL_P (op) && DECL_ARTIFICIAL (op))
return;
}
convert_and_check (tree type, tree expr)
{
tree result;
+ tree expr_for_warning;
+
+ /* Convert from a value with possible excess precision rather than
+ via the semantic type, but do not warn about values not fitting
+ exactly in the semantic type. */
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ {
+ tree orig_type = TREE_TYPE (expr);
+ expr = TREE_OPERAND (expr, 0);
+ expr_for_warning = convert (orig_type, expr);
+ if (orig_type == type)
+ return expr_for_warning;
+ }
+ else
+ expr_for_warning = expr;
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);
+ warnings_for_convert_and_check (type, expr_for_warning, result);
return result;
}
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.
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
- && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (node))
if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_OK (integer_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
#undef TYPE_OK
- if (c_dialect_cxx ())
- return type;
- else
- return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+ return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
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.
of pointer PTROP and integer INTOP. */
tree
-pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
+pointer_int_sum (location_t location, enum tree_code resultcode,
+ tree ptrop, tree intop)
{
tree size_exp, ret;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (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 (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (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 (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (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. */
if (resultcode == MINUS_EXPR)
intop = fold_build1 (NEGATE_EXPR, sizetype, intop);
+ if (TREE_CODE (intop) == INTEGER_CST)
+ {
+ tree offset_node;
+ tree string_cst = string_constant (ptrop, &offset_node);
+
+ if (string_cst != 0
+ && !(offset_node && TREE_CODE (offset_node) != INTEGER_CST))
+ {
+ HOST_WIDE_INT max = TREE_STRING_LENGTH (string_cst);
+ HOST_WIDE_INT offset;
+ if (offset_node == 0)
+ offset = 0;
+ else if (! host_integerp (offset_node, 0))
+ offset = -1;
+ else
+ offset = tree_low_cst (offset_node, 0);
+
+ offset = offset + tree_low_cst (intop, 0);
+ if (offset < 0 || offset > max)
+ warning_at (location, 0,
+ "offset %<%wd%> outside bounds of constant string",
+ tree_low_cst (intop, 0));
+ }
+ }
+
ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
fold_undefer_and_ignore_overflow_warnings ();
return ret;
}
\f
+/* 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
+ to look inside SAVE_EXPRs. */
+
+tree
+c_save_expr (tree expr)
+{
+ bool maybe_const = true;
+ if (c_dialect_cxx ())
+ return save_expr (expr);
+ 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;
+ }
+ return expr;
+}
+
/* Return whether EXPR is a declaration whose address can never be
NULL. */
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:
+ case EXCESS_PRECISION_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)));
+ if (c_dialect_cxx ())
+ return fold_build3 (COND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 0),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr,
+ 1)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr,
+ 2)));
+ else
+ /* Folding will happen later for C. */
+ return build3 (COND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 0),
+ 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:
if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
{
- tree t = save_expr (expr);
+ tree t = c_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,
wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
+ underlying_wchar_type_node = wchar_type_node;
if (c_dialect_cxx ())
{
if (TYPE_UNSIGNED (wchar_type_node))
wchar_type_node = make_signed_type (wchar_type_size);
record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);
}
- else
- {
- signed_wchar_type_node = c_common_signed_type (wchar_type_node);
- unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);
- }
/* This is for wide string constants. */
wchar_array_type_node
uintmax_type_node =
TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));
+ if (SIG_ATOMIC_TYPE)
+ sig_atomic_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (SIG_ATOMIC_TYPE)));
+ if (INT8_TYPE)
+ int8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT8_TYPE)));
+ if (INT16_TYPE)
+ int16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT16_TYPE)));
+ if (INT32_TYPE)
+ int32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT32_TYPE)));
+ if (INT64_TYPE)
+ int64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT64_TYPE)));
+ if (UINT8_TYPE)
+ uint8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT8_TYPE)));
+ if (UINT16_TYPE)
+ uint16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT16_TYPE)));
+ if (UINT32_TYPE)
+ c_uint32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT32_TYPE)));
+ if (UINT64_TYPE)
+ c_uint64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT64_TYPE)));
+ if (INT_LEAST8_TYPE)
+ int_least8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_LEAST8_TYPE)));
+ if (INT_LEAST16_TYPE)
+ int_least16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_LEAST16_TYPE)));
+ if (INT_LEAST32_TYPE)
+ int_least32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_LEAST32_TYPE)));
+ if (INT_LEAST64_TYPE)
+ int_least64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_LEAST64_TYPE)));
+ if (UINT_LEAST8_TYPE)
+ uint_least8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_LEAST8_TYPE)));
+ if (UINT_LEAST16_TYPE)
+ uint_least16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_LEAST16_TYPE)));
+ if (UINT_LEAST32_TYPE)
+ uint_least32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_LEAST32_TYPE)));
+ if (UINT_LEAST64_TYPE)
+ uint_least64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_LEAST64_TYPE)));
+ if (INT_FAST8_TYPE)
+ int_fast8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_FAST8_TYPE)));
+ if (INT_FAST16_TYPE)
+ int_fast16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_FAST16_TYPE)));
+ if (INT_FAST32_TYPE)
+ int_fast32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_FAST32_TYPE)));
+ if (INT_FAST64_TYPE)
+ int_fast64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INT_FAST64_TYPE)));
+ if (UINT_FAST8_TYPE)
+ uint_fast8_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_FAST8_TYPE)));
+ if (UINT_FAST16_TYPE)
+ uint_fast16_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_FAST16_TYPE)));
+ if (UINT_FAST32_TYPE)
+ uint_fast32_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_FAST32_TYPE)));
+ if (UINT_FAST64_TYPE)
+ uint_fast64_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINT_FAST64_TYPE)));
+ if (INTPTR_TYPE)
+ intptr_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INTPTR_TYPE)));
+ if (UINTPTR_TYPE)
+ uintptr_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINTPTR_TYPE)));
+
default_function_type = build_function_type (integer_type_node, NULL_TREE);
ptrdiff_type_node
= TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
set_user_assembler_name (builtin, asmspec);
- if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
- init_block_move_fn (asmspec);
- else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
- init_block_clear_fn (asmspec);
+ switch (DECL_FUNCTION_CODE (decl))
+ {
+ case BUILT_IN_MEMCPY:
+ init_block_move_fn (asmspec);
+ memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
+ break;
+ case BUILT_IN_MEMSET:
+ init_block_clear_fn (asmspec);
+ memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
+ break;
+ case BUILT_IN_MEMMOVE:
+ memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
+ break;
+ case BUILT_IN_MEMCMP:
+ memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
+ break;
+ case BUILT_IN_ABORT:
+ abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
+ break;
+ default:
+ break;
+ }
}
/* The number of named compound-literals generated thus far. */
}
/* 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;
/* 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;
}
-
-/* Hook used by expand_expr to expand language-specific tree codes. */
-/* The only things that should go here are bits needed to expand
- constant initializers. Everything else should be handled by the
- gimplification routines. */
-
-rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
- int modifiera /* Actually enum expand_modifier. */,
- rtx *alt_rtl)
-{
- enum expand_modifier modifier = (enum expand_modifier) modifiera;
- switch (TREE_CODE (exp))
- {
- case COMPOUND_LITERAL_EXPR:
- {
- /* Initialize the anonymous variable declared in the compound
- literal, then return the variable. */
- tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
- emit_local_var (decl);
- return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
- }
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Hook used by staticp to handle language-specific tree codes. */
-
-tree
-c_staticp (tree exp)
-{
- return (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
- && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp))
- ? exp : NULL);
-}
\f
/* Given a boolean expression ARG, return a tree representing an increment
return val;
}
\f
-/* Built-in macros for stddef.h, that require macros defined in this
- file. */
+/* Built-in macros for stddef.h and stdint.h, that require macros
+ defined in this file. */
void
c_stddef_cpp_builtins(void)
{
builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
+ if (SIG_ATOMIC_TYPE)
+ builtin_define_with_value ("__SIG_ATOMIC_TYPE__", SIG_ATOMIC_TYPE, 0);
+ if (INT8_TYPE)
+ builtin_define_with_value ("__INT8_TYPE__", INT8_TYPE, 0);
+ if (INT16_TYPE)
+ builtin_define_with_value ("__INT16_TYPE__", INT16_TYPE, 0);
+ if (INT32_TYPE)
+ builtin_define_with_value ("__INT32_TYPE__", INT32_TYPE, 0);
+ if (INT64_TYPE)
+ builtin_define_with_value ("__INT64_TYPE__", INT64_TYPE, 0);
+ if (UINT8_TYPE)
+ builtin_define_with_value ("__UINT8_TYPE__", UINT8_TYPE, 0);
+ if (UINT16_TYPE)
+ builtin_define_with_value ("__UINT16_TYPE__", UINT16_TYPE, 0);
+ if (UINT32_TYPE)
+ builtin_define_with_value ("__UINT32_TYPE__", UINT32_TYPE, 0);
+ if (UINT64_TYPE)
+ builtin_define_with_value ("__UINT64_TYPE__", UINT64_TYPE, 0);
+ if (INT_LEAST8_TYPE)
+ builtin_define_with_value ("__INT_LEAST8_TYPE__", INT_LEAST8_TYPE, 0);
+ if (INT_LEAST16_TYPE)
+ builtin_define_with_value ("__INT_LEAST16_TYPE__", INT_LEAST16_TYPE, 0);
+ if (INT_LEAST32_TYPE)
+ builtin_define_with_value ("__INT_LEAST32_TYPE__", INT_LEAST32_TYPE, 0);
+ if (INT_LEAST64_TYPE)
+ builtin_define_with_value ("__INT_LEAST64_TYPE__", INT_LEAST64_TYPE, 0);
+ if (UINT_LEAST8_TYPE)
+ builtin_define_with_value ("__UINT_LEAST8_TYPE__", UINT_LEAST8_TYPE, 0);
+ if (UINT_LEAST16_TYPE)
+ builtin_define_with_value ("__UINT_LEAST16_TYPE__", UINT_LEAST16_TYPE, 0);
+ if (UINT_LEAST32_TYPE)
+ builtin_define_with_value ("__UINT_LEAST32_TYPE__", UINT_LEAST32_TYPE, 0);
+ if (UINT_LEAST64_TYPE)
+ builtin_define_with_value ("__UINT_LEAST64_TYPE__", UINT_LEAST64_TYPE, 0);
+ if (INT_FAST8_TYPE)
+ builtin_define_with_value ("__INT_FAST8_TYPE__", INT_FAST8_TYPE, 0);
+ if (INT_FAST16_TYPE)
+ builtin_define_with_value ("__INT_FAST16_TYPE__", INT_FAST16_TYPE, 0);
+ if (INT_FAST32_TYPE)
+ builtin_define_with_value ("__INT_FAST32_TYPE__", INT_FAST32_TYPE, 0);
+ if (INT_FAST64_TYPE)
+ builtin_define_with_value ("__INT_FAST64_TYPE__", INT_FAST64_TYPE, 0);
+ if (UINT_FAST8_TYPE)
+ builtin_define_with_value ("__UINT_FAST8_TYPE__", UINT_FAST8_TYPE, 0);
+ if (UINT_FAST16_TYPE)
+ builtin_define_with_value ("__UINT_FAST16_TYPE__", UINT_FAST16_TYPE, 0);
+ if (UINT_FAST32_TYPE)
+ builtin_define_with_value ("__UINT_FAST32_TYPE__", UINT_FAST32_TYPE, 0);
+ if (UINT_FAST64_TYPE)
+ builtin_define_with_value ("__UINT_FAST64_TYPE__", UINT_FAST64_TYPE, 0);
+ if (INTPTR_TYPE)
+ builtin_define_with_value ("__INTPTR_TYPE__", INTPTR_TYPE, 0);
+ if (UINTPTR_TYPE)
+ builtin_define_with_value ("__UINTPTR_TYPE__", UINTPTR_TYPE, 0);
}
static void
}
else if (TREE_CODE (*node) == FIELD_DECL)
{
- if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT)
+ if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
+ /* Still pack bitfields. */
+ && ! DECL_INITIAL (*node))
warning (OPT_Wattributes,
"%qE attribute ignored for field of type %qT",
name, TREE_TYPE (*node));
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
{
tree *type = NULL;
int is_type = 0;
tree align_expr = (args ? TREE_VALUE (args)
- : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+ : size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT));
int i;
if (DECL_P (*node))
error ("requested alignment is not a power of 2");
*no_add_attrs = true;
}
- else if (i > HOST_BITS_PER_INT - 2)
+ else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
{
error ("requested alignment is too large");
*no_add_attrs = true;
else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
*type = build_variant_type_copy (*type);
- TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
+ TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT;
TYPE_USER_ALIGN (*type) = 1;
}
else if (! VAR_OR_FUNCTION_DECL_P (decl)
*no_add_attrs = true;
}
else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_ALIGN (decl) > (1 << i) * BITS_PER_UNIT)
+ && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
{
if (DECL_USER_ALIGN (decl))
error ("alignment for %q+D was previously specified as %d "
}
else
{
- DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
+ DECL_ALIGN (decl) = (1U << i) * BITS_PER_UNIT;
DECL_USER_ALIGN (decl) = 1;
}
{
tree decl = *node;
- if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+ if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
|| (TREE_CODE (decl) != FUNCTION_DECL
&& TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
/* A static variable declaration is always a tentative definition,
/* 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;
visibility_specified depending on #pragma GCC visibility. */
if (!DECL_VISIBILITY_SPECIFIED (decl))
{
- DECL_VISIBILITY (decl) = default_visibility;
- DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ if (visibility_options.inpragma
+ || DECL_VISIBILITY (decl) != default_visibility)
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ /* If visibility changed and DECL already has DECL_RTL, ensure
+ symbol flags are updated. */
+ if (((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_RTL_SET_P (decl))
+ make_decl_rtl (decl);
+ }
}
return false;
}
*no_add_attrs = true;
- if (!DECL_THREAD_LOCAL_P (decl))
+ if (TREE_CODE (decl) != VAR_DECL || !DECL_THREAD_LOCAL_P (decl))
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
return NULL_TREE;
|| (!SCALAR_FLOAT_MODE_P (orig_mode)
&& GET_MODE_CLASS (orig_mode) != MODE_INT
&& !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
- || !host_integerp (TYPE_SIZE_UNIT (type), 1))
+ || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+ || TREE_CODE (type) == BOOLEAN_TYPE)
{
error ("invalid vector type for attribute %qE", name);
return NULL_TREE;
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;
bool ret = true;
unsigned opt_argc;
unsigned i;
+ int saved_flag_strict_aliasing;
const char **opt_argv;
tree ap;
for (i = 1; i < opt_argc; i++)
opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
+ saved_flag_strict_aliasing = flag_strict_aliasing;
+
/* Now parse the options. */
decode_options (opt_argc, opt_argv);
+ /* Don't allow changing -fstrict-aliasing. */
+ flag_strict_aliasing = saved_flag_strict_aliasing;
+
VEC_truncate (const_char_p, optimize_args, 0);
return ret;
}
#undef catenate_messages
}
+/* Callback from cpp_error for PFILE to print diagnostics from the
+ preprocessor. The diagnostic is of type LEVEL, 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
+ the arguments. Returns true if a diagnostic was emitted, false
+ otherwise. */
+
+bool
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+ location_t location, unsigned int column_override,
+ const char *msg, va_list *ap)
+{
+ diagnostic_info diagnostic;
+ diagnostic_t dlevel;
+ int save_warn_system_headers = warn_system_headers;
+ bool ret;
+
+ switch (level)
+ {
+ case CPP_DL_WARNING_SYSHDR:
+ if (flag_no_output)
+ return false;
+ warn_system_headers = 1;
+ /* Fall through. */
+ case CPP_DL_WARNING:
+ if (flag_no_output)
+ return false;
+ dlevel = DK_WARNING;
+ break;
+ case CPP_DL_PEDWARN:
+ if (flag_no_output && !flag_pedantic_errors)
+ return false;
+ dlevel = DK_PEDWARN;
+ break;
+ case CPP_DL_ERROR:
+ dlevel = DK_ERROR;
+ break;
+ case CPP_DL_ICE:
+ dlevel = DK_ICE;
+ break;
+ case CPP_DL_NOTE:
+ dlevel = DK_NOTE;
+ break;
+ case CPP_DL_FATAL:
+ dlevel = DK_FATAL;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (done_lexing)
+ location = input_location;
+ diagnostic_set_info_translated (&diagnostic, msg, ap,
+ location, dlevel);
+ if (column_override)
+ diagnostic_override_column (&diagnostic, column_override);
+ ret = report_diagnostic (&diagnostic);
+ if (level == CPP_DL_WARNING_SYSHDR)
+ warn_system_headers = save_warn_system_headers;
+ return ret;
+}
+
/* Walk a gimplified function and warn for functions whose return value is
ignored and attribute((warn_unused_result)) is set. This is done before
inlining, so we don't have to worry about that. */
return error_mark_node;
case CALL_EXPR:
+ case TARGET_EXPR:
error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
return error_mark_node;
tree curindex;
unsigned HOST_WIDE_INT cnt;
constructor_elt *ce;
+ bool fold_p = false;
if (VEC_index (constructor_elt, v, 0)->index)
maxindex = fold_convert (sizetype,
VEC_iterate (constructor_elt, v, cnt, ce);
cnt++)
{
+ bool curfold_p = false;
if (ce->index)
- curindex = fold_convert (sizetype, ce->index);
+ curindex = ce->index, curfold_p = true;
else
- curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
-
+ {
+ if (fold_p)
+ curindex = fold_convert (sizetype, curindex);
+ curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
+ }
if (tree_int_cst_lt (maxindex, curindex))
- maxindex = curindex;
+ maxindex = curindex, fold_p = curfold_p;
}
+ if (fold_p)
+ maxindex = fold_convert (sizetype, maxindex);
}
}
else
/* 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_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 %<+%> in operand of %<&%>");
+ else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
warning (OPT_Wparentheses,
- "suggest parentheses around + or - in operand of &");
+ "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
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
+ || (TREE_CODE_CLASS (code_right) == tcc_comparison
+ && code_right != NE_EXPR && code_right != EQ_EXPR
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
+ 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.
+ 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 (tree orig_op0, tree orig_op1,
+warn_for_sign_compare (location_t location,
+ tree orig_op0, tree orig_op1,
tree op0, tree op1,
tree result_type, enum tree_code resultcode)
{
&& 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)))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
{
- warning (OPT_Wsign_compare, "comparison between types %qT and %qT",
- TREE_TYPE (orig_op0), 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,
/* OK */;
else
{
- tree sop, uop;
+ tree sop, uop, base_type;
bool ovf;
-
+
if (op0_signed)
sop = orig_op0, uop = orig_op1;
else
STRIP_TYPE_NOPS (sop);
STRIP_TYPE_NOPS (uop);
+ base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
+ ? TREE_TYPE (result_type) : result_type);
/* Do not warn if the signed quantity is an unsuffixed integer
literal (or some static constant expression involving such
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)))
+ && int_fits_type_p (uop, c_common_signed_type (base_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
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)))
+ c_common_signed_type (base_type)))
/* OK */;
else
- warning (OPT_Wsign_compare,
- "comparison between signed and unsigned integer expressions");
+ 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
warning (OPT_Wsign_compare,
"promoted ~unsigned is always non-zero");
else
- warning (OPT_Wsign_compare,
- "comparison of promoted ~unsigned with constant");
+ warning_at (location, OPT_Wsign_compare,
+ "comparison of promoted ~unsigned with constant");
}
}
}
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (op1))
< TYPE_PRECISION (result_type)))
- warning (OPT_Wsign_compare,
+ warning_at (location, OPT_Wsign_compare,
"comparison of promoted ~unsigned with unsigned");
}
}