/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
{
tree copy = NULL_TREE;
int i;
- int n = TREE_OPERAND_LENGTH (exp);
- for (i = 1; i < n; i++)
+
+ for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
{
tree op = TREE_OPERAND (exp, i);
tree newop = SUBSTITUTE_IN_EXPR (op, f, r);
else
return exp;
}
+ break;
default:
gcc_unreachable ();
TREE_SET_CODE (t, code);
TREE_TYPE (t) = type;
-#ifdef USE_MAPPED_LOCATION
SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
-#else
- SET_EXPR_LOCUS (t, NULL);
-#endif
TREE_OPERAND (t, 0) = node;
TREE_BLOCK (t) = NULL_TREE;
if (node && !TYPE_P (node))
return block;
}
-#if 1 /* ! defined(USE_MAPPED_LOCATION) */
-/* ??? gengtype doesn't handle conditionals */
-static GTY(()) source_locus last_annotated_node;
-#endif
-
-#ifdef USE_MAPPED_LOCATION
-
expanded_location
expand_location (source_location loc)
{
return xloc;
}
-#else
-
-/* Record the exact location where an expression or an identifier were
- encountered. */
-
-void
-annotate_with_file_line (tree node, const char *file, int line)
-{
- location_t *new_loc;
-
- /* Roughly one percent of the calls to this function are to annotate
- a node with the same information already attached to that node!
- Just return instead of wasting memory. */
- if (EXPR_LOCUS (node)
- && EXPR_LINENO (node) == line
- && (EXPR_FILENAME (node) == file
- || !strcmp (EXPR_FILENAME (node), file)))
- {
- last_annotated_node = EXPR_LOCUS (node);
- return;
- }
-
- /* In heavily macroized code (such as GCC itself) this single
- entry cache can reduce the number of allocations by more
- than half. */
- if (last_annotated_node
- && last_annotated_node->line == line
- && (last_annotated_node->file == file
- || !strcmp (last_annotated_node->file, file)))
- {
- SET_EXPR_LOCUS (node, last_annotated_node);
- return;
- }
-
- new_loc = GGC_NEW (location_t);
- new_loc->file = file;
- new_loc->line = line;
- SET_EXPR_LOCUS (node, new_loc);
- last_annotated_node = new_loc;
-}
-
-void
-annotate_with_locus (tree node, location_t locus)
-{
- annotate_with_file_line (node, locus.file, locus.line);
-}
-#endif
\f
/* Source location accessor functions. */
location_t
expr_location (const_tree node)
{
-#ifdef USE_MAPPED_LOCATION
if (GIMPLE_STMT_P (node))
return GIMPLE_STMT_LOCUS (node);
return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION;
-#else
- if (GIMPLE_STMT_P (node))
- return EXPR_HAS_LOCATION (node)
- ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION;
- return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION;
-#endif
}
void
set_expr_location (tree node, location_t locus)
{
-#ifdef USE_MAPPED_LOCATION
if (GIMPLE_STMT_P (node))
GIMPLE_STMT_LOCUS (node) = locus;
else
EXPR_CHECK (node)->exp.locus = locus;
-#else
- annotate_with_locus (node, locus);
-#endif
}
bool
expr_has_location (const_tree node)
{
-#ifdef USE_MAPPED_LOCATION
return expr_location (node) != UNKNOWN_LOCATION;
-#else
- return expr_locus (node) != NULL;
-#endif
}
-#ifdef USE_MAPPED_LOCATION
source_location *
-#else
-source_locus
-#endif
expr_locus (const_tree node)
{
-#ifdef USE_MAPPED_LOCATION
if (GIMPLE_STMT_P (node))
return CONST_CAST (source_location *, &GIMPLE_STMT_LOCUS (node));
return (EXPR_P (node)
? CONST_CAST (source_location *, &node->exp.locus)
: (source_location *) NULL);
-#else
- if (GIMPLE_STMT_P (node))
- return GIMPLE_STMT_LOCUS (node);
- return EXPR_P (node) ? node->exp.locus : (source_locus) NULL;
-#endif
}
void
-set_expr_locus (tree node,
-#ifdef USE_MAPPED_LOCATION
- source_location *loc
-#else
- source_locus loc
-#endif
- )
+set_expr_locus (tree node, source_location *loc)
{
-#ifdef USE_MAPPED_LOCATION
if (loc == NULL)
{
if (GIMPLE_STMT_P (node))
else
EXPR_CHECK (node)->exp.locus = *loc;
}
-#else
- if (GIMPLE_STMT_P (node))
- GIMPLE_STMT_LOCUS (node) = loc;
- else
- EXPR_CHECK (node)->exp.locus = loc;
-#endif
}
/* Return the file name of the location of NODE. */
expr_filename (const_tree node)
{
if (GIMPLE_STMT_P (node))
- return LOCATION_FILE (location_from_locus (GIMPLE_STMT_LOCUS (node)));
- return LOCATION_FILE (location_from_locus (EXPR_CHECK (node)->exp.locus));
+ return LOCATION_FILE (GIMPLE_STMT_LOCUS (node));
+ return LOCATION_FILE (EXPR_CHECK (node)->exp.locus);
}
/* Return the line number of the location of NODE. */
expr_lineno (const_tree node)
{
if (GIMPLE_STMT_P (node))
- return LOCATION_LINE (location_from_locus (GIMPLE_STMT_LOCUS (node)));
- return LOCATION_LINE (location_from_locus (EXPR_CHECK (node)->exp.locus));
+ return LOCATION_LINE (GIMPLE_STMT_LOCUS (node));
+ return LOCATION_LINE (EXPR_CHECK (node)->exp.locus);
}
\f
tree ntype;
enum tree_code code = TREE_CODE (ttype);
- ntype = copy_node (ttype);
+ /* Building a distinct copy of a tagged type is inappropriate; it
+ causes breakage in code that expects there to be a one-to-one
+ relationship between a struct and its fields.
+ build_duplicate_type is another solution (as used in
+ handle_transparent_union_attribute), but that doesn't play well
+ with the stronger C++ type identity model. */
+ if (TREE_CODE (ttype) == RECORD_TYPE
+ || TREE_CODE (ttype) == UNION_TYPE
+ || TREE_CODE (ttype) == QUAL_UNION_TYPE
+ || TREE_CODE (ttype) == ENUMERAL_TYPE)
+ {
+ warning (OPT_Wattributes,
+ "ignoring attributes applied to %qT after definition",
+ TYPE_MAIN_VARIANT (ttype));
+ return build_qualified_type (ttype, quals);
+ }
- TYPE_POINTER_TO (ntype) = 0;
- TYPE_REFERENCE_TO (ntype) = 0;
- TYPE_ATTRIBUTES (ntype) = attribute;
+ ntype = build_distinct_type_copy (ttype);
- /* Create a new main variant of TYPE. */
- TYPE_MAIN_VARIANT (ntype) = ntype;
- TYPE_NEXT_VARIANT (ntype) = 0;
+ TYPE_ATTRIBUTES (ntype) = attribute;
set_type_quals (ntype, TYPE_UNQUALIFIED);
hashcode = iterative_hash_object (code, hashcode);
hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
break;
case ARRAY_TYPE:
- hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
- hashcode);
+ if (TYPE_DOMAIN (ntype))
+ hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
+ hashcode);
break;
case INTEGER_TYPE:
hashcode = iterative_hash_object
ttype = build_qualified_type (ntype, quals);
}
+ else if (TYPE_QUALS (ttype) != quals)
+ ttype = build_qualified_type (ttype, quals);
return ttype;
}
return NULL_TREE;
}
+ if (TREE_CODE (node) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
+ {
+ *no_add_attrs = true;
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
/* Report error on dllimport ambiguities seen now before they cause
any damage. */
else if (is_attribute_p ("dllimport", name))
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
}
-/* Returns true iff cand is equivalent to base with type_quals. */
+/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */
bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
struct tree_map_base in;
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
- gcc_assert (TREE_CODE (decl) == VAR_DECL
- ? DECL_HAS_INIT_PRIORITY_P (decl)
- : DECL_STATIC_CONSTRUCTOR (decl));
in.from = decl;
h = htab_find (init_priority_for_decl, &in);
return h ? h->init : DEFAULT_INIT_PRIORITY;
struct tree_map_base in;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- gcc_assert (DECL_STATIC_DESTRUCTOR (decl));
in.from = decl;
h = htab_find (init_priority_for_decl, &in);
return h ? h->fini : DEFAULT_INIT_PRIORITY;
h->hash = hashcode;
h->type = type;
loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
- *(struct type_hash **) loc = h;
+ *loc = (void *)h;
}
/* Given TYPE, and HASHCODE its hash code, return the canonical
|| (! pos && TREE_INT_CST_HIGH (t) == -1
&& (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
&& (!TYPE_UNSIGNED (TREE_TYPE (t))
- || TYPE_IS_SIZETYPE (TREE_TYPE (t))))
+ || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (t)))))
|| (pos && TREE_INT_CST_HIGH (t) == 0)));
}
If FOR_TYPE is nonzero, we return a value which, if converted to
type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE.
- If FOR_TYPE is nonzero, unaligned bit-field references may be changed to the
- narrowest type that can hold the value, even if they don't exactly fit.
- Otherwise, bit-field references are changed to a narrower type
- only if they can be fetched directly from memory in that type.
-
OP must have integer, real or enumeral type. Pointers are not allowed!
There are some cases where the obvious value we could return
}
}
- if (TREE_CODE (op) == COMPONENT_REF
- /* Since type_for_size always gives an integer type. */
- && TREE_CODE (type) != REAL_TYPE
- && TREE_CODE (type) != FIXED_POINT_TYPE
- /* Don't crash if field not laid out yet. */
- && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
- && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
- {
- unsigned int innerprec
- = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
- int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
- || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
- type = lang_hooks.types.type_for_size (innerprec, unsignedp);
-
- /* We can get this structure field in the narrowest type it fits in.
- If FOR_TYPE is 0, do this only for a field that matches the
- narrower type exactly and is aligned for it
- The resulting extension to its nominal type (a fullword type)
- must fit the same conditions as for other extensions. */
-
- if (type != 0
- && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (op)))
- && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
- && (! uns || final_prec <= innerprec || unsignedp))
- {
- win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
- TREE_OPERAND (op, 1), NULL_TREE);
- TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
- TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
- }
- }
-
return win;
}
\f
inner,
TREE_CHAIN (TYPE_ARG_TYPES (type)));
}
+ else if (TREE_CODE (type) == OFFSET_TYPE)
+ {
+ inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner);
+ }
else
return bottom;
return orig_field;
}
-/* Return value of a constant X. */
+/* Return value of a constant X and sign-extend it. */
HOST_WIDE_INT
int_cst_value (const_tree x)
{
unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
- bool negative = ((val >> (bits - 1)) & 1) != 0;
- gcc_assert (bits <= HOST_BITS_PER_WIDE_INT);
+ /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
+ gcc_assert (TREE_INT_CST_HIGH (x) == 0
+ || TREE_INT_CST_HIGH (x) == -1);
- if (negative)
- val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
- else
- val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+ if (bits < HOST_BITS_PER_WIDE_INT)
+ {
+ bool negative = ((val >> (bits - 1)) & 1) != 0;
+ if (negative)
+ val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+ else
+ val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+ }
return val;
}