/* Language-dependent 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, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "debug.h"
#include "target.h"
#include "convert.h"
+#include "tree-flow.h"
+#include "cgraph.h"
static tree bot_manip (tree *, int *, void *);
static tree bot_replace (tree *, int *, void *);
static int list_hash_eq (const void *, const void *);
static hashval_t list_hash_pieces (tree, tree, tree);
static hashval_t list_hash (const void *);
-static cp_lvalue_kind lvalue_p_1 (tree, int);
+static cp_lvalue_kind lvalue_p_1 (const_tree);
static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
- Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- nonzero, rvalues of class type are considered lvalues. */
+ Otherwise, returns clk_none. */
static cp_lvalue_kind
-lvalue_p_1 (tree ref,
- int treat_class_rvalues_as_lvalues)
+lvalue_p_1 (const_tree ref)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
if (TREE_CODE (ref) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
== REFERENCE_TYPE)
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{
&& TREE_CODE (ref) != PARM_DECL
&& TREE_CODE (ref) != VAR_DECL
&& TREE_CODE (ref) != COMPONENT_REF)
- return clk_none;
+ return clk_rvalueref;
/* lvalue references and named rvalue references are lvalues. */
return clk_ordinary;
switch (TREE_CODE (ref))
{
+ case SAVE_EXPR:
+ return clk_none;
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
- case SAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
case COMPONENT_REF:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
/* Look at the member designator. */
- if (!op1_lvalue_kind
- /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
- situations. */
- || TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+ if (!op1_lvalue_kind)
;
+ else if (is_overloaded_fn (TREE_OPERAND (ref, 1)))
+ /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+ situations. If we're seeing a COMPONENT_REF, it's a non-static
+ member, so it isn't an lvalue. */
+ op1_lvalue_kind = clk_none;
+ else if (TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+ /* This can be IDENTIFIER_NODE in a template. */;
else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
return op1_lvalue_kind;
case STRING_CST:
+ case COMPOUND_LITERAL_EXPR:
return clk_ordinary;
case CONST_DECL:
+ /* CONST_DECL without TREE_STATIC are enumeration values and
+ thus not lvalues. With TREE_STATIC they are used by ObjC++
+ in objc_build_string_object and need to be considered as
+ lvalues. */
+ if (! TREE_STATIC (ref))
+ return clk_none;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
|| TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
return clk_none;
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
+ ? TREE_OPERAND (ref, 1)
+ : TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 1));
case TARGET_EXPR:
- return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
+ return clk_class;
case VA_ARG_EXPR:
- return (treat_class_rvalues_as_lvalues
- && CLASS_TYPE_P (TREE_TYPE (ref))
- ? clk_class : clk_none);
+ return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
case CALL_EXPR:
/* Any class-valued call would be wrapped in a TARGET_EXPR. */
return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : clk_ordinary);
+ case BASELINK:
+ /* We now represent a reference to a single static member function
+ with a BASELINK. */
+ /* This CONST_CAST is okay because BASELINK_FUNCTIONS returns
+ its argument unmodified and we assign it to a const_tree. */
+ return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
+
case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
things like "&E" where "E" is an expression with a
/* Otherwise, it's an lvalue, and it has all the odd properties
contributed by either operand. */
op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
- /* It's not an ordinary lvalue if it involves either a bit-field or
- a class rvalue. */
+ /* It's not an ordinary lvalue if it involves any other kind. */
if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
op1_lvalue_kind &= ~clk_ordinary;
+ /* It can't be both a pseudo-lvalue and a non-addressable lvalue.
+ A COND_EXPR of those should be wrapped in a TARGET_EXPR. */
+ if ((op1_lvalue_kind & (clk_rvalueref|clk_class))
+ && (op1_lvalue_kind & (clk_bitfield|clk_packed)))
+ op1_lvalue_kind = clk_none;
return op1_lvalue_kind;
}
cp_lvalue_kind
real_lvalue_p (tree ref)
{
- return lvalue_p_1 (ref,
- /*treat_class_rvalues_as_lvalues=*/0);
+ cp_lvalue_kind kind = lvalue_p_1 (ref);
+ if (kind & (clk_rvalueref|clk_class))
+ return clk_none;
+ else
+ return kind;
}
-/* This differs from real_lvalue_p in that class rvalues are
- considered lvalues. */
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
-int
-lvalue_p (tree ref)
+bool
+lvalue_p (const_tree ref)
{
- return
- (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
+ return (lvalue_p_1 (ref) != clk_none);
+}
+
+/* This differs from real_lvalue_p in that rvalues formed by dereferencing
+ rvalue references are considered rvalues. */
+
+bool
+lvalue_or_rvalue_with_address_p (const_tree ref)
+{
+ cp_lvalue_kind kind = lvalue_p_1 (ref);
+ if (kind & clk_class)
+ return false;
+ else
+ return (kind != clk_none);
}
/* Test whether DECL is a builtin that may appear in a
constant-expression. */
bool
-builtin_valid_in_constant_expr_p (tree decl)
+builtin_valid_in_constant_expr_p (const_tree decl)
{
/* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
in constant-expressions. We may want to add other builtins later. */
{
tree t;
+#ifdef ENABLE_CHECKING
+ gcc_assert (VOID_TYPE_P (TREE_TYPE (value))
+ || TREE_TYPE (decl) == TREE_TYPE (value)
+ || useless_type_conversion_p (TREE_TYPE (decl),
+ TREE_TYPE (value)));
+#endif
+
t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
cxx_maybe_build_cleanup (decl), NULL_TREE);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
static tree
build_local_temp (tree type)
{
- tree slot = build_decl (VAR_DECL, NULL_TREE, type);
+ tree slot = build_decl (input_location,
+ VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_IGNORED_P (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
}
/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
- target. TYPE is the type that this initialization should appear to
- have.
+ target. TYPE is the type to be initialized.
- Build an encapsulation of the initialization to perform
- and return it so that it can be processed by language-independent
- and language-specific expression expanders. */
+ Build an AGGR_INIT_EXPR to represent the initialization. This function
+ differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
+ to initialize another object, whereas a TARGET_EXPR can either
+ initialize another object or create its own temporary object, and as a
+ result building up a TARGET_EXPR requires that the type's destructor be
+ callable. */
tree
-build_cplus_new (tree type, tree init)
+build_aggr_init_expr (tree type, tree init)
{
tree fn;
tree slot;
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
- slot = build_local_temp (type);
-
/* We split the CALL_EXPR into its function and its arguments here.
Then, in expand_expr, we put them back together. The reason for
this is that this expression might be a default argument
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
+ slot = build_local_temp (type);
+
if (TREE_CODE(init) == CALL_EXPR)
rval = build_aggr_init_array (void_type_node, fn, slot,
call_expr_nargs (init),
else
rval = init;
+ return rval;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+ target. TYPE is the type that this initialization should appear to
+ have.
+
+ Build an encapsulation of the initialization to perform
+ and return it so that it can be processed by language-independent
+ and language-specific expression expanders. */
+
+tree
+build_cplus_new (tree type, tree init)
+{
+ tree rval = build_aggr_init_expr (type, init);
+ tree slot;
+
+ if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+ slot = AGGR_INIT_EXPR_SLOT (rval);
+ else if (TREE_CODE (rval) == CALL_EXPR)
+ slot = build_local_temp (type);
+ else
+ return rval;
+
rval = build_target_expr (slot, rval);
TARGET_EXPR_IMPLICIT_P (rval) = 1;
return rval;
}
+/* Return a TARGET_EXPR which expresses the direct-initialization of one
+ array from another. */
+
+tree
+build_array_copy (tree init)
+{
+ tree type = TREE_TYPE (init);
+ tree slot = build_local_temp (type);
+ init = build2 (VEC_INIT_EXPR, type, slot, init);
+ SET_EXPR_LOCATION (init, input_location);
+ init = build_target_expr (slot, init);
+ TARGET_EXPR_IMPLICIT_P (init) = 1;
+
+ return init;
+}
+
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
if (TREE_CODE (init) == TARGET_EXPR)
return init;
else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)
+ && !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
&& TREE_CODE (init) != VA_ARG_EXPR)
- /* We need to build up a copy constructor call. COND_EXPR is a special
+ /* We need to build up a copy constructor call. A void initializer
+ means we're being called from bot_manip. COND_EXPR is a special
case because we already have copies on the arms and we don't want
another one here. A CONSTRUCTOR is aggregate initialization, which
is handled separately. A VA_ARG_EXPR is magic creation of an
tree
get_target_expr (tree init)
{
- return build_target_expr_with_type (init, TREE_TYPE (init));
+ if (TREE_CODE (init) == AGGR_INIT_EXPR)
+ return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init);
+ else
+ return build_target_expr_with_type (init, TREE_TYPE (init));
}
/* If EXPR is a bitfield reference, convert it to the declared type of
Non-class rvalues always have cv-unqualified types. */
type = TREE_TYPE (expr);
- if (!CLASS_TYPE_P (type) && cp_type_quals (type))
- type = TYPE_MAIN_VARIANT (type);
+ if (!CLASS_TYPE_P (type) && cv_qualified_p (type))
+ type = cv_unqualified (type);
- if (!processing_template_decl && real_lvalue_p (expr))
+ /* We need to do this for rvalue refs as well to get the right answer
+ from decltype; see c++/36628. */
+ if (!processing_template_decl && lvalue_or_rvalue_with_address_p (expr))
expr = build1 (NON_LVALUE_EXPR, type, expr);
else if (type != TREE_TYPE (expr))
expr = build_nop (type, expr);
hashval_t hash;
const_tree const t = (const_tree) k;
- hash = (htab_hash_pointer (TREE_TYPE (t))
- ^ htab_hash_pointer (TYPE_DOMAIN (t)));
-
+ hash = TYPE_UID (TREE_TYPE (t));
+ if (TYPE_DOMAIN (t))
+ hash ^= TYPE_UID (TYPE_DOMAIN (t));
return hash;
}
const_tree const t1 = (const_tree) k1;
const cplus_array_info *const t2 = (const cplus_array_info*) k2;
- if (!comptypes (TREE_TYPE (t1), t2->type, COMPARE_STRUCTURAL))
- return 0;
-
- if (!TYPE_DOMAIN (t1))
- return !t2->domain;
-
- if (!t2->domain)
- return 0;
-
- return comptypes (TYPE_DOMAIN (t1), t2->domain, COMPARE_STRUCTURAL);
+ return (TREE_TYPE (t1) == t2->type && TYPE_DOMAIN (t1) == t2->domain);
}
+/* Hash table containing all of the C++ array types, including
+ dependent array types and array types whose element type is
+ cv-qualified. */
static GTY ((param_is (union tree_node))) htab_t cplus_array_htab;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
- if (dependent_type_p (elt_type)
- || (index_type
- && value_dependent_expression_p (TYPE_MAX_VALUE (index_type))))
+ if (processing_template_decl
+ && (dependent_type_p (elt_type)
+ || (index_type && !TREE_CONSTANT (TYPE_MAX_VALUE (index_type)))))
{
void **e;
cplus_array_info cai;
hashval_t hash;
-
+
if (cplus_array_htab == NULL)
cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
&cplus_array_compare, NULL);
- hash = (htab_hash_pointer (elt_type)
- ^ htab_hash_pointer (index_type));
+ hash = TYPE_UID (elt_type);
+ if (index_type)
+ hash ^= TYPE_UID (index_type);
cai.type = elt_type;
cai.domain = index_type;
e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash, INSERT);
if (*e)
- /* We have found the type: we're done. */
+ /* We have found the type: we're done. */
return (tree) *e;
else
{
- /* Build a new array type. */
- t = make_node (ARRAY_TYPE);
+ /* Build a new array type. */
+ t = cxx_make_type (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
- /* Complete building the array type. */
+ /* Store it in the hash table. */
+ *e = t;
+
+ /* Set the canonical type for this new node. */
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
|| (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (elt_type) != elt_type
|| (index_type
&& TYPE_CANONICAL (index_type) != index_type))
- TYPE_CANONICAL (t)
- = TYPE_CANONICAL
- (build_cplus_array_type_1 (TYPE_CANONICAL (elt_type),
- index_type?
- TYPE_CANONICAL (index_type)
- : index_type));
-
- /* Store it in the hash table. */
- *e = t;
+ TYPE_CANONICAL (t)
+ = build_cplus_array_type
+ (TYPE_CANONICAL (elt_type),
+ index_type ? TYPE_CANONICAL (index_type) : index_type);
+ else
+ TYPE_CANONICAL (t) = t;
}
}
else
return t;
}
+/* Return an ARRAY_TYPE with element type ELT and length N. */
+
+tree
+build_array_of_n_type (tree elt, int n)
+{
+ return build_cplus_array_type (elt, build_index_type (size_int (n - 1)));
+}
+
/* Return a reference type node referring to TO_TYPE. If RVAL is
true, return an rvalue reference type, otherwise return an lvalue
reference type. If a type node exists, reuse it, otherwise create
if (TYPE_REF_IS_RVALUE (t))
return t;
- t = copy_node (lvalue_ref);
+ t = build_distinct_type_copy (lvalue_ref);
TYPE_REF_IS_RVALUE (t) = true;
TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
TYPE_NEXT_REF_TO (lvalue_ref) = t;
- TYPE_MAIN_VARIANT (t) = t;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
}
+/* Returns EXPR cast to rvalue reference type, like std::move. */
+
+tree
+move (tree expr)
+{
+ tree type = TREE_TYPE (expr);
+ gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
+ type = cp_build_reference_type (type, /*rval*/true);
+ return build_static_cast (type, expr, tf_warning_or_error);
+}
+
+/* Used by the C++ front end to build qualified array types. However,
+ the C version of this function does not properly maintain canonical
+ types (which are not used in C). */
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+ return cp_build_qualified_type (type, type_quals);
+}
\f
/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
arrays correctly. In particular, if TYPE is an array of T's, and
TYPE_QUALS is non-empty, returns an array of qualified T's.
- FLAGS determines how to deal with illformed qualifications. If
+ FLAGS determines how to deal with ill-formed qualifications. If
tf_ignore_bad_quals is set, then bad qualifications are dropped
(this is permitted if TYPE was introduced via a typedef or template
type parameter). If bad qualifications are dropped and tf_warning
break;
if (!t)
- {
- tree domain = TYPE_DOMAIN (type);
-
- /* Make a new array type, just like the old one, but with the
- appropriately qualified element type. */
- t = build_variant_type_copy (type);
- TREE_TYPE (t) = element_type;
-
- /* This is a new type. */
- TYPE_CANONICAL (t) = t;
-
- if (dependent_type_p (element_type)
- || (domain
- && value_dependent_expression_p (TYPE_MAX_VALUE (domain))))
- {
- /* The new dependent array type we just created might be
- equivalent to an existing dependent array type, so we
- need to keep track of this new array type with a
- lookup into CPLUS_ARRAY_HTAB. Note that we cannot
- directly call build_cplus_array_type (that would
- recurse) or build_cplus_array_type_1 (that would lose
- attributes). */
- void **e;
- cplus_array_info cai;
- hashval_t hash;
-
- if (cplus_array_htab == NULL)
- cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
- &cplus_array_compare,
- NULL);
-
- hash = (htab_hash_pointer (element_type)
- ^ htab_hash_pointer (domain));
- cai.type = element_type;
- cai.domain = domain;
-
- e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash,
- INSERT);
- if (! *e)
- /* Save this new type. */
- *e = t;
- }
+ {
+ t = build_cplus_array_type_1 (element_type, TYPE_DOMAIN (type));
- if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t))
- || (TYPE_DOMAIN (t)
- && TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (t))))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else
- TYPE_CANONICAL (t)
- = TYPE_CANONICAL
- (build_array_type (TYPE_CANONICAL (TREE_TYPE (t)),
- TYPE_DOMAIN (t)?
- TYPE_CANONICAL (TYPE_DOMAIN(t))
- : TYPE_DOMAIN (t)));
- }
+ if (TYPE_MAIN_VARIANT (t) != TYPE_MAIN_VARIANT (type))
+ {
+ /* Set the main variant of the newly-created ARRAY_TYPE
+ (with cv-qualified element type) to the main variant of
+ the unqualified ARRAY_TYPE we started with. */
+ tree last_variant = t;
+ tree m = TYPE_MAIN_VARIANT (type);
+
+ /* Find the last variant on the new ARRAY_TYPEs list of
+ variants, setting the main variant of each of the other
+ types to the main variant of our unqualified
+ ARRAY_TYPE. */
+ while (TYPE_NEXT_VARIANT (last_variant))
+ {
+ TYPE_MAIN_VARIANT (last_variant) = m;
+ last_variant = TYPE_NEXT_VARIANT (last_variant);
+ }
+
+ /* Splice in the newly-created variants. */
+ TYPE_NEXT_VARIANT (last_variant) = TYPE_NEXT_VARIANT (m);
+ TYPE_NEXT_VARIANT (m) = t;
+ TYPE_MAIN_VARIANT (last_variant) = m;
+ }
+ }
/* Even if we already had this variant, we update
TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
t = cp_build_qualified_type_real (t, type_quals, complain);
return build_ptrmemfunc_type (t);
}
+ else if (TREE_CODE (type) == TYPE_PACK_EXPANSION)
+ {
+ tree t = PACK_EXPANSION_PATTERN (type);
+
+ t = cp_build_qualified_type_real (t, type_quals, complain);
+ return make_pack_expansion (t);
+ }
- /* A reference or method type shall not be cv qualified.
- [dcl.ref], [dct.fct] */
+ /* A reference or method type shall not be cv-qualified.
+ [dcl.ref], [dcl.fct] */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
}
/* A restrict-qualified type must be a pointer (or reference)
- to object or incomplete type, or a function type. */
+ to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
- && TREE_CODE (type) != FUNCTION_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
between the unqualified and qualified types. */
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+ && TYPE_LANG_SPECIFIC (result) == TYPE_LANG_SPECIFIC (type))
TYPE_LANG_SPECIFIC (result) = NULL;
+ /* We may also have ended up building a new copy of the canonical
+ type of a pointer-to-method type, which could have the same
+ sharing problem described above. */
+ if (TYPE_CANONICAL (result) != TYPE_CANONICAL (type)
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+ && (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result))
+ == TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type))))
+ TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) = NULL;
+
return result;
}
-/* Returns the canonical version of TYPE. In other words, if TYPE is
- a typedef, returns the underlying type. The cv-qualification of
- the type returned matches the type input; they will always be
- compatible types. */
+/* Return TYPE with const and volatile removed. */
tree
-canonical_type_variant (tree t)
+cv_unqualified (tree type)
+{
+ int quals = TYPE_QUALS (type);
+ quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
+ return cp_build_qualified_type (type, quals);
+}
+
+/* Builds a qualified variant of T that is not a typedef variant.
+ E.g. consider the following declarations:
+ typedef const int ConstInt;
+ typedef ConstInt* PtrConstInt;
+ If T is PtrConstInt, this function returns a type representing
+ const int*.
+ In other words, if T is a typedef, the function returns the underlying type.
+ The cv-qualification and attributes of the type returned match the
+ input type.
+ They will always be compatible types.
+ The returned type is built so that all of its subtypes
+ recursively have their typedefs stripped as well.
+
+ This is different from just returning TYPE_CANONICAL (T)
+ Because of several reasons:
+ * If T is a type that needs structural equality
+ its TYPE_CANONICAL (T) will be NULL.
+ * TYPE_CANONICAL (T) desn't carry type attributes
+ and looses template parameter names. */
+
+tree
+strip_typedefs (tree t)
{
- return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
+ tree result = NULL, type = NULL, t0 = NULL;
+
+ if (!t || t == error_mark_node || t == TYPE_CANONICAL (t))
+ return t;
+
+ gcc_assert (TYPE_P (t));
+
+ switch (TREE_CODE (t))
+ {
+ case POINTER_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_pointer_type (type);
+ break;
+ case REFERENCE_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
+ break;
+ case OFFSET_TYPE:
+ t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t));
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_offset_type (t0, type);
+ break;
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ {
+ t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ result = build_ptrmemfunc_type (t0);
+ }
+ break;
+ case ARRAY_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ t0 = strip_typedefs (TYPE_DOMAIN (t));;
+ result = build_cplus_array_type (type, t0);
+ break;
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree arg_types = NULL, arg_node, arg_type;
+ for (arg_node = TYPE_ARG_TYPES (t);
+ arg_node;
+ arg_node = TREE_CHAIN (arg_node))
+ {
+ if (arg_node == void_list_node)
+ break;
+ arg_type = strip_typedefs (TREE_VALUE (arg_node));
+ gcc_assert (arg_type);
+
+ arg_types =
+ tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types);
+ }
+
+ if (arg_types)
+ arg_types = nreverse (arg_types);
+
+ /* A list of parameters not ending with an ellipsis
+ must end with void_list_node. */
+ if (arg_node)
+ arg_types = chainon (arg_types, void_list_node);
+
+ type = strip_typedefs (TREE_TYPE (t));
+ if (TREE_CODE (t) == METHOD_TYPE)
+ {
+ tree class_type = TREE_TYPE (TREE_VALUE (arg_types));
+ gcc_assert (class_type);
+ result =
+ build_method_type_directly (class_type, type,
+ TREE_CHAIN (arg_types));
+ }
+ else
+ result = build_function_type (type,
+ arg_types);
+
+ if (TYPE_RAISES_EXCEPTIONS (t))
+ result = build_exception_variant (result,
+ TYPE_RAISES_EXCEPTIONS (t));
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!result)
+ result = TYPE_MAIN_VARIANT (t);
+ if (TYPE_ATTRIBUTES (t))
+ result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
+ return cp_build_qualified_type (result, cp_type_quals (t));
}
+
+/* Returns true iff TYPE is a type variant created for a typedef. */
+
+bool
+typedef_variant_p (tree type)
+{
+ return is_typedef_decl (TYPE_NAME (type));
+}
+
\f
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
return error_mark_node;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
+ if (type)
+ t = convert_from_reference (t);
return t;
}
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);
- if (TREE_CODE (x) == TEMPLATE_ID_EXPR
- || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
+ if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
+ x = TREE_OPERAND (x, 0);
+ if (DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
|| (TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x)))
return 2;
return (TREE_CODE (x) == FUNCTION_DECL
{
gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == COMPONENT_REF)
+ if (TREE_CODE (from) == OFFSET_REF
+ || TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
+ if (TREE_CODE (from) == TEMPLATE_ID_EXPR)
+ from = TREE_OPERAND (from, 0);
return OVL_CURRENT (from);
}
\f
#define PRINT_RING_SIZE 4
-const char *
-cxx_printable_name (tree decl, int v)
+static const char *
+cxx_printable_name_internal (tree decl, int v, bool translate)
{
- static tree decl_ring[PRINT_RING_SIZE];
+ static unsigned int uid_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
+ static bool trans_ring[PRINT_RING_SIZE];
static int ring_counter;
int i;
if (v < 2
|| TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
- return lang_decl_name (decl, v);
+ return lang_decl_name (decl, v, translate);
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
- if (decl_ring[i] == decl)
+ if (uid_ring[i] == DECL_UID (decl) && translate == trans_ring[i])
/* yes, so return it. */
return print_ring[i];
if (current_function_decl != NULL_TREE)
{
- if (decl_ring[ring_counter] == current_function_decl)
- ring_counter += 1;
- if (ring_counter == PRINT_RING_SIZE)
- ring_counter = 0;
- gcc_assert (decl_ring[ring_counter] != current_function_decl);
+ /* There may be both translated and untranslated versions of the
+ name cached. */
+ for (i = 0; i < 2; i++)
+ {
+ if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
+ ring_counter += 1;
+ if (ring_counter == PRINT_RING_SIZE)
+ ring_counter = 0;
+ }
+ gcc_assert (uid_ring[ring_counter] != DECL_UID (current_function_decl));
}
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
- print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
- decl_ring[ring_counter] = decl;
+ print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v, translate));
+ uid_ring[ring_counter] = DECL_UID (decl);
+ trans_ring[ring_counter] = translate;
return print_ring[ring_counter];
}
+
+const char *
+cxx_printable_name (tree decl, int v)
+{
+ return cxx_printable_name_internal (decl, v, false);
+}
+
+const char *
+cxx_printable_name_translate (tree decl, int v)
+{
+ return cxx_printable_name_internal (decl, v, true);
+}
\f
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
tree decl = TYPE_NAME (t);
tree t2;
- t2 = make_aggr_type (BOUND_TEMPLATE_TEMPLATE_PARM);
- decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);
+ t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
+ decl = build_decl (input_location,
+ TYPE_DECL, DECL_NAME (decl), NULL_TREE);
/* These nodes have to be created to reflect new TYPE_DECL and template
arguments. */
TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
- = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
- newargs, NULL_TREE);
+ = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs);
TREE_TYPE (decl) = t2;
TYPE_NAME (t2) = decl;
count_trees (tree t)
{
int n_trees = 0;
- walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
+ cp_walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
return n_trees;
}
{
htab_t statements;
statements = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
- walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
+ cp_walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
htab_delete (statements);
}
/* Check if the type T depends on a type with no linkage and if so, return
it. If RELAXED_P then do not consider a class type declared within
- a TREE_PUBLIC function to have no linkage. */
+ a vague-linkage function to have no linkage. */
tree
no_linkage_check (tree t, bool relaxed_p)
switch (TREE_CODE (t))
{
- tree fn;
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
+ /* Lambda types that don't have mangling scope have no linkage. We
+ check CLASSTYPE_LAMBDA_EXPR here rather than LAMBDA_TYPE_P because
+ when we get here from pushtag none of the lambda information is
+ set up yet, so we want to assume that the lambda has linkage and
+ fix it up later if not. */
+ if (CLASSTYPE_LAMBDA_EXPR (t)
+ && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE)
+ return t;
/* Fall through. */
case UNION_TYPE:
if (!CLASS_TYPE_P (t))
return NULL_TREE;
/* Fall through. */
case ENUMERAL_TYPE:
- if (TYPE_ANONYMOUS_P (t))
- return t;
- fn = decl_function_context (TYPE_MAIN_DECL (t));
- if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
+ /* Only treat anonymous types as having no linkage if they're at
+ namespace scope. This doesn't have a core issue number yet. */
+ if (TYPE_ANONYMOUS_P (t) && TYPE_NAMESPACE_SCOPE_P (t))
return t;
+
+ for (r = CP_TYPE_CONTEXT (t); ; )
+ {
+ /* If we're a nested type of a !TREE_PUBLIC class, we might not
+ have linkage, or we might just be in an anonymous namespace.
+ If we're in a TREE_PUBLIC class, we have linkage. */
+ if (TYPE_P (r) && !TREE_PUBLIC (TYPE_NAME (r)))
+ return no_linkage_check (TYPE_CONTEXT (t), relaxed_p);
+ else if (TREE_CODE (r) == FUNCTION_DECL)
+ {
+ if (!relaxed_p || !vague_linkage_fn_p (r))
+ return t;
+ else
+ r = CP_DECL_CONTEXT (r);
+ }
+ else
+ break;
+ }
+
return NULL_TREE;
case ARRAY_TYPE:
tree
array_type_nelts_top (tree type)
{
- return fold_build2 (PLUS_EXPR, sizetype,
+ return fold_build2_loc (input_location,
+ PLUS_EXPR, sizetype,
array_type_nelts (type),
- integer_one_node);
+ size_one_node);
}
/* Return, as an INTEGER_CST node, the number of elements for TYPE
while (TREE_CODE (type) == ARRAY_TYPE)
{
tree n = array_type_nelts_top (type);
- sz = fold_build2 (MULT_EXPR, sizetype, sz, n);
+ sz = fold_build2_loc (input_location,
+ MULT_EXPR, sizetype, sz, n);
type = TREE_TYPE (type);
}
return sz;
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new
- (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1));
else
- u = build_target_expr_with_type
- (break_out_target_exprs (TREE_OPERAND (t, 1)), TREE_TYPE (t));
+ u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
/* Map the old variable to the new one. */
splay_tree_insert (target_remap,
(splay_tree_key) TREE_OPERAND (t, 0),
(splay_tree_value) TREE_OPERAND (u, 0));
+ TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1));
+
/* Replace the old expression with the new version. */
*tp = u;
/* We don't have to go below this point; the recursive call to
target_remap = splay_tree_new (splay_tree_compare_pointers,
/*splay_tree_delete_key_fn=*/NULL,
/*splay_tree_delete_value_fn=*/NULL);
- walk_tree (&t, bot_manip, target_remap, NULL);
- walk_tree (&t, bot_replace, target_remap, NULL);
+ cp_walk_tree (&t, bot_manip, target_remap, NULL);
+ cp_walk_tree (&t, bot_replace, target_remap, NULL);
if (!--target_remap_count)
{
built. */
tree
-build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
+build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
{
- tree t = build_nt_call_list (fn, arglist);
+ tree t = build_nt_call_vec (fn, argvec);
TREE_TYPE (t) = TREE_TYPE (non_dep);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
return t;
nested, or false otherwise. */
bool
-decl_anon_ns_mem_p (tree decl)
+decl_anon_ns_mem_p (const_tree decl)
{
while (1)
{
return false;
for (code1 = TREE_CODE (t1);
- code1 == NOP_EXPR || code1 == CONVERT_EXPR
+ CONVERT_EXPR_CODE_P (code1)
|| code1 == NON_LVALUE_EXPR;
code1 = TREE_CODE (t1))
t1 = TREE_OPERAND (t1, 0);
for (code2 = TREE_CODE (t2);
- code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ CONVERT_EXPR_CODE_P (code2)
|| code1 == NON_LVALUE_EXPR;
code2 = TREE_CODE (t2))
t2 = TREE_OPERAND (t2, 0);
&& !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
TREE_STRING_LENGTH (t1));
+ case FIXED_CST:
+ return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
+ TREE_FIXED_CST (t2));
+
case COMPLEX_CST:
return cp_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
&& cp_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
return false;
return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
- case VAR_DECL:
case PARM_DECL:
+ /* For comparing uses of parameters in late-specified return types
+ with an out-of-class definition of the function. */
+ if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ && DECL_PARM_INDEX (t1) == DECL_PARM_INDEX (t2))
+ return true;
+ else
+ return false;
+
+ case VAR_DECL:
case CONST_DECL:
case FUNCTION_DECL:
case TEMPLATE_DECL:
case TEMPLATE_PARM_INDEX:
return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+ && (TEMPLATE_PARM_PARAMETER_PACK (t1)
+ == TEMPLATE_PARM_PARAMETER_PACK (t2))
&& same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
;
else if (real_lvalue_p (arg))
type = build_reference_type (lvalue_type (arg));
- else if (IS_AGGR_TYPE (type))
+ else if (MAYBE_CLASS_TYPE_P (type))
type = lvalue_type (arg);
return type;
/* Does FUNCTION use a variable-length argument list? */
int
-varargs_function_p (tree function)
+varargs_function_p (const_tree function)
{
- tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ const_tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
for (; parm; parm = TREE_CHAIN (parm))
if (TREE_VALUE (parm) == void_type_node)
return 0;
/* Returns 1 if decl is a member of a class. */
int
-member_p (tree decl)
+member_p (const_tree decl)
{
- const tree ctx = DECL_CONTEXT (decl);
+ const_tree const ctx = DECL_CONTEXT (decl);
return (ctx && TYPE_P (ctx));
}
build_dummy_object (tree type)
{
tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
- return build_indirect_ref (decl, NULL);
+ return cp_build_indirect_ref (decl, NULL, tf_warning_or_error);
}
/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
/* Returns 1 if OB is a placeholder object, or a pointer to one. */
int
-is_dummy_object (tree ob)
+is_dummy_object (const_tree ob)
{
if (TREE_CODE (ob) == INDIRECT_REF)
ob = TREE_OPERAND (ob, 0);
&& TREE_OPERAND (ob, 0) == void_zero_node);
}
-/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+ the purpose of deciding whether it is trivial/POD/standard-layout. */
-int
-pod_type_p (tree t)
+static bool
+scalarish_type_p (const_tree t)
{
- t = strip_array_types (t);
-
if (t == error_mark_node)
return 1;
- if (INTEGRAL_TYPE_P (t))
- return 1; /* integral, character or enumeral type */
- if (FLOAT_TYPE_P (t))
- return 1;
- if (TYPE_PTR_P (t))
- return 1; /* pointer to non-member */
- if (TYPE_PTR_TO_MEMBER_P (t))
- return 1; /* pointer to member */
- if (TREE_CODE (t) == VECTOR_TYPE)
- return 1; /* vectors are (small) arrays of scalars */
+ return (SCALAR_TYPE_P (t)
+ || TREE_CODE (t) == VECTOR_TYPE);
+}
+
+/* Returns true iff T requires non-trivial default initialization. */
+
+bool
+type_has_nontrivial_default_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_DFLT (t);
+ else
+ return 0;
+}
+
+/* Returns true iff copying an object of type T is non-trivial. */
- if (! CLASS_TYPE_P (t))
- return 0; /* other non-class type (reference or function) */
- if (CLASSTYPE_NON_POD_P (t))
+bool
+type_has_nontrivial_copy_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_INIT_REF (t);
+ else
return 0;
- return 1;
+}
+
+/* Returns 1 iff type T is a trivial type, as defined in [basic.types]. */
+
+bool
+trivial_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return (TYPE_HAS_TRIVIAL_DFLT (t)
+ && TYPE_HAS_TRIVIAL_INIT_REF (t)
+ && TYPE_HAS_TRIVIAL_ASSIGN_REF (t)
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (t));
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
+
+bool
+pod_type_p (const_tree t)
+{
+ /* This CONST_CAST is okay because strip_array_types returns its
+ argument unmodified and we assign it to a const_tree. */
+ t = strip_array_types (CONST_CAST_TREE(t));
+
+ if (CLASS_TYPE_P (t))
+ /* [class]/10: A POD struct is a class that is both a trivial class and a
+ standard-layout class, and has no non-static data members of type
+ non-POD struct, non-POD union (or array of such types).
+
+ We don't need to check individual members because if a member is
+ non-std-layout or non-trivial, the class will be too. */
+ return (std_layout_type_p (t) && trivial_type_p (t));
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is POD for the purpose of layout, as defined in the
+ C++ ABI. */
+
+bool
+layout_pod_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_LAYOUT_POD_P (t);
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is a standard-layout type, as defined in
+ [basic.types]. */
+
+bool
+std_layout_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_STD_LAYOUT (t);
+ else
+ return scalarish_type_p (t);
}
/* Nonzero iff type T is a class template implicit specialization. */
bool
-class_tmpl_impl_spec_p (tree t)
+class_tmpl_impl_spec_p (const_tree t)
{
return CLASS_TYPE_P (t) && CLASSTYPE_TEMPLATE_INSTANTIATION (t);
}
zeros in it. */
int
-zero_init_p (tree t)
+zero_init_p (const_tree t)
{
- t = strip_array_types (t);
+ /* This CONST_CAST is okay because strip_array_types returns its
+ argument unmodified and we assign it to a const_tree. */
+ t = strip_array_types (CONST_CAST_TREE(t));
if (t == error_mark_node)
return 1;
}
/* Build a variant of TYPE that has the indicated ATTRIBUTES. May
- return an existing type of an appropriate type already exists. */
+ return an existing type if an appropriate type already exists. */
tree
cp_build_type_attribute_variant (tree type, tree attributes)
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
- if (TREE_CODE (new_type) == FUNCTION_TYPE
+ if ((TREE_CODE (new_type) == FUNCTION_TYPE
+ || TREE_CODE (new_type) == METHOD_TYPE)
&& (TYPE_RAISES_EXCEPTIONS (new_type)
!= TYPE_RAISES_EXCEPTIONS (type)))
new_type = build_exception_variant (new_type,
return new_type;
}
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+ Called only after doing all language independent checks. Only
+ to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
+ compared in type_hash_eq. */
+
+bool
+cxx_type_hash_eq (const_tree typea, const_tree typeb)
+{
+ gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE);
+
+ return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
+ TYPE_RAISES_EXCEPTIONS (typeb), 1);
+}
+
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree. */
#define WALK_SUBTREE(NODE) \
do \
{ \
- result = walk_tree (&(NODE), func, data, pset); \
+ result = cp_walk_tree (&(NODE), func, data, pset); \
if (result) goto out; \
} \
while (0)
*walk_subtrees_p = 0;
break;
- case TINST_LEVEL:
- WALK_SUBTREE (TINST_DECL (*tp));
- *walk_subtrees_p = 0;
- break;
-
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
*walk_subtrees_p = 0;
*walk_subtrees_p = 0;
break;
+ case USING_DECL:
+ WALK_SUBTREE (DECL_NAME (*tp));
+ WALK_SUBTREE (USING_DECL_SCOPE (*tp));
+ WALK_SUBTREE (USING_DECL_DECLS (*tp));
+ *walk_subtrees_p = 0;
+ break;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (*tp))
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
break;
case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
if (TREE_TYPE (*tp))
WALK_SUBTREE (TREE_TYPE (*tp));
#undef WALK_SUBTREE
}
-/* Decide whether there are language-specific reasons to not inline a
- function as a tree. */
-
-int
-cp_cannot_inline_tree_fn (tree* fnp)
-{
- tree fn = *fnp;
-
- /* We can inline a template instantiation only if it's fully
- instantiated. */
- if (DECL_TEMPLATE_INFO (fn)
- && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
- {
- /* Don't instantiate functions that are not going to be
- inlined. */
- if (!DECL_INLINE (DECL_TEMPLATE_RESULT
- (template_for_substitution (fn))))
- return 1;
-
- fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
-
- if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
- return 1;
- }
-
- if (flag_really_no_inline
- && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
- return 1;
-
- /* Don't auto-inline functions that might be replaced at link-time
- with an alternative definition. */
- if (!DECL_DECLARED_INLINE_P (fn) && DECL_REPLACEABLE_P (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- if (varargs_function_p (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- if (! function_attribute_inlinable_p (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- return 0;
-}
-
-/* Determine whether VAR is a declaration of an automatic variable in
- function FN. */
-
-int
-cp_auto_var_in_fn_p (tree var, tree fn)
-{
- return (DECL_P (var) && DECL_CONTEXT (var) == fn
- && nonstatic_local_decl_p (var));
-}
-
/* Like save_expr, but for C++. */
tree
predicate to test whether or not DECL is a special function. */
special_function_kind
-special_function_p (tree decl)
+special_function_p (const_tree decl)
{
/* Rather than doing all this stuff with magic names, we should
probably have a field of type `special_function_kind' in
DECL_LANG_SPECIFIC. */
if (DECL_COPY_CONSTRUCTOR_P (decl))
return sfk_copy_constructor;
+ if (DECL_MOVE_CONSTRUCTOR_P (decl))
+ return sfk_move_constructor;
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
return (same_type_p (type, char_type_node)
|| same_type_p (type, unsigned_char_type_node)
|| same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char16_type_node)
+ || same_type_p (type, char32_type_node)
|| same_type_p (type, wchar_type_node));
}
if (!DECL_NAME (decl))
return lk_none;
+ /* Fields have no linkage. */
+ if (TREE_CODE (decl) == FIELD_DECL)
+ return lk_none;
+
/* Things that are TREE_PUBLIC have external linkage. */
if (TREE_PUBLIC (decl))
return lk_external;
template instantiations have internal linkage (in the object
file), but the symbols should still be treated as having external
linkage from the point of view of the language. */
- if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl)
+ if ((TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
&& DECL_COMDAT (decl))
return lk_external;
/* Members of the anonymous namespace also have TREE_PUBLIC unset, but
are considered to have external linkage for language purposes. DECLs
really meant to have internal linkage have DECL_THIS_STATIC set. */
- if (TREE_CODE (decl) == TYPE_DECL
- || ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
- && !DECL_THIS_STATIC (decl)))
+ if (TREE_CODE (decl) == TYPE_DECL)
return lk_external;
+ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (!DECL_THIS_STATIC (decl))
+ return lk_external;
+
+ /* Static data members and static member functions from classes
+ in anonymous namespace also don't have TREE_PUBLIC set. */
+ if (DECL_CLASS_CONTEXT (decl))
+ return lk_external;
+ }
/* Everything else has internal linkage. */
return lk_internal;
}
else
{
- exp = build_unary_op (ADDR_EXPR, exp, 1);
+ exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
- exp = build_indirect_ref (exp, 0);
+ exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error);
}
*initp = init_expr;
return exp;
}
-/* Add NEW, an expression whose value we don't care about, after the
+/* Add NEW_EXPR, an expression whose value we don't care about, after the
similar expression ORIG. */
tree
-add_stmt_to_compound (tree orig, tree new)
+add_stmt_to_compound (tree orig, tree new_expr)
{
- if (!new || !TREE_SIDE_EFFECTS (new))
+ if (!new_expr || !TREE_SIDE_EFFECTS (new_expr))
return orig;
if (!orig || !TREE_SIDE_EFFECTS (orig))
- return new;
- return build2 (COMPOUND_EXPR, void_type_node, orig, new);
+ return new_expr;
+ return build2 (COMPOUND_EXPR, void_type_node, orig, new_expr);
}
/* Like stabilize_expr, but for a call whose arguments we want to
int i;
int nargs = call_expr_nargs (call);
- if (call == error_mark_node)
- return;
+ if (call == error_mark_node || processing_template_decl)
+ {
+ *initp = NULL_TREE;
+ return;
+ }
gcc_assert (TREE_CODE (call) == CALL_EXPR);
*initp = NULL_TREE;
- if (t == error_mark_node)
+ if (t == error_mark_node || processing_template_decl)
return true;
if (TREE_CODE (t) == INIT_EXPR
- && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+ && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
{
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
return true;
|| type == error_mark_node);
}
+/* Return true if we need to fix linkage information of DECL. */
+
+static bool
+cp_fix_function_decl_p (tree decl)
+{
+ /* Skip if DECL is not externally visible. */
+ if (!TREE_PUBLIC (decl))
+ return false;
+
+ /* We need to fix DECL if it a appears to be exported but with no
+ function body. Thunks do not have CFGs and we may need to
+ handle them specially later. */
+ if (!gimple_has_body_p (decl)
+ && !DECL_THUNK_P (decl)
+ && !DECL_EXTERNAL (decl))
+ {
+ struct cgraph_node *node = cgraph_get_node (decl);
+
+ /* Don't fix same_body aliases. Although they don't have their own
+ CFG, they share it with what they alias to. */
+ if (!node
+ || node->decl == decl
+ || !node->same_body)
+ return true;
+ }
+
+ return false;
+}
+
+/* Clean the C++ specific parts of the tree T. */
+
+void
+cp_free_lang_data (tree t)
+{
+ if (TREE_CODE (t) == METHOD_TYPE
+ || TREE_CODE (t) == FUNCTION_TYPE)
+ {
+ /* Default args are not interesting anymore. */
+ tree argtypes = TYPE_ARG_TYPES (t);
+ while (argtypes)
+ {
+ TREE_PURPOSE (argtypes) = 0;
+ argtypes = TREE_CHAIN (argtypes);
+ }
+ }
+ else if (TREE_CODE (t) == FUNCTION_DECL
+ && cp_fix_function_decl_p (t))
+ {
+ /* If T is used in this translation unit at all, the definition
+ must exist somewhere else since we have decided to not emit it
+ in this TU. So make it an external reference. */
+ DECL_EXTERNAL (t) = 1;
+ TREE_STATIC (t) = 0;
+ }
+ if (CP_AGGREGATE_TYPE_P (t)
+ && TYPE_NAME (t))
+ {
+ tree name = TYPE_NAME (t);
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+ /* Drop anonymous names. */
+ if (name != NULL_TREE
+ && ANON_AGGRNAME_P (name))
+ TYPE_NAME (t) = NULL_TREE;
+ }
+}
+
\f
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree