cpp_reader *parse_in; /* Declared in c-pragma.h. */
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PID_TYPE
-#define PID_TYPE "int"
-#endif
-
-/* 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
-
-#ifdef UINT_LEAST32_TYPE
-#define CHAR32_TYPE UINT_LEAST32_TYPE
-#else
-#define CHAR32_TYPE "unsigned int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-
-/* WCHAR_TYPE gets overridden by -fshort-wchar. */
-#define MODIFIED_WCHAR_TYPE \
- (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WINT_TYPE
-#define WINT_TYPE "unsigned int"
-#endif
-
-#ifndef INTMAX_TYPE
-#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "int" \
- : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "long int" \
- : "long long int"))
-#endif
-
-#ifndef UINTMAX_TYPE
-#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "unsigned int" \
- : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "long unsigned int" \
- : "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.
int warn_implicit = 1;
-/* Maximum template instantiation depth. This limit is rather
- arbitrary, but it exists to limit the time it takes to notice
- infinite template instantiations. */
+/* Maximum template instantiation depth. This limit exists to limit the
+ time it takes to notice infinite template instantiations; the default
+ value of 1024 is likely to be in the next C++ standard. */
-int max_tinst_depth = 500;
+int max_tinst_depth = 1024;
type names and storage classes. It is indexed by a RID_... value. */
tree *ridpointers;
-tree (*make_fname_decl) (tree, int);
+tree (*make_fname_decl) (location_t, tree, int);
-/* Nonzero means the expression being parsed will never be evaluated.
- This is a count, since unevaluated expressions can nest. */
-int skip_evaluation;
+/* Nonzero means don't warn about problems that occur when the code is
+ executed. */
+int c_inhibit_evaluation_warnings;
/* Whether lexing has been completed, so subsequent preprocessor
errors should use the compiler's input_location. */
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
{
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
+ { "_Imaginary", RID_IMAGINARY, D_CONLY },
{ "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
{ "_Decimal128", RID_DFLOAT128, D_CONLY | D_EXT },
{ "__is_enum", RID_IS_ENUM, D_CXXONLY },
{ "__is_pod", RID_IS_POD, D_CXXONLY },
{ "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
+ { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
+ { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY },
{ "__is_union", RID_IS_UNION, D_CXXONLY },
{ "__imag", RID_IMAGPART, 0 },
{ "__imag__", RID_IMAGPART, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__volatile", RID_VOLATILE, 0 },
{ "__volatile__", RID_VOLATILE, 0 },
+ { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "asm", RID_ASM, D_ASM },
{ "auto", RID_AUTO, 0 },
{ "bool", RID_BOOL, D_CXXONLY | D_CXXWARN },
{ "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
{ "const", RID_CONST, 0 },
+ { "constexpr", RID_CONSTEXPR, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
{ "continue", RID_CONTINUE, 0 },
{ "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X | D_CXXWARN },
handle_noreturn_attribute },
{ "noinline", 0, 0, true, false, false,
handle_noinline_attribute },
+ { "noclone", 0, 0, true, false, false,
+ handle_noclone_attribute },
{ "always_inline", 0, 0, true, false, false,
handle_always_inline_attribute },
{ "gnu_inline", 0, 0, true, false, false,
to prevent its usage in source code. */
{ "no vops", 0, 0, true, false, false,
handle_novops_attribute },
- { "deprecated", 0, 0, false, false, false,
+ { "deprecated", 0, 1, false, false, false,
handle_deprecated_attribute },
{ "vector_size", 1, 1, false, true, false,
handle_vector_size_attribute },
input_location = UNKNOWN_LOCATION;
stmts = push_stmt_list ();
- decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
+ decl = (*make_fname_decl) (loc, id, fname_vars[ix].pretty);
stmts = pop_stmt_list (stmts);
if (!IS_EMPTY_STMT (stmts))
saved_function_name_decls
tree eptype = NULL_TREE;
bool dummy = true;
bool maybe_const_itself = true;
+ location_t loc = EXPR_LOCATION (expr);
/* This function is not relevant to C++ because C++ folds while
parsing, and may need changes to be correct for C++ when C++
ret = c_fully_fold_internal (expr, in_init, maybe_const,
&maybe_const_itself);
if (eptype)
- ret = fold_convert (eptype, ret);
+ ret = fold_convert_loc (loc, eptype, ret);
*maybe_const &= maybe_const_itself;
return ret;
}
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);
+ int unused_p;
/* This function is not relevant to C++ because C++ folds while
parsing, and may need changes to be correct for C++ when C++
op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (op0 != orig_op0)
ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
if (ret != expr)
op3 = TREE_OPERAND (expr, 3);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1)
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != MODIFY_EXPR
&& code != PREDECREMENT_EXPR
&& code != PREINCREMENT_EXPR
if (code != MODIFY_EXPR)
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
ret = in_init
- ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
- : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+ ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
+ : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
else
ret = fold (expr);
+ if (TREE_OVERFLOW_P (ret)
+ && !TREE_OVERFLOW_P (op0)
+ && !TREE_OVERFLOW_P (op1))
+ overflow_warning (EXPR_LOCATION (expr), ret);
goto out;
case INDIRECT_REF:
orig_op0 = op0 = TREE_OPERAND (expr, 0);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
op0 = decl_constant_value_for_optimization (op0);
if (op0 != orig_op0 || in_init)
ret = in_init
- ? fold_build1_initializer (code, TREE_TYPE (expr), op0)
- : fold_build1 (code, TREE_TYPE (expr), op0);
+ ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
+ : fold_build1_loc (loc, code, TREE_TYPE (expr), op0);
else
ret = fold (expr);
if (code == INDIRECT_REF
TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
}
+ switch (code)
+ {
+ case FIX_TRUNC_EXPR:
+ case FLOAT_EXPR:
+ CASE_CONVERT:
+ /* Don't warn about explicit conversions. We will already
+ have warned about suspect implicit conversions. */
+ break;
+
+ default:
+ if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0))
+ overflow_warning (EXPR_LOCATION (expr), ret);
+ break;
+ }
goto out;
case TRUTH_ANDIF_EXPR:
orig_op0 = op0 = TREE_OPERAND (expr, 0);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ STRIP_TYPE_NOPS (op0);
+
+ unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
+ ? truthvalue_false_node
+ : truthvalue_true_node));
+ c_inhibit_evaluation_warnings += unused_p;
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
+ c_inhibit_evaluation_warnings -= unused_p;
+
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
ret = in_init
- ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
- : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+ ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
+ : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
else
ret = fold (expr);
*maybe_const_operands &= op0_const;
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);
+
+ STRIP_TYPE_NOPS (op0);
+ c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
+ c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
+
+ c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+ STRIP_TYPE_NOPS (op2);
+ c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
+
if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
- ret = fold_build3 (code, TREE_TYPE (expr), op0, op1, op2);
+ ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2);
else
ret = fold (expr);
*maybe_const_operands &= op0_const;
already overflowed. */
void
-overflow_warning (tree value)
+overflow_warning (location_t loc, tree value)
{
- if (skip_evaluation) return;
+ if (c_inhibit_evaluation_warnings != 0)
+ return;
switch (TREE_CODE (value))
{
case INTEGER_CST:
- warning (OPT_Woverflow, "integer overflow in expression");
+ warning_at (loc, OPT_Woverflow, "integer overflow in expression");
break;
case REAL_CST:
- warning (OPT_Woverflow, "floating point overflow in expression");
+ warning_at (loc, OPT_Woverflow,
+ "floating point overflow in expression");
break;
case FIXED_CST:
- warning (OPT_Woverflow, "fixed-point overflow in expression");
+ warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
break;
case VECTOR_CST:
- warning (OPT_Woverflow, "vector overflow in expression");
+ warning_at (loc, OPT_Woverflow, "vector overflow in expression");
break;
case COMPLEX_CST:
if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
- warning (OPT_Woverflow, "complex integer overflow in expression");
+ warning_at (loc, OPT_Woverflow,
+ "complex integer overflow in expression");
else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
- warning (OPT_Woverflow, "complex floating point overflow in expression");
+ warning_at (loc, OPT_Woverflow,
+ "complex floating point overflow in expression");
break;
default:
/* Warn about uses of logical || / && operator in a context where it
is likely that the bitwise equivalent was intended by the
programmer. We have seen an expression in which CODE is a binary
- operator used to combine expressions OP_LEFT and OP_RIGHT, which
- before folding had CODE_LEFT and CODE_RIGHT. */
-
+ operator used to combine expressions OP_LEFT and OP_RIGHT, which before folding
+ had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */
void
-warn_logical_operator (location_t location, enum tree_code code,
+warn_logical_operator (location_t location, enum tree_code code, tree type,
enum tree_code code_left, tree op_left,
enum tree_code ARG_UNUSED (code_right), tree op_right)
{
+ int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
+ int in0_p, in1_p, in_p;
+ tree low0, low1, low, high0, high1, high, lhs, rhs, tem;
+ bool strict_overflow_p = false;
+
if (code != TRUTH_ANDIF_EXPR
&& code != TRUTH_AND_EXPR
&& code != TRUTH_ORIF_EXPR
&& !integer_zerop (op_right)
&& !integer_onep (op_right))
{
- if (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR)
+ if (or_op)
warning_at (location, OPT_Wlogical_op, "logical %<or%>"
" applied to non-boolean constant");
else
warning_at (location, OPT_Wlogical_op, "logical %<and%>"
" applied to non-boolean constant");
TREE_NO_WARNING (op_left) = true;
+ return;
+ }
+
+ /* We do not warn for constants because they are typical of macro
+ expansions that test for features. */
+ if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right))
+ return;
+
+ /* This warning only makes sense with logical operands. */
+ if (!(truth_value_p (TREE_CODE (op_left))
+ || INTEGRAL_TYPE_P (TREE_TYPE (op_left)))
+ || !(truth_value_p (TREE_CODE (op_right))
+ || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
+ return;
+
+ lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
+ rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
+
+ if (lhs && TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
+ lhs = C_MAYBE_CONST_EXPR_EXPR (lhs);
+
+ if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
+ rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
+
+ /* If this is an OR operation, invert both sides; we will invert
+ again at the end. */
+ if (or_op)
+ in0_p = !in0_p, in1_p = !in1_p;
+
+ /* If both expressions are the same, if we can merge the ranges, and we
+ can build the range test, return it or it inverted. */
+ if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
+ && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
+ in1_p, low1, high1)
+ && 0 != (tem = build_range_check (UNKNOWN_LOCATION,
+ type, lhs, in_p, low, high)))
+ {
+ if (TREE_CODE (tem) != INTEGER_CST)
+ return;
+
+ if (or_op)
+ warning_at (location, OPT_Wlogical_op,
+ "logical %<or%> "
+ "of collectively exhaustive tests is always true");
+ else
+ warning_at (location, OPT_Wlogical_op,
+ "logical %<and%> "
+ "of mutually exclusive tests is always false");
}
}
bool
strict_aliasing_warning (tree otype, tree type, tree expr)
{
+ /* Strip pointer conversion chains and get to the correct original type. */
+ STRIP_NOPS (expr);
+ otype = TREE_TYPE (expr);
+
if (!(flag_strict_aliasing
&& POINTER_TYPE_P (type)
&& POINTER_TYPE_P (otype)
result = convert (type, expr);
- if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
+ if (c_inhibit_evaluation_warnings == 0
+ && !TREE_OVERFLOW_P (expr)
+ && result != error_mark_node)
warnings_for_convert_and_check (type, expr_for_warning, result);
return result;
static void merge_tlist (struct tlist **, struct tlist *, int);
static void verify_tree (tree, struct tlist **, struct tlist **, tree);
static int warning_candidate_p (tree);
+static bool candidate_equal_p (const_tree, const_tree);
static void warn_for_collisions (struct tlist *);
static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
static struct tlist *new_tlist (struct tlist *, tree, tree);
struct tlist *next = add->next;
if (!copy)
add->next = *to;
- if (!exclude_writer || add->writer != exclude_writer)
+ if (!exclude_writer || !candidate_equal_p (add->writer, exclude_writer))
*to = copy ? new_tlist (*to, add->expr, add->writer) : add;
add = next;
}
struct tlist *next = add->next;
for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
- if (tmp2->expr == add->expr)
+ if (candidate_equal_p (tmp2->expr, add->expr))
{
found = 1;
if (!tmp2->writer)
/* Avoid duplicate warnings. */
for (tmp = warned_ids; tmp; tmp = tmp->next)
- if (tmp->expr == written)
+ if (candidate_equal_p (tmp->expr, written))
return;
while (list)
{
- if (list->expr == written
- && list->writer != writer
- && (!only_writes || list->writer)
- && DECL_NAME (list->expr))
+ if (candidate_equal_p (list->expr, written)
+ && !candidate_equal_p (list->writer, writer)
+ && (!only_writes || list->writer))
{
warned_ids = new_tlist (warned_ids, written, NULL_TREE);
warning_at (EXPR_HAS_LOCATION (writer)
static int
warning_candidate_p (tree x)
{
- return TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == PARM_DECL;
+ /* !VOID_TYPE_P (TREE_TYPE (x)) is workaround for cp/tree.c
+ (lvalue_p) crash on TRY/CATCH. */
+ return !(DECL_P (x) && DECL_ARTIFICIAL (x))
+ && TREE_TYPE (x) && !VOID_TYPE_P (TREE_TYPE (x)) && lvalue_p (x);
+}
+
+/* Return nonzero if X and Y appear to be the same candidate (or NULL) */
+static bool
+candidate_equal_p (const_tree x, const_tree y)
+{
+ return (x == y) || (x && y && operand_equal_p (x, y, 0));
}
/* Walk the tree X, and record accesses to variables. If X is written by the
cl = TREE_CODE_CLASS (code);
if (warning_candidate_p (x))
- {
- *pno_sp = new_tlist (*pno_sp, x, writer);
- return;
- }
+ *pno_sp = new_tlist (*pno_sp, x, writer);
switch (code)
{
{
struct tlist_cache *t;
for (t = save_expr_cache; t; t = t->next)
- if (t->expr == x)
+ if (candidate_equal_p (t->expr, x))
break;
if (!t)
{
tree decl;
- decl = build_decl (TYPE_DECL, get_identifier (name), type);
+ decl = build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (name), type);
DECL_ARTIFICIAL (decl) = 1;
if (!TYPE_NAME (type))
TYPE_NAME (type) = decl;
of pointer PTROP and integer INTOP. */
tree
-pointer_int_sum (location_t location, enum tree_code resultcode,
+pointer_int_sum (location_t loc, enum tree_code resultcode,
tree ptrop, tree intop)
{
tree size_exp, ret;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer of type %<void *%> used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
{
- pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to a function used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
{
- pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to member function used in arithmetic");
size_exp = integer_one_node;
}
Do this multiplication as signed, then convert to the appropriate
type for the pointer operation. */
intop = convert (sizetype,
- build_binary_op (EXPR_LOCATION (intop),
+ build_binary_op (loc,
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);
+ intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
- 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);
+ ret = fold_build2_loc (loc, POINTER_PLUS_EXPR, result_type, ptrop, intop);
fold_undefer_and_ignore_overflow_warnings ();
return ret;
}
\f
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+ and if NON_CONST is known not to be permitted in an evaluated part
+ of a constant expression. */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+ bool nowarning = TREE_NO_WARNING (expr);
+ location_t loc = EXPR_LOCATION (expr);
+
+ /* This should never be called for C++. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING. */
+ STRIP_TYPE_NOPS (expr);
+ expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+ if (nowarning)
+ TREE_NO_WARNING (expr) = 1;
+ protected_set_expr_location (expr, loc);
+
+ return expr;
+}
+
/* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
around the SAVE_EXPR if needed so that c_fully_fold does not need
expr = c_fully_fold (expr, false, &maybe_const);
expr = save_expr (expr);
if (!maybe_const)
- {
- expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
- C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
- }
+ expr = c_wrap_maybe_const (expr, true);
return expr;
}
case ORDERED_EXPR: case UNORDERED_EXPR:
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
- return build2 (TREE_CODE (expr), truthvalue_type_node,
+ expr = build2 (TREE_CODE (expr), truthvalue_type_node,
TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+ goto ret;
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_XOR_EXPR:
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
- return build2 (TREE_CODE (expr), truthvalue_type_node,
- c_common_truthvalue_conversion (location,
- TREE_OPERAND (expr, 0)),
- c_common_truthvalue_conversion (location,
- TREE_OPERAND (expr, 1)));
+ expr = build2 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)));
+ goto ret;
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 (location,
- TREE_OPERAND (expr, 0)));
+ expr = build1 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)));
+ goto ret;
case ERROR_MARK:
return expr;
}
if (TREE_SIDE_EFFECTS (inner))
- return build2 (COMPOUND_EXPR, truthvalue_type_node,
- inner, truthvalue_true_node);
+ {
+ expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
+ inner, truthvalue_true_node);
+ goto ret;
+ }
else
return truthvalue_true_node;
}
case COMPLEX_EXPR:
- return build_binary_op (EXPR_LOCATION (expr),
+ expr = build_binary_op (EXPR_LOCATION (expr),
(TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
c_common_truthvalue_conversion (location,
c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 1)),
0);
+ goto ret;
case NEGATE_EXPR:
case ABS_EXPR:
/* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
- return build2 (COMPOUND_EXPR, truthvalue_type_node,
- TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion
- (location, TREE_OPERAND (expr, 0)));
+ {
+ expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 1),
+ c_common_truthvalue_conversion
+ (location, TREE_OPERAND (expr, 0)));
+ goto ret;
+ }
else
return c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 0));
case COND_EXPR:
/* Distribute the conversion into the arms of a COND_EXPR. */
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)));
+ {
+ expr = fold_build3_loc (location, 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)));
+ goto ret;
+ }
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)));
+ {
+ /* Folding will happen later for C. */
+ expr = 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)));
+ goto ret;
+ }
CASE_CONVERT:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
{
tree t = c_save_expr (expr);
- return (build_binary_op
+ expr = (build_binary_op
(EXPR_LOCATION (expr),
(TREE_SIDE_EFFECTS (expr)
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
(location,
build_unary_op (location, IMAGPART_EXPR, t, 0)),
0));
+ goto ret;
}
if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
FCONST0 (TYPE_MODE
(TREE_TYPE (expr))));
- return build_binary_op (EXPR_LOCATION (expr),
- NE_EXPR, expr, fixed_zero_node, 1);
+ return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, 1);
}
+ else
+ return build_binary_op (location, NE_EXPR, expr, integer_zero_node, 1);
- return build_binary_op (EXPR_LOCATION (expr),
- NE_EXPR, expr, integer_zero_node, 1);
+ ret:
+ protected_set_expr_location (expr, location);
+ return expr;
}
\f
static void def_builtin_1 (enum built_in_function fncode,
|| !POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
error ("invalid use of %<restrict%>");
- else if (flag_strict_aliasing && type == TREE_TYPE (decl))
- /* Indicate we need to make a unique alias set for this pointer.
- We can't do it here because it might be pointing to an
- incomplete type. */
- DECL_POINTER_ALIAS_SET (decl) = -2;
}
}
return -1;
}
\f
-/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
- second parameter indicates which OPERATOR is being applied. The COMPLAIN
- flag controls whether we should diagnose possibly ill-formed
- constructs or not. */
+/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
+ the second parameter indicates which OPERATOR is being applied.
+ The COMPLAIN flag controls whether we should diagnose possibly
+ ill-formed constructs or not. LOC is the location of the SIZEOF or
+ TYPEOF operator. */
tree
-c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
+c_sizeof_or_alignof_type (location_t loc,
+ tree type, bool is_sizeof, int complain)
{
const char *op_name;
tree value = NULL;
if (is_sizeof)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %<sizeof%> to a function type");
else if (!complain)
return error_mark_node;
{
if (type_code == VOID_TYPE
&& complain && (pedantic || warn_pointer_arith))
- pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %qs to a void type", op_name);
else if (!complain)
return error_mark_node;
else if (!COMPLETE_TYPE_P (type))
{
if (complain)
- error ("invalid application of %qs to incomplete type %qT ",
- op_name, type);
+ error_at (loc, "invalid application of %qs to incomplete type %qT ",
+ op_name, type);
value = size_zero_node;
}
else
{
if (is_sizeof)
/* Convert in case a char is more than one unit. */
- value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
+ value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+ size_int (TYPE_PRECISION (char_type_node)
+ / BITS_PER_UNIT));
else
value = size_int (TYPE_ALIGN_UNIT (type));
}
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- value = fold_convert (size_type_node, value);
+ value = fold_convert_loc (loc, size_type_node, value);
gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
return value;
/* Implement the __alignof keyword: Return the minimum required
alignment of EXPR, measured in bytes. For VAR_DECLs,
FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
- from an "aligned" __attribute__ specification). */
+ from an "aligned" __attribute__ specification). LOC is the
+ location of the ALIGNOF operator. */
tree
-c_alignof_expr (tree expr)
+c_alignof_expr (location_t loc, tree expr)
{
tree t;
else if (TREE_CODE (expr) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
{
- error ("%<__alignof%> applied to a bit-field");
+ error_at (loc, "%<__alignof%> applied to a bit-field");
t = size_one_node;
}
else if (TREE_CODE (expr) == COMPONENT_REF
if (thisalign > bestalign)
best = t, bestalign = thisalign;
}
- return c_alignof (TREE_TYPE (TREE_TYPE (best)));
+ return c_alignof (loc, TREE_TYPE (TREE_TYPE (best)));
}
else
- return c_alignof (TREE_TYPE (expr));
+ return c_alignof (loc, TREE_TYPE (expr));
- return fold_convert (size_type_node, t);
+ return fold_convert_loc (loc, size_type_node, t);
}
\f
/* Handle C and C++ default attributes. */
/* These are types that c_common_type_for_size and
c_common_type_for_mode use. */
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
intQI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
intHI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
intSI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
if (targetm.scalar_mode_supported_p (TImode))
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
get_identifier ("__int128_t"),
intTI_type_node));
#endif
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
unsigned_intQI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
unsigned_intHI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
unsigned_intSI_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
unsigned_intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
if (targetm.scalar_mode_supported_p (TImode))
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
get_identifier ("__uint128_t"),
unsigned_intTI_type_node));
#endif
/* Create the widest literal types. */
widest_integer_literal_type_node
= make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
widest_integer_literal_type_node));
widest_unsigned_literal_type_node
= make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
widest_unsigned_literal_type_node));
/* `unsigned long' is the standard type for sizeof.
}
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
get_identifier ("complex int"),
complex_integer_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
get_identifier ("complex float"),
complex_float_type_node));
- lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
get_identifier ("complex double"),
complex_double_type_node));
lang_hooks.decls.pushdecl
- (build_decl (TYPE_DECL, get_identifier ("complex long double"),
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier ("complex long double"),
complex_long_double_type_node));
if (c_dialect_cxx ())
unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
lang_hooks.decls.pushdecl
- (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier ("__builtin_va_list"),
va_list_type_node));
#ifdef TARGET_ENUM_VA_LIST
{
for (l = 0; TARGET_ENUM_VA_LIST (l, &pname, &ptype); ++l)
{
lang_hooks.decls.pushdecl
- (build_decl (TYPE_DECL, get_identifier (pname),
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (pname),
ptype));
}
memset (builtin_types, 0, sizeof (builtin_types));
}
-/* Look up the function in built_in_decls that corresponds to DECL
- and set ASMSPEC as its user assembler name. DECL must be a
- function decl that declares a builtin. */
-
-void
-set_builtin_user_assembler_name (tree decl, const char *asmspec)
-{
- tree builtin;
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && asmspec != 0);
-
- builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- set_user_assembler_name (builtin, 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. */
static GTY(()) int compound_literal_number;
}
tree
-build_va_arg (tree expr, tree type)
+build_va_arg (location_t loc, tree expr, tree type)
{
- return build1 (VA_ARG_EXPR, type, expr);
+ expr = build1 (VA_ARG_EXPR, type, expr);
+ SET_EXPR_LOCATION (expr, loc);
+ return expr;
}
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
-/* Process a case label for the range LOW_VALUE ... HIGH_VALUE. If
- LOW_VALUE and HIGH_VALUE are both NULL_TREE then this case label is
- actually a `default' label. If only HIGH_VALUE is NULL_TREE, then
- case label was declared using the usual C/C++ syntax, rather than
- the GNU case range extension. CASES is a tree containing all the
- case ranges processed so far; COND is the condition for the
- switch-statement itself. Returns the CASE_LABEL_EXPR created, or
- ERROR_MARK_NODE if no CASE_LABEL_EXPR is created. */
+/* Process a case label, located at LOC, for the range LOW_VALUE
+ ... HIGH_VALUE. If LOW_VALUE and HIGH_VALUE are both NULL_TREE
+ then this case label is actually a `default' label. If only
+ HIGH_VALUE is NULL_TREE, then case label was declared using the
+ usual C/C++ syntax, rather than the GNU case range extension.
+ CASES is a tree containing all the case ranges processed so far;
+ COND is the condition for the switch-statement itself. Returns the
+ CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR
+ is created. */
tree
-c_add_case_label (splay_tree cases, tree cond, tree orig_type,
+c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
tree low_value, tree high_value)
{
tree type;
splay_tree_node node;
/* Create the LABEL_DECL itself. */
- label = create_artificial_label ();
+ label = create_artificial_label (loc);
/* If there was an error processing the switch condition, bail now
before we get more confused. */
|| (high_value && TREE_TYPE (high_value)
&& POINTER_TYPE_P (TREE_TYPE (high_value))))
{
- error ("pointers are not permitted as case values");
+ error_at (loc, "pointers are not permitted as case values");
goto error_out;
}
/* Case ranges are a GNU extension. */
if (high_value)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"range expressions in switch statements are non-standard");
type = TREE_TYPE (cond);
if (tree_int_cst_equal (low_value, high_value))
high_value = NULL_TREE;
else if (!tree_int_cst_lt (low_value, high_value))
- warning (0, "empty range specified");
+ warning_at (loc, 0, "empty range specified");
}
/* See if the case is in range of the type of the original testing
if (high_value)
{
- error ("duplicate (or overlapping) case value");
- error ("%Jthis is the first entry overlapping that value", duplicate);
+ error_at (loc, "duplicate (or overlapping) case value");
+ error_at (DECL_SOURCE_LOCATION (duplicate),
+ "this is the first entry overlapping that value");
}
else if (low_value)
{
- error ("duplicate case value") ;
- error ("%Jpreviously used here", duplicate);
+ error_at (loc, "duplicate case value") ;
+ error_at (DECL_SOURCE_LOCATION (duplicate), "previously used here");
}
else
{
- error ("multiple default labels in one switch");
- error ("%Jthis is the first default label", duplicate);
+ error_at (loc, "multiple default labels in one switch");
+ error_at (DECL_SOURCE_LOCATION (duplicate),
+ "this is the first default label");
}
goto error_out;
}
/* Add a CASE_LABEL to the statement-tree. */
- case_label = add_stmt (build_case_label (low_value, high_value, label));
+ case_label = add_stmt (build_case_label (loc, low_value, high_value, label));
/* Register this case label in the splay tree. */
splay_tree_insert (cases,
(splay_tree_key) low_value,
that just leads to duplicates and thence to failure later on. */
if (!cases->root)
{
- tree t = create_artificial_label ();
- add_stmt (build_stmt (LABEL_EXPR, t));
+ tree t = create_artificial_label (loc);
+ add_stmt (build_stmt (loc, LABEL_EXPR, t));
}
return error_mark_node;
}
(unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
if (TYPE_NAME (type) == 0)
- warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
- "%Jcase value %qs not in enumerated type",
- CASE_LABEL (label), buf);
+ warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
+ warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+ "case value %qs not in enumerated type",
+ buf);
else
- warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
- "%Jcase value %qs not in enumerated type %qT",
- CASE_LABEL (label), buf, type);
+ warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
+ warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+ "case value %qs not in enumerated type %qT",
+ buf, type);
}
/* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
splay_tree_node default_node;
splay_tree_node node;
tree chain;
- int saved_warn_switch;
if (!warn_switch && !warn_switch_enum && !warn_switch_default)
return;
default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
if (!default_node)
- warning (OPT_Wswitch_default, "%Hswitch missing default case",
- &switch_location);
+ warning_at (switch_location, OPT_Wswitch_default,
+ "switch missing default case");
/* From here on, we only care about about enumerated types. */
if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
return;
- /* If the switch expression was an enumerated type, check that
- exactly all enumeration literals are covered by the cases.
- The check is made when -Wswitch was specified and there is no
- default case, or when -Wswitch-enum was specified. */
-
- if (!warn_switch_enum
- && !(warn_switch && !default_node))
+ /* From here on, we only care about -Wswitch and -Wswitch-enum. */
+ if (!warn_switch_enum && !warn_switch)
return;
+ /* Check the cases. Warn about case values which are not members of
+ the enumerated type. For -Wswitch-enum, or for -Wswitch when
+ there is no default case, check that exactly all enumeration
+ literals are covered by the cases. */
+
/* Clearing COND if it is not an integer constant simplifies
the tests inside the loop below. */
if (TREE_CODE (cond) != INTEGER_CST)
continue;
/* If there is a default_node, the only relevant option is
- Wswitch-enum. Otherwise, if both are enabled then we prefer
+ Wswitch-enum. Otherwise, if both are enabled then we prefer
to warn using -Wswitch because -Wswitch is enabled by -Wall
while -Wswitch-enum is explicit. */
- warning ((default_node || !warn_switch)
- ? OPT_Wswitch_enum : OPT_Wswitch,
- "%Henumeration value %qE not handled in switch",
- &switch_location, TREE_PURPOSE (chain));
+ warning_at (switch_location,
+ (default_node || !warn_switch
+ ? OPT_Wswitch_enum
+ : OPT_Wswitch),
+ "enumeration value %qE not handled in switch",
+ TREE_PURPOSE (chain));
}
/* Warn if there are case expressions that don't correspond to
every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
above. This scan also resets those fields. */
- /* If there is a default_node, the only relevant option is
- Wswitch-enum. Otherwise, if both are enabled then we prefer
- to warn using -Wswitch because -Wswitch is enabled by -Wall
- while -Wswitch-enum is explicit. */
- saved_warn_switch = warn_switch;
- if (default_node)
- warn_switch = 0;
splay_tree_foreach (cases, match_case_to_enum, type);
- warn_switch = saved_warn_switch;
-
}
/* Finish an expression taking the address of LABEL (an
break;
case PREDECREMENT_EXPR:
val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
- invert_truthvalue (arg));
+ invert_truthvalue_loc (input_location, arg));
break;
case POSTDECREMENT_EXPR:
val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
- invert_truthvalue (arg));
+ invert_truthvalue_loc (input_location, arg));
arg = save_expr (arg);
val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
return NULL_TREE;
}
+/* Handle a "noclone" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noclone_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "always_inline" attribute; arguments as in
struct attribute_spec.handler. */
int ARG_UNUSED (flags), bool *no_add_attrs)
{
tree type = *node;
+ tree ident = TREE_VALUE (args);
*no_add_attrs = true;
- if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
+ if (TREE_CODE (ident) != IDENTIFIER_NODE)
warning (OPT_Wattributes, "%qE attribute ignored", name);
else
{
int j;
- const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
+ const char *p = IDENTIFIER_POINTER (ident);
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
if (mode == VOIDmode)
{
- error ("unknown machine mode %qs", p);
+ error ("unknown machine mode %qE", ident);
return NULL_TREE;
}
&& current_function_decl != NULL_TREE
&& !TREE_STATIC (decl))
{
- error ("%Jsection attribute cannot be specified for "
- "local variables", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "section attribute cannot be specified for "
+ "local variables");
*no_add_attrs = true;
}
}
else
{
- error ("%Jsection attributes are not supported for this target", *node);
+ error_at (DECL_SOURCE_LOCATION (*node),
+ "section attributes are not supported for this target");
*no_add_attrs = true;
}
else
{
if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
- error ("%Jweakref attribute must appear before alias attribute",
- *node);
+ error_at (DECL_SOURCE_LOCATION (*node),
+ "weakref attribute must appear before alias attribute");
/* Can't call declare_weak because it wants this to be TREE_PUBLIC,
and that isn't supported; and because it wants to add it to
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%J%qE attribute applies only to functions", decl, name);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute applies only to functions", name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Jcan%'t set %qE attribute after definition", decl, name);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "can%'t set %qE attribute after definition", name);
*no_add_attrs = true;
}
else
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%J%qE attribute applies only to functions", decl, name);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute applies only to functions", name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Jcan%'t set %qE attribute after definition", decl, name);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "can%'t set %qE attribute after definition", name);
*no_add_attrs = true;
}
else
static tree
handle_deprecated_attribute (tree *node, tree name,
- tree ARG_UNUSED (args), int flags,
+ tree args, int flags,
bool *no_add_attrs)
{
tree type = NULL_TREE;
int warn = 0;
tree what = NULL_TREE;
+ if (!args)
+ *no_add_attrs = true;
+ else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ {
+ error ("deprecated message is not a string");
+ *no_add_attrs = true;
+ }
+
if (DECL_P (*node))
{
tree decl = *node;
TOKEN, which had the associated VALUE. */
void
-c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
+ tree value, unsigned char token_flags)
{
#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
char *message = NULL;
- if (token == CPP_EOF)
+ if (token_type == CPP_EOF)
message = catenate_messages (gmsgid, " at end of input");
- else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16
- || token == CPP_CHAR32)
+ else if (token_type == CPP_CHAR
+ || token_type == CPP_WCHAR
+ || token_type == CPP_CHAR16
+ || token_type == CPP_CHAR32)
{
unsigned int val = TREE_INT_CST_LOW (value);
const char *prefix;
- switch (token)
+ switch (token_type)
{
default:
prefix = "";
free (message);
message = NULL;
}
- else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16
- || token == CPP_STRING32)
+ else if (token_type == CPP_STRING
+ || token_type == CPP_WSTRING
+ || token_type == CPP_STRING16
+ || token_type == CPP_STRING32)
message = catenate_messages (gmsgid, " before string constant");
- else if (token == CPP_NUMBER)
+ else if (token_type == CPP_NUMBER)
message = catenate_messages (gmsgid, " before numeric constant");
- else if (token == CPP_NAME)
+ else if (token_type == CPP_NAME)
{
message = catenate_messages (gmsgid, " before %qE");
error (message, value);
free (message);
message = NULL;
}
- else if (token == CPP_PRAGMA)
+ else if (token_type == CPP_PRAGMA)
message = catenate_messages (gmsgid, " before %<#pragma%>");
- else if (token == CPP_PRAGMA_EOL)
+ else if (token_type == CPP_PRAGMA_EOL)
message = catenate_messages (gmsgid, " before end of line");
- else if (token < N_TTYPES)
+ else if (token_type < N_TTYPES)
{
message = catenate_messages (gmsgid, " before %qs token");
- error (message, cpp_type2name (token));
+ error (message, cpp_type2name (token_type, token_flags));
free (message);
message = NULL;
}
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. */
-
-void
-c_warn_unused_result (gimple_seq seq)
-{
- tree fdecl, ftype;
- gimple_stmt_iterator i;
-
- for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
- {
- gimple g = gsi_stmt (i);
-
- switch (gimple_code (g))
- {
- case GIMPLE_BIND:
- c_warn_unused_result (gimple_bind_body (g));
- break;
- case GIMPLE_TRY:
- c_warn_unused_result (gimple_try_eval (g));
- c_warn_unused_result (gimple_try_cleanup (g));
- break;
- case GIMPLE_CATCH:
- c_warn_unused_result (gimple_catch_handler (g));
- break;
- case GIMPLE_EH_FILTER:
- c_warn_unused_result (gimple_eh_filter_failure (g));
- break;
-
- case GIMPLE_CALL:
- if (gimple_call_lhs (g))
- break;
-
- /* 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_fndecl (g);
- ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
-
- if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
- {
- location_t loc = gimple_location (g);
-
- if (fdecl)
- warning (0, "%Hignoring return value of %qD, "
- "declared with attribute warn_unused_result",
- &loc, fdecl);
- else
- warning (0, "%Hignoring return value of function "
- "declared with attribute warn_unused_result",
- &loc);
- }
- break;
-
- default:
- /* Not a container, not a call, or a call whose value is used. */
- break;
- }
- }
-}
-
/* Convert a character from the host to the target execution character
set. cpplib handles this, mostly. */
"member %qD", t);
return error_mark_node;
}
- off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
- size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
- / BITS_PER_UNIT));
+ off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
+ 1)
+ / BITS_PER_UNIT));
break;
case ARRAY_REF:
if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
{
code = MINUS_EXPR;
- t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
+ t = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (t), t);
}
t = convert (sizetype, t);
off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
bool fold_p = false;
if (VEC_index (constructor_elt, v, 0)->index)
- maxindex = fold_convert (sizetype,
- VEC_index (constructor_elt,
- v, 0)->index);
+ maxindex = fold_convert_loc (input_location, sizetype,
+ VEC_index (constructor_elt,
+ v, 0)->index);
curindex = maxindex;
for (cnt = 1;
{
if (fold_p)
curindex = fold_convert (sizetype, curindex);
- curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
+ curindex = size_binop (PLUS_EXPR, curindex,
+ size_one_node);
}
if (tree_int_cst_lt (maxindex, curindex))
maxindex = curindex, fold_p = curfold_p;
Returns 0 if an error is encountered. */
static int
-sync_resolve_size (tree function, tree params)
+sync_resolve_size (tree function, VEC(tree,gc) *params)
{
tree type;
int size;
- if (params == NULL)
+ if (VEC_empty (tree, params))
{
error ("too few arguments to function %qE", function);
return 0;
}
- type = TREE_TYPE (TREE_VALUE (params));
+ type = TREE_TYPE (VEC_index (tree, params, 0));
if (TREE_CODE (type) != POINTER_TYPE)
goto incompatible;
was encountered; true on success. */
static bool
-sync_resolve_params (tree orig_function, tree function, tree params)
+sync_resolve_params (tree orig_function, tree function, VEC(tree, gc) *params)
{
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
tree ptype;
int number;
+ unsigned int parmnum;
/* We've declared the implementation functions to use "volatile void *"
as the pointer parameter, so we shouldn't get any complaints from the
call to check_function_arguments what ever type the user used. */
arg_types = TREE_CHAIN (arg_types);
- ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+ ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
number = 2;
/* For the rest of the values, we need to cast these to FTYPE, so that we
don't get warnings for passing pointer types, etc. */
+ parmnum = 0;
while (arg_types != void_list_node)
{
tree val;
- params = TREE_CHAIN (params);
- if (params == NULL)
+ ++parmnum;
+ if (VEC_length (tree, params) <= parmnum)
{
error ("too few arguments to function %qE", orig_function);
return false;
/* ??? Ideally for the first conversion we'd use convert_for_assignment
so that we get warnings for anything that doesn't match the pointer
type. This isn't portable across the C and C++ front ends atm. */
- val = TREE_VALUE (params);
+ val = VEC_index (tree, params, parmnum);
val = convert (ptype, val);
val = convert (TREE_VALUE (arg_types), val);
- TREE_VALUE (params) = val;
+ VEC_replace (tree, params, parmnum, val);
arg_types = TREE_CHAIN (arg_types);
number++;
being "an optional list of variables protected by the memory barrier".
No clue what that's supposed to mean, precisely, but we consider all
call-clobbered variables to be protected so we're safe. */
- TREE_CHAIN (params) = NULL;
+ VEC_truncate (tree, params, parmnum + 1);
return true;
}
PARAMS. */
static tree
-sync_resolve_return (tree params, tree result)
+sync_resolve_return (tree first_param, tree result)
{
- tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+ tree ptype = TREE_TYPE (TREE_TYPE (first_param));
ptype = TYPE_MAIN_VARIANT (ptype);
return convert (ptype, result);
}
function should be called immediately after parsing the call expression
before surrounding code has committed to the type of the expression.
+ LOC is the location of the builtin call.
+
FUNCTION is the DECL that has been invoked; it is known to be a builtin.
PARAMS is the argument list for the call. The return value is non-null
when expansion is complete, and null if normal processing should
continue. */
tree
-resolve_overloaded_builtin (tree function, tree params)
+resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
{
enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
switch (DECL_BUILT_IN_CLASS (function))
break;
case BUILT_IN_MD:
if (targetm.resolve_overloaded_builtin)
- return targetm.resolve_overloaded_builtin (function, params);
+ return targetm.resolve_overloaded_builtin (loc, function, params);
else
return NULL_TREE;
default:
case BUILT_IN_LOCK_RELEASE_N:
{
int n = sync_resolve_size (function, params);
- tree new_function, result;
+ tree new_function, first_param, result;
if (n == 0)
return error_mark_node;
if (!sync_resolve_params (function, new_function, params))
return error_mark_node;
- result = build_function_call (new_function, params);
+ first_param = VEC_index (tree, params, 0);
+ result = build_function_call_vec (loc, new_function, params, NULL);
if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
&& orig_code != BUILT_IN_LOCK_RELEASE_N)
- result = sync_resolve_return (params, result);
+ result = sync_resolve_return (first_param, result);
return result;
}
about division by zero. Do not issue a warning if DIVISOR has a
floating-point type, since we consider 0.0/0.0 a valid way of
generating a NaN. */
- if (skip_evaluation == 0
+ if (c_inhibit_evaluation_warnings == 0
&& (integer_zerop (divisor) || fixed_zerop (divisor)))
warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
}
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
}
+/* Record the types used by the current global variable declaration
+ being parsed, so that we can decide later to emit their debug info.
+ Those types are in types_used_by_cur_var_decl, and we are going to
+ store them in the types_used_by_vars_hash hash table.
+ DECL is the declaration of the global variable that has been parsed. */
+
+void
+record_types_used_by_current_var_decl (tree decl)
+{
+ gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
+
+ if (types_used_by_cur_var_decl)
+ {
+ tree node;
+ for (node = types_used_by_cur_var_decl;
+ node;
+ node = TREE_CHAIN (node))
+ {
+ tree type = TREE_PURPOSE (node);
+ types_used_by_var_decl_insert (type, decl);
+ }
+ types_used_by_cur_var_decl = NULL;
+ }
+}
+
+/* The C and C++ parsers both use vectors to hold function arguments.
+ For efficiency, we keep a cache of unused vectors. This is the
+ cache. */
+
+typedef VEC(tree,gc)* tree_gc_vec;
+DEF_VEC_P(tree_gc_vec);
+DEF_VEC_ALLOC_P(tree_gc_vec,gc);
+static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
+
+/* Return a new vector from the cache. If the cache is empty,
+ allocate a new vector. These vectors are GC'ed, so it is OK if the
+ pointer is not released.. */
+
+VEC(tree,gc) *
+make_tree_vector (void)
+{
+ if (!VEC_empty (tree_gc_vec, tree_vector_cache))
+ return VEC_pop (tree_gc_vec, tree_vector_cache);
+ else
+ {
+ /* Passing 0 to VEC_alloc returns NULL, and our callers require
+ that we always return a non-NULL value. The vector code uses
+ 4 when growing a NULL vector, so we do too. */
+ return VEC_alloc (tree, gc, 4);
+ }
+}
+
+/* Release a vector of trees back to the cache. */
+
+void
+release_tree_vector (VEC(tree,gc) *vec)
+{
+ if (vec != NULL)
+ {
+ VEC_truncate (tree, vec, 0);
+ VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
+ }
+}
+
+/* Get a new tree vector holding a single tree. */
+
+VEC(tree,gc) *
+make_tree_vector_single (tree t)
+{
+ VEC(tree,gc) *ret = make_tree_vector ();
+ VEC_quick_push (tree, ret, t);
+ return ret;
+}
+
+/* Get a new tree vector which is a copy of an existing one. */
+
+VEC(tree,gc) *
+make_tree_vector_copy (const VEC(tree,gc) *orig)
+{
+ VEC(tree,gc) *ret;
+ unsigned int ix;
+ tree t;
+
+ ret = make_tree_vector ();
+ VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
+ for (ix = 0; VEC_iterate (tree, orig, ix, t); ++ix)
+ VEC_quick_push (tree, ret, t);
+ return ret;
+}
+
#include "gt-c-common.h"