+2010-03-25 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/43206
+ * cp-tree.h (get_template_parms_at_level): Declare ...
+ * pt.c (get_template_parms_at_level): ... new function.
+ * typeck.c (get_template_parms_of_dependent_type): If a template
+ type parm's DECL_CONTEXT isn't yet set, get its siblings from
+ current_template_parms. Use get_template_parms_at_level. Remove
+ useless test.
+ (incompatible_dependent_types_p): If we get empty parms from just one
+ of the template type parms we are comparing then the template parms are
+ incompatible.
+
2010-03-24 Jason Merrill <jason@redhat.com>
PR c++/43502
/* Definitions for C++ parsing and type checking.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "hashtab.h"
#include "splay-tree.h"
#include "vec.h"
+#include "varray.h"
#include "c-common.h"
#include "name-lookup.h"
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
+ TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
3: TYPE_FOR_JAVA.
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
+ SCOPED_ENUM_P (in ENUMERAL_TYPE)
6: TYPE_DEPENDENT_P_VALID
Usage of DECL_LANG_FLAG_?:
CPTI_KEYED_CLASSES,
- CPTI_NULLPTR,
- CPTI_NULLPTR_TYPE,
-
CPTI_MAX
};
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
-#define nullptr_node cp_global_trees[CPTI_NULLPTR]
-#define nullptr_type_node cp_global_trees[CPTI_NULLPTR_TYPE]
/* We cache these tree nodes so as to call get_identifier less
frequently. */
(TYPE_RAISES_EXCEPTIONS (NODE) \
&& TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE)
-/* For FUNCTION_TYPE or METHOD_TYPE, true if NODE is noexcept. This is the
- case for things declared noexcept(true) and, with -fnothrow-opt, for
- throw() functions. */
-#define TYPE_NOEXCEPT_P(NODE) \
- (flag_nothrow_opt && TYPE_NOTHROW_P(NODE))
-
/* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) \
(LANG_DECL_NS_CHECK (NODE)->level)
unsigned threadprivate_or_deleted_p : 1; /* var or fn */
unsigned anticipated_p : 1; /* fn or type */
unsigned friend_attr : 1; /* fn or type */
- unsigned template_conv_p : 1; /* var or template */
+ unsigned template_conv_p : 1; /* template only? */
unsigned odr_used : 1; /* var or fn */
unsigned u2sel : 1;
/* 1 spare bit */
#define DECL_TEMPLATE_CONV_FN_P(NODE) \
(DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE))->u.base.template_conv_p)
-/* Nonzero if NODE, a static data member, was declared in its class as an
- array of unknown bound. */
-#define VAR_HAD_UNKNOWN_BOUND(NODE) \
- (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
- ? DECL_LANG_SPECIFIC (NODE)->u.base.template_conv_p \
- : false)
-#define SET_VAR_HAD_UNKNOWN_BOUND(NODE) \
- (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.template_conv_p = true)
-
/* Set the overloaded operator code for NODE to CODE. */
#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
(LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
|| TREE_CODE (TYPE) == REAL_TYPE \
|| TREE_CODE (TYPE) == COMPLEX_TYPE)
-/* True iff TYPE is cv decltype(nullptr). */
-#define NULLPTR_TYPE_P(TYPE) \
- (TREE_CODE (TYPE) == LANG_TYPE \
- && TYPE_MAIN_VARIANT (TYPE) == nullptr_type_node)
-
/* [basic.types]
- Arithmetic types, enumeration types, pointer types,
- pointer-to-member types, and std::nullptr_t are collectively called
- scalar types.
+ Arithmetic types, enumeration types, pointer types, and
+ pointer-to-member types, are collectively called scalar types.
Keep these checks in ascending code order. */
#define SCALAR_TYPE_P(TYPE) \
|| TREE_CODE (TYPE) == ENUMERAL_TYPE \
|| ARITHMETIC_TYPE_P (TYPE) \
|| TYPE_PTR_P (TYPE) \
- || TYPE_PTRMEMFUNC_P (TYPE) \
- || NULLPTR_TYPE_P (TYPE))
+ || TYPE_PTRMEMFUNC_P (TYPE))
/* Determines whether this type is a C++0x scoped enumeration
type. Scoped enumerations types are introduced via "enum class" or
- The underlying type of the enum is well-defined. */
#define SCOPED_ENUM_P(TYPE) \
- (TREE_CODE (TYPE) == ENUMERAL_TYPE && ENUM_IS_SCOPED (TYPE))
+ (TREE_CODE (TYPE) == ENUMERAL_TYPE && TYPE_LANG_FLAG_5 (TYPE))
/* Determine whether this is an unscoped enumeration type. */
#define UNSCOPED_ENUM_P(TYPE) \
- (TREE_CODE (TYPE) == ENUMERAL_TYPE && !ENUM_IS_SCOPED (TYPE))
+ (TREE_CODE (TYPE) == ENUMERAL_TYPE && !TYPE_LANG_FLAG_5 (TYPE))
/* Set the flag indicating whether an ENUMERAL_TYPE is a C++0x scoped
enumeration type (1) or a normal (unscoped) enumeration type
(0). */
#define SET_SCOPED_ENUM_P(TYPE, VAL) \
- (ENUM_IS_SCOPED (TYPE) = (VAL))
+ (TYPE_LANG_FLAG_5 (ENUMERAL_TYPE_CHECK (TYPE)) = (VAL))
/* Returns the underlying type of the given enumeration type. The
underlying type is determined in different ways, depending on the
#define TYPE_REF_OBJ_P(NODE) \
(TREE_CODE (NODE) == REFERENCE_TYPE && TYPE_OBJ_P (TREE_TYPE (NODE)))
+/* True if reference type NODE is an rvalue reference */
+#define TYPE_REF_IS_RVALUE(NODE) \
+ TREE_LANG_FLAG_0 (REFERENCE_TYPE_CHECK (NODE))
+
/* Returns true if NODE is a pointer to an object, or a pointer to
void. Keep these checks in ascending tree code order. */
#define TYPE_PTROBV_P(NODE) \
#define ANON_UNION_TYPE_P(NODE) \
(TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE))
+#define UNKNOWN_TYPE LANG_TYPE
+
/* Define fields and accessors for nodes representing declared names. */
#define TYPE_WAS_ANONYMOUS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->was_anonymous)
have already generated a temporary, such as reference
initialization and the catch parameter. */
#define DIRECT_BIND (1 << 4)
-/* We're performing a user-defined conversion, so more user-defined
- conversions are not permitted (only built-in conversions). */
+/* User-defined conversions are not permitted. (Built-in conversions
+ are permitted.) */
#define LOOKUP_NO_CONVERSION (1 << 5)
/* The user has explicitly called a destructor. (Therefore, we do
not need to check that the object is non-NULL before calling the
#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1)
/* This is the first parameter of a copy constructor. */
#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
-/* We only want to consider list constructors. */
-#define LOOKUP_LIST_ONLY (LOOKUP_COPY_PARM << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
(TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
- TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
- (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
/* These constants can used as bit flags in the process of tree formatting.
extern tree build_vfield_ref (tree, tree);
extern tree build_base_path (enum tree_code, tree,
tree, int);
-extern tree convert_to_base (tree, tree, bool, bool,
- tsubst_flags_t);
+extern tree convert_to_base (tree, tree, bool, bool);
extern tree convert_to_base_statically (tree, tree);
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern bool add_method (tree, tree, tree);
extern bool currently_open_class (tree);
extern tree currently_open_derived_class (tree);
-extern tree current_nonlambda_class_type (void);
extern tree finish_struct (tree, tree);
extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *);
extern void push_class_stack (void);
extern void pop_class_stack (void);
extern bool type_has_user_nondefault_constructor (tree);
-extern tree in_class_defaulted_default_constructor (tree);
extern bool user_provided_p (tree);
extern bool type_has_user_provided_constructor (tree);
extern bool type_has_user_provided_default_constructor (tree);
extern tree check_for_out_of_scope_variable (tree);
extern void print_other_binding_stack (struct cp_binding_level *);
extern tree maybe_push_decl (tree);
-extern tree current_decl_namespace (void);
/* decl.c */
extern tree poplevel (int, int, int);
extern void initialize_artificial_var (tree, tree);
extern tree check_var_type (tree, tree);
extern tree reshape_init (tree, tree);
-extern tree next_initializable_field (tree);
extern bool defer_mark_used_calls;
extern GTY(()) VEC(tree, gc) *deferred_mark_used_calls;
/* in expr.c */
extern tree cplus_expand_constant (tree);
-extern tree mark_rvalue_use (tree);
-extern tree mark_lvalue_use (tree);
-extern tree mark_type_use (tree);
-extern void mark_exp_read (tree);
/* friend.c */
extern int is_friend (tree, tree);
extern void initialize_vtbl_ptrs (tree);
extern tree build_java_class_ref (tree);
extern tree integral_constant_value (tree);
-extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool);
/* in lex.c */
extern void cxx_dup_lang_specific_decl (tree);
extern struct tinst_level *outermost_tinst_level(void);
extern bool parameter_of_template_p (tree, tree);
extern void init_template_processing (void);
-extern void print_template_statistics (void);
bool template_template_parameter_p (const_tree);
extern bool primary_template_instantiation_p (const_tree);
extern tree get_primary_template_innermost_parameters (const_tree);
-extern tree get_template_parms_at_level (tree, int);
+extern tree get_template_parms_at_level (tree, unsigned);
extern tree get_template_innermost_arguments (const_tree);
extern tree get_template_argument_pack_elems (const_tree);
extern tree get_function_template_decl (const_tree);
extern tree add_default_capture (tree, tree, tree);
extern void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree);
-extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree);
/* in tree.c */
extern tree hash_tree_chain (tree, tree);
extern tree build_qualified_name (tree, tree, tree, bool);
extern int is_overloaded_fn (tree);
-extern tree get_fns (tree);
extern tree get_first_fn (tree);
extern tree ovl_cons (tree, tree);
extern tree build_overload (tree, tree);
extern tree cp_build_indirect_ref (tree, ref_operator,
tsubst_flags_t);
extern tree build_array_ref (location_t, tree, tree);
-extern tree cp_build_array_ref (location_t, tree, tree,
- tsubst_flags_t);
extern tree get_member_function_from_ptrfunc (tree *, tree);
extern tree cp_build_function_call (tree, tree, tsubst_flags_t);
extern tree cp_build_function_call_vec (tree, VEC(tree,gc) **,
extern int ptr_reasonably_similar (const_tree, const_tree);
extern tree build_ptrmemfunc (tree, tree, int, bool);
extern int cp_type_quals (const_tree);
-extern int type_memfn_quals (const_tree);
-extern tree apply_memfn_quals (tree, cp_cv_quals);
+extern bool cp_type_readonly (const_tree);
extern bool cp_has_mutable_p (const_tree);
extern bool at_least_as_qualified_p (const_tree, const_tree);
extern void cp_apply_type_quals_to_decl (int, tree);
composite_pointer_operation,
tsubst_flags_t);
extern tree merge_types (tree, tree);
-extern tree strip_array_domain (tree);
extern tree check_return_expr (tree, bool *);
extern tree cp_build_binary_op (location_t,
enum tree_code, tree, tree,
/* Handle parameterized types (templates) for GNU C++.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
int i;
int j;
- if (args == NULL_TREE)
- return extra_args;
-
extra_depth = TMPL_ARGS_DEPTH (extra_args);
new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
val = iterative_hash_template_arg (TREE_TYPE (arg), val);
return iterative_hash_template_arg (TYPE_DOMAIN (arg), val);
- case LAMBDA_EXPR:
- /* A lambda can't appear in a template arg, but don't crash on
- erroneous input. */
- gcc_assert (errorcount > 0);
- return val;
-
default:
switch (tclass)
{
of template parameters PARMS. */
tree
-get_template_parms_at_level (tree parms, int level)
+get_template_parms_at_level (tree parms, unsigned level)
{
tree p;
if (!parms
next = TREE_CHAIN (parm);
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
TREE_CHAIN (parm) = NULL_TREE;
- if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
- TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
- current_template_parms;
}
--processing_template_parmlist;
TYPENAME_TYPEs and SCOPE_REFs that were previously dependent. */
tree args = current_template_args ();
tree auto_node = type_uses_auto (type);
- tree pushed;
if (auto_node)
{
tree auto_vec = make_tree_vec (1);
TREE_VEC_ELT (auto_vec, 0) = auto_node;
args = add_to_template_args (args, auto_vec);
}
- pushed = push_scope (scope);
+ push_scope (scope);
type = tsubst (type, args, tf_warning_or_error, NULL_TREE);
- if (pushed)
- pop_scope (scope);
+ pop_scope (scope);
}
if (type == error_mark_node)
int nargs = TREE_VEC_LENGTH (inner_args);
int ntparms;
int i;
- bool did_error_intro = false;
+ int did_error_intro = 0;
struct template_parm_data tpd;
struct template_parm_data tpd2;
if (!did_error_intro)
{
error ("template parameters not used in partial specialization:");
- did_error_intro = true;
+ did_error_intro = 1;
}
error (" %qD", TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
}
- if (did_error_intro)
- return error_mark_node;
-
/* [temp.class.spec]
The argument list of the specialization shall not be identical to
if (current == decl)
current = ctx;
- else if (current == NULL_TREE)
- /* Can happen in erroneous input. */
- break;
else
current = (TYPE_P (current)
? TYPE_CONTEXT (current)
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
if (TREE_CODE (parm) == TEMPLATE_DECL)
DECL_CONTEXT (parm) = tmpl;
+
+ if (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM)
+ DECL_CONTEXT (TYPE_NAME (TREE_TYPE (parm))) = tmpl;
}
}
if (error_operand_p (expr))
return error_mark_node;
expr_type = TREE_TYPE (expr);
- expr = mark_rvalue_use (expr);
/* HACK: Due to double coercion, we can get a
NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
if (TREE_CODE (old_decl) != TEMPLATE_DECL)
- {
- /* We should have called reregister_specialization in
- duplicate_decls. */
- gcc_assert (retrieve_specialization (new_template,
- new_args, 0)
- == old_decl);
-
- /* Instantiate it if the global has already been used. */
- if (DECL_ODR_USED (old_decl))
- instantiate_decl (old_decl, /*defer_ok=*/true,
- /*expl_inst_class_mem_p=*/false);
- }
+ /* We should have called reregister_specialization in
+ duplicate_decls. */
+ gcc_assert (retrieve_specialization (new_template,
+ new_args, 0)
+ == old_decl);
else
{
tree t;
{
r = lookup_template_class (t, argvec, in_decl, context,
entering_scope, complain);
- r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
+ r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
}
cp_unevaluated_operand = saved_unevaluated_operand;
specialize R. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
argvec = tsubst_template_args (DECL_TI_ARGS
- (DECL_TEMPLATE_RESULT
- (DECL_TI_TEMPLATE (t))),
+ (DECL_TEMPLATE_RESULT (gen_tmpl)),
args, complain, in_decl);
/* Check to see if we already have this specialization. */
type = DECL_ORIGINAL_TYPE (t);
else
type = TREE_TYPE (t);
- if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
- type = strip_array_domain (type);
type = tsubst (type, args, complain, in_decl);
}
if (TREE_CODE (r) == VAR_DECL)
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
- {
- fntype = build_function_type (return_type, arg_types);
- fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
- }
+ fntype = build_function_type (return_type, arg_types);
else
{
tree r = TREE_TYPE (TREE_VALUE (arg_types));
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
+ fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
int quals;
gcc_assert (TYPE_P (arg));
- quals = cp_type_quals (arg) | cp_type_quals (t);
+ /* cv-quals from the template are discarded when
+ substituting in a function or reference type. */
+ if (TREE_CODE (arg) == FUNCTION_TYPE
+ || TREE_CODE (arg) == METHOD_TYPE
+ || TREE_CODE (arg) == REFERENCE_TYPE)
+ quals = cp_type_quals (arg);
+ else
+ quals = cp_type_quals (arg) | cp_type_quals (t);
return cp_build_qualified_type_real
(arg, quals, complain | tf_ignore_bad_quals);
/*entering_scope=*/0,
complain);
return cp_build_qualified_type_real
- (r, cp_type_quals (t), complain);
+ (r, TYPE_QUALS (t), complain);
}
else
/* TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX. */
- return unshare_expr (arg);
+ return arg;
}
if (level == 1)
TYPE_REF_IS_RVALUE (t) && TYPE_REF_IS_RVALUE (type));
else
r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
- r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
+ r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
if (r != error_mark_node)
/* Will this ever be needed for TYPE_..._TO values? */
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree memptr;
- tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
+ tree method_type = build_memfn_type (type, r, cp_type_quals (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);
}
else
return cp_build_qualified_type_real (build_ptrmem_type (r, type),
- cp_type_quals (t),
+ TYPE_QUALS (t),
complain);
}
case FUNCTION_TYPE:
{
/* Although a CVR qualifier is ignored when being applied to a
substituted template parameter ([8.3.2]/1 for example), that
- does not allow us to unify "const T" with "int&" because both
- types are not of the form "cv-list T" [14.8.2.5 temp.deduct.type].
- It is ok when we're allowing additional CV qualifiers
+ does not apply during deduction [14.8.2.4]/1, (even though
+ that is not explicitly mentioned, [14.8.2.4]/9 indicates
+ this). Except when we're allowing additional CV qualifiers
at the outer level [14.8.2.1]/3,1st bullet. */
if ((TREE_CODE (arg) == REFERENCE_TYPE
|| TREE_CODE (arg) == FUNCTION_TYPE
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
{
int elt_strict = strict;
-
- if (elt == error_mark_node)
- return 1;
-
if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
{
tree type = TREE_TYPE (elt);
{
tree method_type;
tree fntype;
+ cp_cv_quals cv_quals;
/* Check top-level cv qualifiers */
if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
/* Extract the cv-qualifiers of the member function from the
implicit object parameter and place them on the function
type to be restored later. */
- fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
+ cv_quals =
+ cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
+ fntype = build_qualified_type (fntype, cv_quals);
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
}
/* Matched cases are handled by the ARG == PARM test above. */
return 1;
- case VAR_DECL:
- /* A non-type template parameter that is a variable should be a
- an integral constant, in which case, it whould have been
- folded into its (constant) value. So we should not be getting
- a variable here. */
- gcc_unreachable ();
-
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
than the type from the parameter template (as described above)
that type is considered to be more specialized than the other. If
neither type is more cv-qualified than the other then neither type
- is more specialized than the other." */
+ is more specialized than the other."
+ We check same_type_p explicitly because deduction can also succeed
+ in both directions when there is a nondeduced context. */
if (deduce1 && deduce2
- && quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
+ && quals1 != quals2 && quals1 >= 0 && quals2 >= 0
+ && same_type_p (arg1, arg2))
{
if ((quals1 & quals2) == quals2)
lose2 = true;
tree parms = TREE_VALUE (t);
partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
-
- ++processing_template_decl;
-
if (outer_args)
{
int i;
+ ++processing_template_decl;
+
/* Discard the outer levels of args, and then substitute in the
template args from the enclosing class. */
partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
TREE_VEC_ELT (parms, i) =
tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
+ --processing_template_decl;
}
-
- partial_spec_args =
- coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- add_to_template_args (outer_args,
- partial_spec_args),
- tmpl, tf_none,
- /*require_all_args=*/true,
- /*use_default_args=*/true);
-
- --processing_template_decl;
-
- if (partial_spec_args == error_mark_node)
- return error_mark_node;
-
spec_args = get_class_bindings (parms,
partial_spec_args,
args);
DECL_DECLARED_INLINE_P (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
- {
- DECL_INITIAL (decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl),
- /*integral_constant_expression_p=*/false);
- if (VAR_HAD_UNKNOWN_BOUND (decl))
- TREE_TYPE (decl) = tsubst (TREE_TYPE (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl));
- }
+ DECL_INITIAL (decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl),
+ /*integral_constant_expression_p=*/false);
else
gcc_unreachable ();
return false;
}
- /* A static data member of the current instantiation with incomplete
- array type is type-dependent, as the definition and specializations
- can have different bounds. */
- if (TREE_CODE (expression) == VAR_DECL
- && DECL_CLASS_SCOPE_P (expression)
- && dependent_type_p (DECL_CONTEXT (expression))
- && VAR_HAD_UNKNOWN_BOUND (expression))
- return true;
-
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
ggc_free);
}
-/* Print stats about the template hash tables for -fstats. */
-
-void
-print_template_statistics (void)
-{
- fprintf (stderr, "decl_specializations: size %ld, %ld elements, "
- "%f collisions\n", (long) htab_size (decl_specializations),
- (long) htab_elements (decl_specializations),
- htab_collisions (decl_specializations));
- fprintf (stderr, "type_specializations: size %ld, %ld elements, "
- "%f collisions\n", (long) htab_size (type_specializations),
- (long) htab_elements (type_specializations),
- htab_collisions (type_specializations));
-}
-
#include "gt-cp-pt.h"
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
-static void warn_args_num (location_t, tree, bool);
static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
tsubst_flags_t);
if (DERIVED_FROM_P (class1, class2))
t2 = (build_pointer_type
- (cp_build_qualified_type (class1, cp_type_quals (class2))));
+ (cp_build_qualified_type (class1, TYPE_QUALS (class2))));
else if (DERIVED_FROM_P (class2, class1))
t1 = (build_pointer_type
- (cp_build_qualified_type (class2, cp_type_quals (class1))));
+ (cp_build_qualified_type (class2, TYPE_QUALS (class1))));
else
{
if (complain & tf_error)
tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2));
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
- tree parms;
tree rval, raises;
/* Save space: see if the result is identical to one of the args. */
/* Simple way if one arg fails to specify argument types. */
if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
{
- parms = p2;
- raises = TYPE_RAISES_EXCEPTIONS (t2);
+ rval = build_function_type (valtype, p2);
+ if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
+ rval = build_exception_variant (rval, raises);
+ return cp_build_type_attribute_variant (rval, attributes);
}
- else if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
+ raises = TYPE_RAISES_EXCEPTIONS (t1);
+ if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
{
- parms = p1;
- raises = TYPE_RAISES_EXCEPTIONS (t1);
- }
- else
- {
- parms = commonparms (p1, p2);
- /* In cases where we're merging a real declaration with a
- built-in declaration, t1 is the real one. */
- raises = TYPE_RAISES_EXCEPTIONS (t1);
+ rval = build_function_type (valtype, p1);
+ if (raises)
+ rval = build_exception_variant (rval, raises);
+ return cp_build_type_attribute_variant (rval, attributes);
}
- rval = build_function_type (valtype, parms);
- gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
- rval = apply_memfn_quals (rval, type_memfn_quals (t1));
+ rval = build_function_type (valtype, commonparms (p1, p2));
t1 = build_exception_variant (rval, raises);
break;
}
return cp_build_type_attribute_variant (t1, attributes);
}
-/* Return the ARRAY_TYPE type without its domain. */
-
-tree
-strip_array_domain (tree type)
-{
- tree t2;
- gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
- if (TYPE_DOMAIN (type) == NULL_TREE)
- return type;
- t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
- return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type));
-}
-
/* Wrapper around cp_common_type that is used by c-common.c and other
front end optimizations that remove promotions.
template info from T itself. */
if ((tinfo = get_template_info (t)))
;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
+ /* If T1 is a typedef or whatever has a template info associated
+ to its context, get the template parameters from that context. */
else if (typedef_variant_p (t)
&& !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
- /* If T is a TYPENAME_TYPE which context is a template type
- parameter, get the template parameters from that context. */
- else if (TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && DECL_CONTEXT (TYPE_NAME (t)) == NULL_TREE)
+ /* We have not yet created the DECL_TEMPLATE this
+ template type parm belongs to. It probably means
+ that we are in the middle of parsing the template parameters
+ of a template, and T is one of the parameters we have parsed.
+ Let's return the list of template parms we have parsed so far. */
+ return get_template_parms_at_level (current_template_parms,
+ TEMPLATE_TYPE_LEVEL (t));
else if (TYPE_CONTEXT (t)
&& !NAMESPACE_SCOPE_P (t))
tinfo = get_template_info (TYPE_CONTEXT (t));
if (tinfo)
tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
+ /* If T is a template type parameter, get the template parameter
+ set it is part of. */
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && DECL_CONTEXT (TYPE_NAME (t)))
+ tparms = DECL_TEMPLATE_PARMS (DECL_CONTEXT (TYPE_NAME (t)));
+ /* If T is a TYPENAME_TYPE which context is a template type
+ parameter, get the template parameters from that context. */
+ else if (TYPE_CONTEXT (t)
+ && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
+ tparms = get_template_parms_of_dependent_type (TYPE_CONTEXT (t));
return tparms;
}
incompatible_dependent_types_p (tree t1, tree t2)
{
tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
- bool t1_typedef_variant_p, t2_typedef_variant_p;
if (!uses_template_parms (t1) || !uses_template_parms (t2))
return false;
return true;
}
- t1_typedef_variant_p = typedef_variant_p (t1);
- t2_typedef_variant_p = typedef_variant_p (t2);
-
/* Either T1 or T2 must be a typedef. */
- if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+ if (!typedef_variant_p (t1) && !typedef_variant_p (t2))
return false;
- if (!t1_typedef_variant_p || !t2_typedef_variant_p)
- /* Either T1 or T2 is not a typedef so we cannot compare the
- the template parms of the typedefs of T1 and T2.
- At this point, if the main variant type of T1 and T2 are equal
- it means the two types can't be incompatible, from the perspective
- of this function. */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return false;
-
/* So if we reach this point, it means either T1 or T2 is a typedef variant.
Let's compare their template parameters. */
/* Qualifiers must match. For array types, we will check when we
recur on the array element types. */
if (TREE_CODE (t1) != ARRAY_TYPE
- && cp_type_quals (t1) != cp_type_quals (t2))
- return false;
- if (TREE_CODE (t1) == FUNCTION_TYPE
- && type_memfn_quals (t1) != type_memfn_quals (t2))
+ && TYPE_QUALS (t1) != TYPE_QUALS (t2))
return false;
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
- /* If T1 and T2 are dependent typedefs then check upfront that
- the template parameters of their typedef DECLs match before
- going down checking their subtypes. */
- if (incompatible_dependent_types_p (t1, t2))
- return false;
-
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
+ /* If T1 and T2 are dependent typedefs then check upfront that
+ the template parameters of their typedef DECLs match before
+ going down checking their subtypes. */
+ if (incompatible_dependent_types_p (t1, t2))
+ return false;
/* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1))
return e;
}
- /* To get the size of a static data member declared as an array of
- unknown bound, we need to instantiate it. */
- if (TREE_CODE (e) == VAR_DECL
- && VAR_HAD_UNKNOWN_BOUND (e)
- && DECL_TEMPLATE_INSTANTIATION (e))
- instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
-
- e = mark_type_use (e);
-
if (TREE_CODE (e) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
return e;
}
- e = mark_type_use (e);
-
if (TREE_CODE (e) == VAR_DECL)
t = size_int (DECL_ALIGN_UNIT (e));
else if (TREE_CODE (e) == COMPONENT_REF
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions. In addition, manifest constants
are replaced by their values, and bitfield references are converted
- to their declared types. Note that this function does not perform the
- lvalue-to-rvalue conversion for class types. If you need that conversion
- to for class types, then you probably need to use force_rvalue.
+ to their declared types.
Although the returned value is being used as an rvalue, this
function does not wrap the returned expression in a
if (type == error_mark_node)
return error_mark_node;
- exp = mark_rvalue_use (exp);
-
exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp))
{
tree type;
tree promoted_type;
- expr = mark_rvalue_use (expr);
-
/* [conv.prom]
If the bitfield has an enumerated type, it is treated as any
else
{
/* Is this a string constant which has decayed to 'const char *'? */
- t = build_pointer_type (cp_build_qualified_type (t, TYPE_QUAL_CONST));
+ t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
if (!same_type_p (TREE_TYPE (exp), t))
return 0;
STRIP_NOPS (exp);
LOC is the location to use in building the array reference. */
tree
-cp_build_array_ref (location_t loc, tree array, tree idx,
- tsubst_flags_t complain)
+build_array_ref (location_t loc, tree array, tree idx)
{
tree ret;
if (idx == 0)
{
- if (complain & tf_error)
- error_at (loc, "subscript missing in array reference");
+ error_at (loc, "subscript missing in array reference");
return error_mark_node;
}
{
case COMPOUND_EXPR:
{
- tree value = cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
- complain);
+ tree value = build_array_ref (loc, TREE_OPERAND (array, 1), idx);
ret = build2 (COMPOUND_EXPR, TREE_TYPE (value),
TREE_OPERAND (array, 0), value);
SET_EXPR_LOCATION (ret, loc);
case COND_EXPR:
ret = build_conditional_expr
(TREE_OPERAND (array, 0),
- cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
- complain),
- cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx,
- complain),
+ build_array_ref (loc, TREE_OPERAND (array, 1), idx),
+ build_array_ref (loc, TREE_OPERAND (array, 2), idx),
tf_warning_or_error);
protected_set_expr_location (ret, loc);
return ret;
if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (idx)))
{
- if (complain & tf_error)
- error_at (loc, "array subscript is not an integer");
+ error_at (loc, "array subscript is not an integer");
return error_mark_node;
}
return error_mark_node;
}
- if (!lvalue_p (array) && (complain & tf_error))
+ if (!lvalue_p (array))
pedwarn (loc, OPT_pedantic,
"ISO C++ forbids subscripting non-lvalue array");
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
- if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)
- && (complain & tf_warning))
+ if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
warning_at (loc, OPT_Wextra,
"subscripting array declared %<register%>");
}
if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
{
- if (complain & tf_error)
- error_at (loc, "subscripted value is neither array nor pointer");
+ error_at (loc, "subscripted value is neither array nor pointer");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
{
- if (complain & tf_error)
- error_at (loc, "array subscript is not an integer");
+ error_at (loc, "array subscript is not an integer");
return error_mark_node;
}
ret = cp_build_indirect_ref (cp_build_binary_op (input_location,
PLUS_EXPR, ar, ind,
- complain),
+ tf_warning_or_error),
RO_ARRAY_INDEXING,
- complain);
+ tf_warning_or_error);
protected_set_expr_location (ret, loc);
return ret;
}
}
-
-/* Entry point for Obj-C++. */
-
-tree
-build_array_ref (location_t loc, tree array, tree idx)
-{
- return cp_build_array_ref (loc, array, idx, tf_warning_or_error);
-}
\f
/* Resolve a pointer to member function. INSTANCE is the object
instance to use, if the member points to a virtual member.
return ret;
}
\f
-/* Subroutine of convert_arguments.
- Warn about wrong number of args are genereted. */
-
-static void
-warn_args_num (location_t loc, tree fndecl, bool too_many_p)
-{
- if (fndecl)
- {
- if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
- {
- if (DECL_NAME (fndecl) == NULL_TREE
- || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
- error_at (loc,
- too_many_p
- ? G_("too many arguments to constructor %q#D")
- : G_("too few arguments to constructor %q#D"),
- fndecl);
- else
- error_at (loc,
- too_many_p
- ? G_("too many arguments to member function %q#D")
- : G_("too few arguments to member function %q#D"),
- fndecl);
- }
- else
- error_at (loc,
- too_many_p
- ? G_("too many arguments to function %q#D")
- : G_("too few arguments to function %q#D"),
- fndecl);
- inform (DECL_SOURCE_LOCATION (fndecl),
- "declared here");
- }
- else
- error_at (loc, too_many_p ? G_("too many arguments to function")
- : G_("too few arguments to function"));
-}
-
/* Convert the actual parameter expressions in the list VALUES to the
types in the list TYPELIST. The converted expressions are stored
back in the VALUES vector.
int flags, tsubst_flags_t complain)
{
tree typetail;
+ const char *called_thing = 0;
unsigned int i;
/* Argument passing is always copy-initialization. */
flags |= LOOKUP_ONLYCONVERTING;
+ if (fndecl)
+ {
+ if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
+ {
+ if (DECL_NAME (fndecl) == NULL_TREE
+ || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
+ called_thing = "constructor";
+ else
+ called_thing = "member function";
+ }
+ else
+ called_thing = "function";
+ }
+
for (i = 0, typetail = typelist;
i < VEC_length (tree, *values);
i++)
{
if (complain & tf_error)
{
- warn_args_num (input_location, fndecl, /*too_many_p=*/true);
+ if (fndecl)
+ {
+ error_at (input_location, "too many arguments to %s %q#D",
+ called_thing, fndecl);
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "declared here");
+ }
+ else
+ error ("too many arguments to function");
return i;
}
else
else
{
if (complain & tf_error)
- warn_args_num (input_location, fndecl, /*too_many_p=*/false);
+ {
+ if (fndecl)
+ {
+ error_at (input_location, "too few arguments to %s %q#D",
+ called_thing, fndecl);
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "declared here");
+ }
+ else
+ error ("too few arguments to function");
+ }
return -1;
}
}
}
result_type = type1;
}
- else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
- /* One of the operands must be of nullptr_t type. */
- result_type = TREE_TYPE (nullptr_node);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
}
build_type = boolean_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == ENUMERAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == ENUMERAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
- else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
+ else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
+ && integer_zerop (op1))
result_type = type0;
- else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
+ else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
+ && integer_zerop (op0))
result_type = type1;
- else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
- /* One of the operands must be of nullptr_t type. */
- result_type = TREE_TYPE (nullptr_node);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (val != 0)
return val;
- arg = mark_lvalue_use (arg);
-
/* Increment or decrement the real part of the value,
and don't change the imaginary part. */
if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
argtype = lvalue_type (arg);
- arg = mark_lvalue_use (arg);
-
if (TREE_CODE (arg) == OFFSET_REF)
goto offset_ref;
/* [expr.reinterpret.cast]
A pointer can be converted to any integral type large enough to
- hold it. ... A value of type std::nullptr_t can be converted to
- an integral type; the conversion has the same meaning and
- validity as a conversion of (void*)0 to the integral type. */
- if (CP_INTEGRAL_TYPE_P (type)
- && (TYPE_PTR_P (intype) || NULLPTR_TYPE_P (intype)))
+ hold it. */
+ if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype))
{
if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
{
else
return error_mark_node;
}
- if (NULLPTR_TYPE_P (intype))
- return build_int_cst (type, 0);
}
/* [expr.reinterpret.cast]
A value of integral or enumeration type can be explicitly
return error_mark_node;
}
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- /* Casting to an integer of smaller size is an error detected elsewhere. */
- && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value))
- /* Don't warn about converting any constant. */
- && !TREE_CONSTANT (value))
- warning_at (input_location, OPT_Wint_to_pointer_cast,
- "cast to pointer from integer of different size");
-
/* A C-style cast can be a const_cast. */
result = build_const_cast_1 (type, value, /*complain=*/false,
&valid_p);
if (BRACE_ENCLOSED_INITIALIZER_P (newrhs))
{
- if (modifycode != INIT_EXPR)
- {
- if (complain & tf_error)
- error ("assigning to an array from an initializer list");
- return error_mark_node;
- }
if (check_array_initializer (lhs, lhstype, newrhs))
return error_mark_node;
newrhs = digest_init (lhstype, newrhs);
if ((cxx_dialect != cxx98)
&& named_return_value_okay_p
/* The variable must not have the `volatile' qualifier. */
- && !CP_TYPE_VOLATILE_P (TREE_TYPE (retval))
+ && !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)
/* The return type must be a class type. */
&& CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
flags = flags | LOOKUP_PREFER_RVALUE;
int
cp_type_quals (const_tree type)
{
- int quals;
/* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */
- type = strip_array_types (CONST_CAST_TREE (type));
- if (type == error_mark_node
- /* Quals on a FUNCTION_TYPE are memfn quals. */
- || TREE_CODE (type) == FUNCTION_TYPE)
+ type = strip_array_types (CONST_CAST_TREE(type));
+ if (type == error_mark_node)
return TYPE_UNQUALIFIED;
- quals = TYPE_QUALS (type);
- /* METHOD and REFERENCE_TYPEs should never have quals. */
- gcc_assert ((TREE_CODE (type) != METHOD_TYPE
- && TREE_CODE (type) != REFERENCE_TYPE)
- || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
- == TYPE_UNQUALIFIED));
- return quals;
-}
-
-/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
- METHOD_TYPE. */
-
-int
-type_memfn_quals (const_tree type)
-{
- if (TREE_CODE (type) == FUNCTION_TYPE)
- return TYPE_QUALS (type);
- else if (TREE_CODE (type) == METHOD_TYPE)
- return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))));
- else
- gcc_unreachable ();
+ return TYPE_QUALS (type);
}
-/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
- MEMFN_QUALS. */
+/* Returns nonzero if the TYPE is const from a C++ perspective: look inside
+ arrays. */
-tree
-apply_memfn_quals (tree type, cp_cv_quals memfn_quals)
+bool
+cp_type_readonly (const_tree type)
{
- /* Could handle METHOD_TYPE here if necessary. */
- gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
- if (TYPE_QUALS (type) == memfn_quals)
- return type;
- /* This should really have a different TYPE_MAIN_VARIANT, but that gets
- complex. */
- return build_qualified_type (type, memfn_quals);
+ /* This CONST_CAST is okay because strip_array_types returns its
+ argument unmodified and we assign it to a const_tree. */
+ type = strip_array_types (CONST_CAST_TREE(type));
+ return TYPE_READONLY (type);
}
/* Returns nonzero if TYPE is const or volatile. */
if (TREE_CODE (decl) == TYPE_DECL)
return;
- gcc_assert (!(TREE_CODE (type) == FUNCTION_TYPE
- && type_quals != TYPE_UNQUALIFIED));
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals != TYPE_UNQUALIFIED)
+ {
+ /* This was an error in C++98 (cv-qualifiers cannot be added to
+ a function type), but DR 295 makes the code well-formed by
+ dropping the extra qualifiers. */
+ if (pedantic)
+ {
+ tree bad_type = build_qualified_type (type, type_quals);
+ pedwarn (input_location, OPT_pedantic,
+ "ignoring %qV qualifiers added to function type %qT",
+ bad_type, type);
+ }
+
+ TREE_TYPE (decl) = TYPE_MAIN_VARIANT (type);
+ return;
+ }
/* Avoid setting TREE_READONLY incorrectly. */
if (/* If the object has a constructor, the constructor may modify
return win;
}
-
+2010-03-25 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/43206
+ * g++.dg/template/typedef30.C: New test case.
+
2010-03-25 Jakub Jelinek <jakub@redhat.com>
PR c/43385