summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>1999-06-20 16:02:07 +0000
committerMarc Espie <espie@cvs.openbsd.org>1999-06-20 16:02:07 +0000
commit4afe9ad9930b7ccaffe9016029cdc4a06c4cf09c (patch)
tree907832cf342b708bde5ee1dccdb6e96cf4d468d7
parent98b4c1c3edb281110081f22d9fef01547a00f2d6 (diff)
Fix for kdelibs ICE, to appear in the next egcs-snapshot
(by Mark Mitchell)
-rw-r--r--gnu/egcs/gcc/cp/decl.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/gnu/egcs/gcc/cp/decl.c b/gnu/egcs/gcc/cp/decl.c
index 9df5474c1e4..291c5df52b3 100644
--- a/gnu/egcs/gcc/cp/decl.c
+++ b/gnu/egcs/gcc/cp/decl.c
@@ -8504,6 +8504,8 @@ expand_static_init (decl, init)
{
tree cleanup, fcall;
static tree Atexit = 0;
+ int saved_flag_access_control;
+
if (Atexit == 0)
{
tree atexit_fndecl, PFV, pfvlist;
@@ -8530,13 +8532,31 @@ expand_static_init (decl, init)
so that any access checks will be done relative to the
current scope, rather than the scope of the anonymous
function. */
- fcall = build_cleanup (decl);
+ build_cleanup (decl);
+
+ /* Now start the function. */
cleanup = start_anon_func ();
+
+ /* Now, recompute the cleanup. It may contain SAVE_EXPRs
+ that refer to the original function, rather than the
+ anonymous one. That will make the back-end think that
+ nested functions are in use, which causes confusion. */
+ saved_flag_access_control = flag_access_control;
+ flag_access_control = 0;
+ fcall = build_cleanup (decl);
+ flag_access_control = saved_flag_access_control;
+
+ /* Finish off the function. */
expand_expr_stmt (fcall);
end_anon_func ();
+
+ /* Call atexit with the cleanup function. */
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
- fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+ fcall = build_function_call (Atexit,
+ expr_tree_cons (NULL_TREE,
+ cleanup,
+ NULL_TREE));
expand_expr_stmt (fcall);
}
@@ -8558,7 +8578,7 @@ expand_static_init (decl, init)
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
+ 2 if there was no information (in which case assume 0 if DO_DEFAULT). */
int
complete_array_type (type, initial_value, do_default)
@@ -8567,7 +8587,10 @@ complete_array_type (type, initial_value, do_default)
{
register tree maxindex = NULL_TREE;
int value = 0;
-
+
+ /* Allocate on the same obstack as TYPE. */
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+
if (initial_value)
{
/* Note MAXINDEX is really the maximum index,
@@ -8615,23 +8638,28 @@ complete_array_type (type, initial_value, do_default)
if (maxindex)
{
tree itype;
+ tree domain;
+
+ domain = build_index_type (maxindex);
+ TYPE_DOMAIN (type) = domain;
- TYPE_DOMAIN (type) = build_index_type (maxindex);
if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
- TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (itype) = domain;
/* The type of the main variant should never be used for arrays
of different sizes. It should only ever be completed with the
size of the array. */
if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
- TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
}
+ pop_obstacks();
+
/* Lay out the type now that we can get the real answer. */
layout_type (type);
@@ -8710,6 +8738,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ int has_default_arg = 0;
tree t;
if (ctype)
@@ -8826,7 +8855,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
- add_defarg_fn (decl);
+ has_default_arg = 1;
break;
}
@@ -8847,6 +8876,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
return NULL_TREE;
}
+
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
@@ -8854,9 +8884,26 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
+
+ if (has_default_arg)
+ {
+ cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
+
+ if (inlinep)
+ {
+ cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
}
}
+ if (has_default_arg)
+ add_defarg_fn (decl);
+
/* Plain overloading: will not be grok'd by grokclassfn. */
if (! ctype && ! processing_template_decl
&& DECL_LANGUAGE (decl) != lang_c
@@ -10300,7 +10347,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
continue;
/* VC++ spells a zero-sized array with []. */
- if (size == NULL_TREE && decl_context == FIELD && ! staticp)
+ if (size == NULL_TREE && decl_context == FIELD && ! staticp
+ && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
size = integer_zero_node;
if (size)