summaryrefslogtreecommitdiff
path: root/gnu/egcs
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-08-21 08:13:22 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-08-21 08:13:22 +0000
commitd45ae142eb4acaded9661e392962856d13bfcb9f (patch)
tree7dd1517d435f86488fb98b52d5eef8c7ff1344fa /gnu/egcs
parent811d424752966de59d020c2eabcb4ea7460cb9d6 (diff)
A port of the g++ bugfix found at
http://gcc.gnu.org/ml/gcc-bugs/1999-08n/msg00621.html and described in the related thread. This particular problem used to not be triggered (or not often), but the use of propolice affects the instruction flow, and started triggering it more often, for example in Qt's qmenubar class. Ironically, running with /etc/malloc.conf->AJ would neuter the bug in this case... Problem tracked by espie@ and etoh@, tested by various, ok deraadt@
Diffstat (limited to 'gnu/egcs')
-rw-r--r--gnu/egcs/gcc/cp/cp-tree.h12
-rw-r--r--gnu/egcs/gcc/cp/decl.c10
-rw-r--r--gnu/egcs/gcc/cp/decl2.c6
-rw-r--r--gnu/egcs/gcc/cp/lex.c31
-rw-r--r--gnu/egcs/gcc/cp/pt.c124
-rw-r--r--gnu/egcs/gcc/cp/tree.c31
6 files changed, 161 insertions, 53 deletions
diff --git a/gnu/egcs/gcc/cp/cp-tree.h b/gnu/egcs/gcc/cp/cp-tree.h
index c7c501cbefe..c207156c423 100644
--- a/gnu/egcs/gcc/cp/cp-tree.h
+++ b/gnu/egcs/gcc/cp/cp-tree.h
@@ -2108,6 +2108,18 @@ extern int flag_new_for_scope;
#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
+/* The parameters for a call-declarator. */
+#define CALL_DECLARATOR_PARMS(NODE) \
+ (TREE_PURPOSE (TREE_OPERAND ((NODE), 1)))
+
+/* The cv-qualifiers for a call-declarator. */
+#define CALL_DECLARATOR_QUALS(NODE) \
+ (TREE_VALUE (TREE_OPERAND ((NODE), 1)))
+
+/* The exception-specification for a call-declarator. */
+#define CALL_DECLARATOR_EXCEPTION_SPEC(NODE) \
+ (TREE_TYPE ((NODE)))
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type,
signature_type };
diff --git a/gnu/egcs/gcc/cp/decl.c b/gnu/egcs/gcc/cp/decl.c
index 4b4f26a5f65..b7e19b3fccc 100644
--- a/gnu/egcs/gcc/cp/decl.c
+++ b/gnu/egcs/gcc/cp/decl.c
@@ -9434,7 +9434,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
break;
case CALL_EXPR:
- if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
+ if (parmlist_is_exprlist (CALL_DECLARATOR_PARMS (decl)))
{
/* This is actually a variable declaration using
constructor syntax. We need to call start_decl and
@@ -9444,7 +9444,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree attributes, prefix_attributes;
*next = TREE_OPERAND (decl, 0);
- init = TREE_OPERAND (decl, 1);
+ init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
@@ -10500,7 +10500,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
tree arg_types;
int funcdecl_p;
- tree inner_parms = TREE_OPERAND (declarator, 1);
+ tree inner_parms = CALL_DECLARATOR_PARMS (declarator);
tree inner_decl = TREE_OPERAND (declarator, 0);
/* Declaring a function type.
@@ -10530,10 +10530,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
inner_decl = dname;
/* Pick up type qualifiers which should be applied to `this'. */
- quals = TREE_OPERAND (declarator, 2);
+ quals = CALL_DECLARATOR_QUALS (declarator);
/* Pick up the exception specifications. */
- raises = TREE_TYPE (declarator);
+ raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
diff --git a/gnu/egcs/gcc/cp/decl2.c b/gnu/egcs/gcc/cp/decl2.c
index 5f0ff595315..b923b42c0c1 100644
--- a/gnu/egcs/gcc/cp/decl2.c
+++ b/gnu/egcs/gcc/cp/decl2.c
@@ -1673,7 +1673,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& TREE_OPERAND (declarator, 0)
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE
|| TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF)
- && parmlist_is_exprlist (TREE_OPERAND (declarator, 1)))
+ && parmlist_is_exprlist (CALL_DECLARATOR_PARMS (declarator)))
{
init = TREE_OPERAND (declarator, 1);
declarator = TREE_OPERAND (declarator, 0);
@@ -3938,7 +3938,7 @@ reparse_absdcl_as_casts (decl, expr)
if (TREE_CODE (expr) == CONSTRUCTOR
&& TREE_TYPE (expr) == 0)
{
- type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
+ type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
if (IS_SIGNATURE (type))
@@ -3958,7 +3958,7 @@ reparse_absdcl_as_casts (decl, expr)
while (decl)
{
- type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
+ type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
expr = build_c_cast (type, expr);
}
diff --git a/gnu/egcs/gcc/cp/lex.c b/gnu/egcs/gcc/cp/lex.c
index db8fdd50db2..73a1eac576c 100644
--- a/gnu/egcs/gcc/cp/lex.c
+++ b/gnu/egcs/gcc/cp/lex.c
@@ -225,8 +225,15 @@ tree
make_call_declarator (target, parms, cv_qualifiers, exception_specification)
tree target, parms, cv_qualifiers, exception_specification;
{
- target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers);
- TREE_TYPE (target) = exception_specification;
+ target = build_parse_node (CALL_EXPR, target,
+ /* Both build_parse_node and
+ decl_tree_cons build on the
+ temp_decl_obstack. */
+ decl_tree_cons (parms, cv_qualifiers, NULL_TREE),
+ /* The third operand is really RTL. We
+ shouldn't put anything there. */
+ NULL_TREE);
+ CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification;
return target;
}
@@ -234,8 +241,8 @@ void
set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification)
tree call_declarator, cv_qualifiers, exception_specification;
{
- TREE_OPERAND (call_declarator, 2) = cv_qualifiers;
- TREE_TYPE (call_declarator) = exception_specification;
+ CALL_DECLARATOR_QUALS (call_declarator) = cv_qualifiers;
+ CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification;
}
/* Build names and nodes for overloaded operators. */
@@ -2869,6 +2876,14 @@ do_identifier (token, parsing, args)
|| TREE_CODE (field) == CONST_DECL
|| TREE_CODE (field) == TEMPLATE_DECL)
id = field;
+ else if (TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field)
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (field)))
+ /* When we did name-lookup before, we will have eschewed
+ implicit typenames in favor of global bindings. Therefore,
+ if lookup_field returns an implicit typename, but ID is not
+ an implicit typename, then we should skip this one, too. */
+ ;
else if (TREE_CODE (field) != FIELD_DECL)
my_friendly_abort (61);
else
@@ -4674,7 +4689,6 @@ make_lang_type (code)
TYPE_LANG_SPECIFIC (t) = pi;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
/* Make sure this is laid out, for ease of use later. In the
presence of parse errors, the normal was of assuring this
@@ -4692,6 +4706,13 @@ make_lang_type (code)
clear it here. */
TYPE_ALIAS_SET (t) = 0;
+ /* We need to allocate a TYPE_BINFO even for TEMPALTE_TYPE_PARMs
+ since they can be virtual base types, and we then need a
+ canonical binfo for them. Ideally, this would be done lazily for
+ all types. */
+ if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM)
+ TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
+
return t;
}
diff --git a/gnu/egcs/gcc/cp/pt.c b/gnu/egcs/gcc/cp/pt.c
index 442f1b04953..9405905fd67 100644
--- a/gnu/egcs/gcc/cp/pt.c
+++ b/gnu/egcs/gcc/cp/pt.c
@@ -161,6 +161,7 @@ static int coerce_template_template_parms PROTO((tree, tree, int,
static tree determine_specialization PROTO((tree, tree, tree *, int));
static int template_args_equal PROTO((tree, tree));
static void print_template_context PROTO((int));
+static int has_pvbases_p PROTO((tree, tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -2210,12 +2211,17 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type)
- && DECL_REAL_CONTEXT (decl) == current_class_type
&& DECL_LANG_SPECIFIC (decl)
- && DECL_DEFINED_IN_CLASS_P (decl))
+ /* If this is either a friend defined in the scope of the class
+ or a member function. */
+ && DECL_CLASS_CONTEXT (decl) == current_class_type
+ /* And, if it was a member function, it really was defined in
+ the scope of the class. */
+ && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl)))
/* We already checked these parameters when the template was
- declared, so there's no need to do it again now. This is an
- inline member function definition. */
+ declared, so there's no need to do it again now. This function
+ was defined in class scope, but we're processing it's body now
+ that the class is complete. */
return;
if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
@@ -2781,18 +2787,14 @@ convert_nontype_argument (type, expr)
applied. */
e = perform_qualification_conversions (type, expr);
if (TREE_CODE (e) == NOP_EXPR)
- {
- /* The call to perform_qualification_conversions will
- insert a NOP_EXPR over EXPR to do express
- conversion, if necessary. But, that will confuse
- us if we use this (converted) template parameter to
- instantiate another template; then the thing will
- not look like a valid template argument. So, just
- make a new constant, of the appropriate type. */
- e = make_node (PTRMEM_CST);
- TREE_TYPE (e) = type;
- PTRMEM_CST_MEMBER (e) = PTRMEM_CST_MEMBER (expr);
- }
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
return e;
}
else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
@@ -3573,6 +3575,7 @@ maybe_get_template_decl_from_type_decl (decl)
return (decl != NULL_TREE
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_ARTIFICIAL (decl)
+ && CLASS_TYPE_P (TREE_TYPE (decl))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
@@ -4683,6 +4686,23 @@ tsubst_friend_class (friend_tmpl, args)
return friend_type;
}
+static int
+has_pvbases_p (t, pattern)
+ tree t, pattern;
+{
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (t))
+ return 0;
+
+ if (TYPE_USES_PVBASES (pattern))
+ return 1;
+
+ for (t = CLASSTYPE_VBASECLASSES (t); t; t = TREE_CHAIN (t))
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (t)))
+ return 1;
+
+ return 0;
+}
+
tree
instantiate_class_template (type)
tree type;
@@ -5033,6 +5053,13 @@ instantiate_class_template (type)
}
}
+ /* After we have calculated the bases, we can now compute whether we
+ have polymorphic vbases. This needs to happen before we
+ instantiate the methods, because the constructors may take
+ additional arguments. */
+ if (flag_vtable_thunks >= 2)
+ TYPE_USES_PVBASES (type) = has_pvbases_p (type, pattern);
+
/* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
for this instantiation. */
for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
@@ -5714,9 +5741,17 @@ tsubst_decl (t, args, type, in_decl)
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
+
+ if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+
/* Set the mangled name for R. */
if (DECL_DESTRUCTOR_P (t))
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ DECL_ASSEMBLER_NAME (r) =
+ build_destructor_name (ctx, DECL_DESTRUCTOR_FOR_PVBASE_P (r));
else
{
/* Instantiations of template functions must be mangled
@@ -5759,11 +5794,14 @@ tsubst_decl (t, args, type, in_decl)
in_decl);
}
+#if 0
+ /* This has now moved further up. */
if (DECL_CONSTRUCTOR_P (r))
{
maybe_retrofit_in_chrg (r);
grok_ctor_properties (ctx, r);
}
+#endif
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
@@ -6128,7 +6166,17 @@ tsubst (t, args, complain, in_decl)
if (max == error_mark_node)
return error_mark_node;
- if (processing_template_decl)
+ /* See if we can reduce this expression to something simpler. */
+ max = maybe_fold_nontype_arg (max);
+ if (!processing_template_decl && TREE_READONLY_DECL_P (max))
+ max = decl_constant_value (max);
+
+ if (processing_template_decl
+ /* When providing explicit arguments to a template
+ function, but leaving some arguments for subsequent
+ deduction, MAX may be template-dependent even if we're
+ not PROCESSING_TEMPLATE_DECL. */
+ || TREE_CODE (max) != INTEGER_CST)
{
tree itype = make_node (INTEGER_TYPE);
TYPE_MIN_VALUE (itype) = size_zero_node;
@@ -6535,6 +6583,8 @@ tsubst (t, args, complain, in_decl)
}
f = make_typename_type (ctx, f);
+ if (f == error_mark_node)
+ return f;
return cp_build_qualified_type (f,
CP_TYPE_QUALS (f)
| CP_TYPE_QUALS (t));
@@ -6574,15 +6624,16 @@ tsubst (t, args, complain, in_decl)
{
tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
in_decl);
- tree e2 = tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args,
- complain, in_decl);
- tree e3 = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree e2 = (tsubst_call_declarator_parms
+ (CALL_DECLARATOR_PARMS (t), args, complain, in_decl));
+ tree e3 = tsubst (CALL_DECLARATOR_EXCEPTION_SPEC (t), args,
+ complain, in_decl);
if (e1 == error_mark_node || e2 == error_mark_node
|| e3 == error_mark_node)
return error_mark_node;
- return make_call_declarator (e1, e2, TREE_OPERAND (t, 2), e3);
+ return make_call_declarator (e1, e2, CALL_DECLARATOR_QUALS (t), e3);
}
case SCOPE_REF:
@@ -6908,9 +6959,20 @@ tsubst_copy (t, args, complain, in_decl)
/* Substituted template arguments */
tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, complain,
in_decl);
- tree chain;
- for (chain = targs; chain; chain = TREE_CHAIN (chain))
- TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+
+ if (targs && TREE_CODE (targs) == TREE_LIST)
+ {
+ tree chain;
+ for (chain = targs; chain; chain = TREE_CHAIN (chain))
+ TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+ }
+ else if (targs)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (targs); ++i)
+ TREE_VEC_ELT (targs, i)
+ = maybe_fold_nontype_arg (TREE_VEC_ELT (targs, i));
+ }
return lookup_template_function
(tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), targs);
@@ -8893,8 +8955,8 @@ do_decl_instantiation (declspecs, declarator, storage)
No program shall both explicitly instantiate and explicitly
specialize a template. */
- cp_error ("explicit instantiation of `%#D' after", result);
- cp_error_at ("explicit specialization here", result);
+ cp_pedwarn ("explicit instantiation of `%#D' after", result);
+ cp_pedwarn_at ("explicit specialization here", result);
return;
}
else if (DECL_EXPLICIT_INSTANTIATION (result))
@@ -8907,8 +8969,8 @@ do_decl_instantiation (declspecs, declarator, storage)
We check DECL_INTERFACE_KNOWN so as not to complain when the
first instantiation was `extern' and the second is not, and
EXTERN_P for the opposite case. */
- if (DECL_INTERFACE_KNOWN (result) && !extern_p)
- cp_error ("duplicate explicit instantiation of `%#D'", result);
+ if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
+ cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
/* If we've already instantiated the template, just return now. */
if (DECL_INTERFACE_KNOWN (result))
@@ -9035,8 +9097,8 @@ do_type_instantiation (t, storage)
If CLASSTYPE_INTERFACE_ONLY, then the first explicit
instantiation was `extern', and if EXTERN_P then the second
is. Both cases are OK. */
- if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
- cp_error ("duplicate explicit instantiation of `%#T'", t);
+ if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository)
+ cp_pedwarn ("duplicate explicit instantiation of `%#T'", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
diff --git a/gnu/egcs/gcc/cp/tree.c b/gnu/egcs/gcc/cp/tree.c
index bf16fe2a0c5..bb598ef34e6 100644
--- a/gnu/egcs/gcc/cp/tree.c
+++ b/gnu/egcs/gcc/cp/tree.c
@@ -71,6 +71,7 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
+ case NOP_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
@@ -193,7 +194,7 @@ build_cplus_new (type, init)
tree rval;
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
- return init;
+ return convert (type, init);
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
@@ -1882,14 +1883,7 @@ mapcar (t, func)
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-
- /* tree.def says that operand two is RTL, but
- make_call_declarator puts trees in there. */
- if (TREE_OPERAND (t, 2)
- && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
- TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
- else
- TREE_OPERAND (t, 2) = NULL_TREE;
+ TREE_OPERAND (t, 2) = NULL_TREE;
return t;
case CONVERT_EXPR:
@@ -1901,6 +1895,7 @@ mapcar (t, func)
case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
+ case NON_LVALUE_EXPR:
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
@@ -2789,3 +2784,21 @@ cp_valid_lang_attribute (attr_name, attr_args, decl, type)
return 0;
}
+
+/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
+ thing pointed to by the constant. */
+
+tree
+make_ptrmem_cst (type, member)
+ tree type;
+ tree member;
+{
+ tree ptrmem_cst = make_node (PTRMEM_CST);
+ /* If would seem a great convenience if make_node would set
+ TREE_CONSTANT for things of class `c', but it does not. */
+ TREE_CONSTANT (ptrmem_cst) = 1;
+ TREE_TYPE (ptrmem_cst) = type;
+ PTRMEM_CST_MEMBER (ptrmem_cst) = member;
+ return ptrmem_cst;
+}
+