This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH to change handling of local declarations in templates
- To: gcc-patches@gcc.gnu.org
- Subject: PATCH to change handling of local declarations in templates
- From: Mark Mitchell <mark@codesourcery.com>
- Date: Sat, 14 Aug 1999 02:32:13 -0700
- Organization: CodeSourcery, LLC
Previously, we handled local declarations in templates by storing the
declarator and decl-specifiers until instantiation time, at which
point we reconstituted the declaration. This patch keeps track of
these local declarations in just the same way we keep track of
non-local non-primary template declarations. Besides the uniformity,
this patch enables two other future modifications:
o Whole translation-unit representation of source code.
o Two-phase name binding. (There are now declarations to point at,
so we could represent `i + b' as the sum of two VAR_DECLs, rather
than two IDENTIFIER_NODEs.)
I fixed a couple of minor template buglets while doing this.
Although the tests pass, including those for libstdc++, I would expect
that *something* will go wrong as a consequence of this change.
Please let me know what.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Index: testsuite/g++.old-deja/g++.pt/crash15.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/crash15.C,v
retrieving revision 1.2
diff -c -p -r1.2 crash15.C
*** crash15.C 1998/12/16 21:54:12 1.2
--- crash15.C 1999/08/14 09:04:01
*************** struct A { // ERROR - too many template
*** 6,10 ****
public:
A() {}
! A(const A<T>& b) {} // ERROR - invalid use of template
};
--- 6,10 ----
public:
A() {}
! A(const A<T>& b) {}
};
Index: testsuite/g++.old-deja/g++.pt/defarg12.C
===================================================================
RCS file: defarg12.C
diff -N defarg12.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- defarg12.C Sat Aug 14 02:04:01 1999
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+
+ template <class T = int>
+ struct S
+ {
+ void f ()
+ {
+ struct U {
+ };
+ }
+ };
Index: testsuite/g++.old-deja/g++.pt/defarg13.C
===================================================================
RCS file: defarg13.C
diff -N defarg13.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- defarg13.C Sat Aug 14 02:04:01 1999
***************
*** 0 ****
--- 1,13 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+
+ template <class T>
+ void f (int i)
+ {
+ struct S { void g (int j = i) {} }; // ERROR - default argument uses local
+
+ S s; // ERROR - instantiated here
+ }
+
+ template void f<double>(int); // ERROR - instantiated here
+
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.161
diff -c -p -r1.161 call.c
*** call.c 1999/08/11 20:22:23 1.161
--- call.c 1999/08/14 09:04:16
*************** convert_default_arg (type, arg, fn)
*** 3787,3816 ****
tree fn;
{
if (fn && DECL_TEMPLATE_INFO (fn))
! {
! /* This default argument came from a template. Instantiate the
! default argument here, not in tsubst. In the case of
! something like:
!
! template <class T>
! struct S {
! static T t();
! void f(T = t());
! };
!
! we must be careful to do name lookup in the scope of S<T>,
! rather than in the current class. */
! if (DECL_CLASS_SCOPE_P (fn))
! pushclass (DECL_REAL_CONTEXT (fn), 2);
!
! arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
!
! if (DECL_CLASS_SCOPE_P (fn))
! popclass ();
!
! /* Make sure the default argument is reasonable. */
! arg = check_default_argument (type, arg);
! }
arg = break_out_target_exprs (arg);
--- 3787,3793 ----
tree fn;
{
if (fn && DECL_TEMPLATE_INFO (fn))
! arg = tsubst_default_argument (fn, type, arg);
arg = break_out_target_exprs (arg);
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.176
diff -c -p -r1.176 class.c
*** class.c 1999/08/11 20:22:24 1.176
--- class.c 1999/08/14 09:04:19
*************** void
*** 1154,1161 ****
add_method (type, fields, method)
tree type, *fields, method;
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
/* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
redundant. */
--- 1154,1160 ----
add_method (type, fields, method)
tree type, *fields, method;
{
! push_permanent_obstack ();
/* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
redundant. */
*************** build_self_reference ()
*** 5383,5388 ****
--- 5382,5390 ----
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
+
+ if (processing_template_decl)
+ value = push_template_decl (value);
saved_cas = current_access_specifier;
current_access_specifier = access_public_node;
Index: cp/cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.28
diff -c -p -r1.28 cp-tree.def
*** cp-tree.def 1999/05/17 16:07:30 1.28
--- cp-tree.def 1999/08/14 09:04:19
*************** DEFTREECODE (TYPEID_EXPR, "typeid_expr",
*** 217,223 ****
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
! DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3)
DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
--- 217,223 ----
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
! DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.260
diff -c -p -r1.260 cp-tree.h
*** cp-tree.h 1999/08/12 01:45:33 1.260
--- cp-tree.h 1999/08/14 09:04:22
*************** Boston, MA 02111-1307, USA. */
*** 77,82 ****
--- 77,83 ----
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
+ DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
4: DECL_MAYBE_TEMPLATE.
5: DECL_INTERFACE_KNOWN.
*************** struct lang_decl_flags
*** 1192,1202 ****
tree access;
tree context;
- /* In a template FUNCTION_DECL, this is DECL_SAVED_TREE. */
- tree saved_tree;
-
union {
! /* In a FUNCTION_DECL, this is DECL_TEMPLATE_INFO. */
tree template_info;
/* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
--- 1193,1200 ----
tree access;
tree context;
union {
! /* In a FUNCTION_DECL or a VAR_DECL, this is DECL_TEMPLATE_INFO. */
tree template_info;
/* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
*************** struct lang_decl
*** 1210,1219 ****
--- 1208,1224 ----
tree main_decl_variant;
tree befriending_classes;
+
+ /* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
+ tree saved_tree;
+
union
{
tree sorted_fields;
struct pending_inline *pending_inline_info;
+ /* The lang_decls on the free_lang_decl_chain are chained together
+ through this pointer. */
+ struct lang_decl *next;
} u;
};
*************** struct lang_decl
*** 1502,1508 ****
/* In a template FUNCTION_DECL, the tree structure that will be
substituted into to obtain instantiations. */
#define DECL_SAVED_TREE(NODE) \
! (DECL_LANG_SPECIFIC ((NODE))->decl_flags.saved_tree)
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
--- 1507,1513 ----
/* In a template FUNCTION_DECL, the tree structure that will be
substituted into to obtain instantiations. */
#define DECL_SAVED_TREE(NODE) \
! (DECL_LANG_SPECIFIC ((NODE))->saved_tree)
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
*************** extern int flag_new_for_scope;
*** 1984,1989 ****
--- 1989,2006 ----
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
+ /* Nonzero if NODE is the typedef implicitly generated for a type when
+ the type is declared. (In C++, `struct S {};' is roughly equivalent
+ to `struct S {}; typedef struct S S;' in C. This macro will hold
+ for the typedef indicated in this example. Note that in C++, there
+ is a second implicit typedef for each class, in the scope of `S'
+ itself, so that you can `S::S'. This macro does *not* hold for
+ those typedefs. */
+ #define DECL_IMPLICIT_TYPEDEF_P(NODE) \
+ (TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
+ #define SET_DECL_IMPLICIT_TYPEDEF_P(NODE) \
+ (DECL_LANG_FLAG_2 ((NODE)) = 1)
+
/* A `primary' template is one that has its own template header. A
member function of a class template is a template, but not primary.
A member template is primary. Friend templates are primary, too. */
*************** extern int flag_new_for_scope;
*** 2120,2125 ****
--- 2137,2143 ----
#define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2)
#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
+ #define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \
*************** extern int walk_namespaces
*** 2933,2938 ****
--- 2951,2958 ----
void *));
extern int wrapup_globals_for_namespace PROTO((tree, void *));
extern tree cp_namespace_decls PROTO((tree));
+ extern tree create_implicit_typedef PROTO((tree, tree));
+ extern tree maybe_push_decl PROTO((tree));
/* in decl2.c */
extern int check_java_method PROTO((tree));
*************** extern void do_type_instantiation PROTO
*** 3188,3194 ****
extern tree instantiate_decl PROTO((tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree));
- /* CONT ... */
extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void));
extern void end_tree PROTO((void));
--- 3208,3213 ----
*************** extern void maybe_check_template_type
*** 3207,3212 ****
--- 3226,3232 ----
extern tree most_specialized_instantiation PROTO((tree, tree));
extern void print_candidates PROTO((tree));
extern int instantiate_pending_templates PROTO((void));
+ extern tree tsubst_default_argument PROTO((tree, tree, tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;
*************** extern void print_search_statistics PRO
*** 3254,3259 ****
--- 3274,3280 ----
extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
+ extern int at_function_scope_p PROTO((void));
extern tree lookup_conversions PROTO((tree));
extern tree binfo_for_vtable PROTO((tree));
extern int binfo_from_vbase PROTO((tree));
*************** extern tree finish_base_specifier
*** 3339,3344 ****
--- 3360,3366 ----
extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
+ extern void add_decl_stmt PROTO((tree));
/* in spew.c */
extern void init_spew PROTO((void));
*************** extern tree mapcar PROTO((tree, tree
*** 3415,3420 ****
--- 3437,3443 ----
extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void));
+ extern void push_permanent_obstack PROTO((void));
extern tree build_dummy_object PROTO((tree));
extern tree maybe_dummy_object PROTO((tree, tree *));
extern int is_dummy_object PROTO((tree));
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.404
diff -c -p -r1.404 decl.c
*** decl.c 1999/08/12 01:45:33 1.404
--- decl.c 1999/08/14 09:04:31
*************** declare_namespace_level ()
*** 923,931 ****
int
pseudo_global_level_p ()
{
! struct binding_level *b = innermost_nonclass_level ();
!
! return b->pseudo_global;
}
void
--- 923,929 ----
int
pseudo_global_level_p ()
{
! return current_binding_level->pseudo_global;
}
void
*************** push_binding (id, decl, level)
*** 1018,1025 ****
if (!free_binding_nodes)
{
/* There are no free nodes, so we must build one here. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
binding = make_node (CPLUS_BINDING);
pop_obstacks ();
}
--- 1016,1022 ----
if (!free_binding_nodes)
{
/* There are no free nodes, so we must build one here. */
! push_permanent_obstack ();
binding = make_node (CPLUS_BINDING);
pop_obstacks ();
}
*************** maybe_process_template_type_declaration
*** 2761,2766 ****
--- 2758,2786 ----
return decl;
}
+ /* In C++, you don't have to write `struct S' to refer to `S'; you
+ can just use `S'. We accomplish this by creating a TYPE_DECL as
+ if the user had written `typedef struct S S'. Create and return
+ the TYPE_DECL for TYPE. */
+
+ tree
+ create_implicit_typedef (name, type)
+ tree name;
+ tree type;
+ {
+ tree decl;
+
+ decl = build_decl (TYPE_DECL, name, type);
+ SET_DECL_ARTIFICIAL (decl);
+ /* There are other implicit type declarations, like the one *within*
+ a class that allows you to write `S::S'. We must distinguish
+ amongst these. */
+ SET_DECL_IMPLICIT_TYPEDEF_P (decl);
+ TYPE_NAME (type) = decl;
+
+ return decl;
+ }
+
/* Push a tag name NAME for struct/class/union/enum type TYPE.
Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
*************** pushtag (name, type, globalize)
*** 2790,2798 ****
{
register tree d = NULL_TREE;
int in_class = 0;
! tree context;
- context = type ? TYPE_CONTEXT (type) : NULL_TREE;
if (! context)
{
tree cs = current_scope ();
--- 2810,2817 ----
{
register tree d = NULL_TREE;
int in_class = 0;
! tree context = TYPE_CONTEXT (type);
if (! context)
{
tree cs = current_scope ();
*************** pushtag (name, type, globalize)
*** 2813,2827 ****
|| b->parm_flag == 2)
in_class = 1;
- d = build_decl (TYPE_DECL, name, type);
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
- SET_DECL_ARTIFICIAL (d);
- if (! in_class)
- set_identifier_type_value_with_scope (name, type, b);
! TYPE_NAME (type) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
d = maybe_process_template_type_declaration (type,
globalize, b);
--- 2832,2844 ----
|| b->parm_flag == 2)
in_class = 1;
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
! d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ if (! in_class)
+ set_identifier_type_value_with_scope (name, type, b);
d = maybe_process_template_type_declaration (type,
globalize, b);
*************** duplicate_decls (newdecl, olddecl)
*** 3449,3458 ****
if (oldtype)
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
! {
! push_obstacks_nochange ();
! end_temporary_allocation ();
! }
/* Merge the data types specified in the two decls. */
newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
--- 3466,3472 ----
if (oldtype)
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
! push_permanent_obstack ();
/* Merge the data types specified in the two decls. */
newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
*************** duplicate_decls (newdecl, olddecl)
*** 3733,3746 ****
{
if (DECL_MAIN_VARIANT (olddecl) == olddecl)
{
! /* Save these lang_decls that would otherwise be lost. */
! extern tree free_lang_decl_chain;
! tree free_lang_decl = (tree) ol;
if (DECL_LANG_SPECIFIC (olddecl) == ol)
abort ();
! TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl;
}
else
--- 3747,3759 ----
{
if (DECL_MAIN_VARIANT (olddecl) == olddecl)
{
! struct lang_decl *free_lang_decl = ol;
+ /* Save these lang_decls that would otherwise be lost. */
if (DECL_LANG_SPECIFIC (olddecl) == ol)
abort ();
! free_lang_decl->u.next = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl;
}
else
*************** pushdecl_class_level (x)
*** 4310,4315 ****
--- 4323,4357 ----
}
}
+ /* Enter DECL into the symbol table, if that's appropriate. Returns
+ DECL, or a modified version thereof. */
+
+ tree
+ maybe_push_decl (decl)
+ tree decl;
+ {
+ tree type = TREE_TYPE (decl);
+
+ /* Add this decl to the current binding level, but not if it comes
+ from another scope, e.g. a static member variable. TEM may equal
+ DECL or it may be a previous decl of the same name. */
+ if ((TREE_CODE (decl) != PARM_DECL
+ && DECL_CONTEXT (decl) != NULL_TREE
+ /* Definitions of namespace members outside their namespace are
+ possible. */
+ && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+ || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
+ || TREE_CODE (type) == UNKNOWN_TYPE
+ /* The declaration of template specializations does not affect
+ the functions available for overload resolution, so we do not
+ call pushdecl. */
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_TEMPLATE_SPECIALIZATION (decl)))
+ return decl;
+ else
+ return pushdecl (decl);
+ }
+
#if 0
/* This function is used to push the mangled decls for nested types into
the appropriate scope. Previously pushdecl_top_level was used, but that
*************** start_decl (declarator, declspecs, initi
*** 6987,7020 ****
decl);
}
! /* Add this decl to the current binding level, but not if it
! comes from another scope, e.g. a static member variable.
! TEM may equal DECL or it may be a previous decl of the same name. */
!
! if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE
! /* Definitions of namespace members outside their namespace are
! possible. */
! && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
! || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
! || TREE_CODE (type) == LANG_TYPE
! /* The declaration of template specializations does not affect
! the functions available for overload resolution, so we do not
! call pushdecl. */
! || (TREE_CODE (decl) == FUNCTION_DECL
! && DECL_TEMPLATE_SPECIALIZATION (decl)))
! tem = decl;
! else
! tem = pushdecl (decl);
if (processing_template_decl)
{
! if (! current_function_decl)
! tem = push_template_decl (tem);
! else
! DECL_VINDEX (tem)
! = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
! copy_to_permanent (declspecs),
! NULL_TREE);
}
--- 7029,7050 ----
decl);
}
! /* Enter this declaration into the symbol table. */
! tem = maybe_push_decl (decl);
if (processing_template_decl)
{
! if (at_function_scope_p ())
! push_permanent_obstack ();
!
! tem = push_template_decl (tem);
! /* In a a local scope, add a representation of this declaration
! to the statement tree. */
! if (at_function_scope_p ())
! {
! add_decl_stmt (decl);
! pop_obstacks ();
! }
}
*************** start_decl (declarator, declspecs, initi
*** 7033,7064 ****
/* Corresponding pop_obstacks is done in `cp_finish_decl'. */
push_obstacks_nochange ();
- #if 0
- /* We have no way of knowing whether the initializer will need to be
- evaluated at run-time or not until we've parsed it, so let's just put
- it in the permanent obstack. (jason) */
- if (init_written
- && ! (TREE_CODE (tem) == PARM_DECL
- || (TREE_READONLY (tem)
- && (TREE_CODE (tem) == VAR_DECL
- || TREE_CODE (tem) == FIELD_DECL))))
- {
- /* When parsing and digesting the initializer,
- use temporary storage. Do this even if we will ignore the value. */
- if (toplevel_bindings_p () && debug_temp_inits)
- {
- if (processing_template_decl
- || TYPE_NEEDS_CONSTRUCTING (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
- /* In this case, the initializer must lay down in permanent
- storage, since it will be saved until `finish_file' is run. */
- ;
- else
- temporary_allocation ();
- }
- }
- #endif
-
return tem;
}
--- 7063,7068 ----
*************** start_decl_1 (decl)
*** 7130,7152 ****
}
}
- #if 0
- /* We don't do this yet for GNU C++. */
- /* For a local variable, define the RTL now. */
- if (! toplevel_bindings_p ()
- /* But not if this is a duplicate decl
- and we preserved the rtl from the previous one
- (which may or may not happen). */
- && DECL_RTL (tem) == NULL_RTX)
- {
- if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
- expand_decl (tem);
- else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != NULL_TREE)
- expand_decl (tem);
- }
- #endif
-
if (! initialized)
DECL_INITIAL (decl) = NULL_TREE;
}
--- 7134,7139 ----
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7380,7401 ****
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
! DECL_INITIAL (decl) = init;
! if (current_function_decl && ! DECL_ARTIFICIAL (decl))
! {
! tree stmt = DECL_VINDEX (decl);
! /* If the decl is declaring a member of a local class (in a
! template function), the DECL_VINDEX will either be NULL,
! or it will be an actual virtual function index, not a
! DECL_STMT. */
! if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
! {
! DECL_VINDEX (decl) = NULL_TREE;
! TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! add_tree (stmt);
! }
! }
!
goto finish_end0;
}
--- 7367,7373 ----
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
! DECL_INITIAL (decl) = copy_to_permanent (init);
goto finish_end0;
}
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7466,7474 ****
else if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_STATIC (decl))
! make_decl_rtl (decl, NULL_PTR,
! toplevel_bindings_p ()
! || pseudo_global_level_p ());
grok_reference_init (decl, type, init);
init = NULL_TREE;
}
--- 7438,7444 ----
else if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_STATIC (decl))
! make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
grok_reference_init (decl, type, init);
init = NULL_TREE;
}
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7678,7684 ****
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
! int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
--- 7648,7654 ----
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
! int toplev = toplevel_bindings_p ();
int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
*************** grokvardecl (type, declarator, specbits_
*** 8647,8653 ****
else
context = NULL_TREE;
! decl = build_decl (VAR_DECL, declarator, complete_type (type));
if (context)
set_decl_namespace (decl, context, 0);
--- 8617,8633 ----
else
context = NULL_TREE;
! if (processing_template_decl)
! {
! /* If we're in a template, we need DECL_LANG_SPECIFIC so that
! we can call push_template_decl. */
! push_permanent_obstack ();
! decl = build_lang_field_decl (VAR_DECL, declarator,
! complete_type (type));
! pop_obstacks ();
! }
! else
! decl = build_decl (VAR_DECL, declarator, complete_type (type));
if (context)
set_decl_namespace (decl, context, 0);
*************** grokdeclarator (declarator, declspecs, d
*** 9259,9266 ****
We also want to avoid calling this a PARM if it is in a namespace. */
! if (decl_context == NORMAL && ! namespace_bindings_p ()
! && ! pseudo_global_level_p ())
{
struct binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
--- 9239,9245 ----
We also want to avoid calling this a PARM if it is in a namespace. */
! if (decl_context == NORMAL && !toplevel_bindings_p ())
{
struct binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
*************** grokdeclarator (declarator, declspecs, d
*** 10568,10582 ****
since it might be used as a template parameter. */
if (type != error_mark_node)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
! decl = build_decl (TYPE_DECL, declarator, type);
if (type != error_mark_node)
pop_obstacks ();
}
! /* If the user declares "struct {...} foo" then `foo' will have
! an anonymous name. Fill that name in now. Nothing can
! refer to it, so nothing needs know about the name change.
! The TYPE_NAME field was filled in by build_struct_xref. */
if (type != error_mark_node
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
--- 10547,10564 ----
since it might be used as a template parameter. */
if (type != error_mark_node)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
! if (processing_template_decl)
! decl = build_lang_field_decl (TYPE_DECL, declarator, type);
! else
! decl = build_decl (TYPE_DECL, declarator, type);
if (type != error_mark_node)
pop_obstacks ();
}
! /* If the user declares "typedef struct {...} foo" then the
! struct will have an anonymous name. Fill that name in now.
! Nothing can refer to it, so nothing needs know about the name
! change. */
if (type != error_mark_node
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
*************** grokdeclarator (declarator, declspecs, d
*** 11039,11045 ****
{
/* C++ allows static class members.
All other work for this is done by grokfield.
! This VAR_DCL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
--- 11021,11027 ----
{
/* C++ allows static class members.
All other work for this is done by grokfield.
! This VAR_DECL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
*************** start_function (declspecs, declarator, a
*** 12913,12918 ****
--- 12895,12925 ----
if (pre_parsed_p == 2)
maybe_begin_member_template_processing (decl1);
+ /* Effective C++ rule 15. See also c_expand_return. */
+ if (warn_ecpp
+ && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+ && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
+ cp_warning ("`operator=' should return a reference to `*this'");
+
+ /* Make the init_value nonzero so pushdecl knows this is not tentative.
+ error_mark_node is replaced below (in poplevel) with the BLOCK. */
+ DECL_INITIAL (decl1) = error_mark_node;
+
+ #ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
+ #endif
+
+ /* This function exists in static storage.
+ (This does not mean `static' in the C sense!) */
+ TREE_STATIC (decl1) = 1;
+
+ /* We must call push_template_decl after current_class_type is set
+ up. (If we are processing inline definitions after exiting a
+ class scope, current_class_type will be NULL_TREE until set above
+ by push_nested_class.) */
+ if (processing_template_decl)
+ decl1 = push_template_decl (decl1);
+
/* We are now in the scope of the function being defined. */
current_function_decl = decl1;
*************** start_function (declspecs, declarator, a
*** 12954,12984 ****
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
-
- /* Effective C++ rule 15. See also c_expand_return. */
- if (warn_ecpp
- && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
- && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
- cp_warning ("`operator=' should return a reference to `*this'");
-
- /* Make the init_value nonzero so pushdecl knows this is not tentative.
- error_mark_node is replaced below (in poplevel) with the BLOCK. */
- DECL_INITIAL (decl1) = error_mark_node;
-
- #ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
- #endif
-
- /* This function exists in static storage.
- (This does not mean `static' in the C sense!) */
- TREE_STATIC (decl1) = 1;
-
- /* We must call push_template_decl after current_class_type is set
- up. (If we are processing inline definitions after exiting a
- class scope, current_class_type will be NULL_TREE until set above
- by push_nested_class.) */
- if (processing_template_decl)
- decl1 = push_template_decl (decl1);
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
--- 12961,12966 ----
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.232
diff -c -p -r1.232 decl2.c
*** decl2.c 1999/08/11 20:22:25 1.232
--- decl2.c 1999/08/14 09:04:34
*************** grokfield (declarator, declspecs, init,
*** 1639,1644 ****
--- 1639,1647 ----
DECL_ASSEMBLER_NAME (value) =
get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
+ if (processing_template_decl)
+ value = push_template_decl (value);
+
return value;
}
*************** get_sentry (base)
*** 2818,2825 ****
tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
if (! sentry)
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
sentry = build_decl (VAR_DECL, sname, integer_type_node);
TREE_PUBLIC (sentry) = 1;
DECL_ARTIFICIAL (sentry) = 1;
--- 2821,2827 ----
tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
if (! sentry)
{
! push_permanent_obstack ();
sentry = build_decl (VAR_DECL, sname, integer_type_node);
TREE_PUBLIC (sentry) = 1;
DECL_ARTIFICIAL (sentry) = 1;
Index: cp/dump.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/dump.c,v
retrieving revision 1.3
diff -c -p -r1.3 dump.c
*** dump.c 1999/08/11 20:40:11 1.3
--- dump.c 1999/08/14 09:04:34
*************** dequeue_and_dump (di)
*** 662,673 ****
case DECL_STMT:
dump_stmt (di, t);
- #if 0
- /* We do not yet have DECL_STMT_DECL; there are declarators and
- such hanging about in DECL_STMTs. */
if (dump_children_p)
dump_child ("decl", DECL_STMT_DECL (t));
- #endif
break;
case DO_STMT:
--- 662,669 ----
Index: cp/except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.68
diff -c -p -r1.68 except.c
*** except.c 1999/08/09 10:44:09 1.68
--- except.c 1999/08/14 09:04:35
*************** call_eh_info ()
*** 240,247 ****
/* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
/* struct cp_eh_info. This must match exception.cc. Note that this
type is not pushed anywhere. */
--- 240,246 ----
/* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
! push_permanent_obstack ();
/* struct cp_eh_info. This must match exception.cc. Note that this
type is not pushed anywhere. */
*************** build_eh_type_type_ref (type)
*** 422,429 ****
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
! push_obstacks_nochange ();
! end_temporary_allocation ();
if (flag_rtti)
{
--- 421,427 ----
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
! push_permanent_obstack ();
if (flag_rtti)
{
*************** do_pop_exception ()
*** 502,509 ****
{
/* Declare void __cp_pop_exception (void *),
as defined in exception.cc. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
fn = build_lang_decl
(FUNCTION_DECL, fn,
build_function_type (void_type_node, tree_cons
--- 500,506 ----
{
/* Declare void __cp_pop_exception (void *),
as defined in exception.cc. */
! push_permanent_obstack ();
fn = build_lang_decl
(FUNCTION_DECL, fn,
build_function_type (void_type_node, tree_cons
*************** expand_end_eh_spec (raises)
*** 773,780 ****
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
tmp = tree_cons
(NULL_TREE, integer_type_node, tree_cons
--- 770,776 ----
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
! push_permanent_obstack ();
tmp = tree_cons
(NULL_TREE, integer_type_node, tree_cons
*************** alloc_eh_object (type)
*** 920,927 ****
{
/* Declare __eh_alloc (size_t), as defined in exception.cc. */
tree tmp;
! push_obstacks_nochange ();
! end_temporary_allocation ();
tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (ptr_type_node, tmp));
--- 916,922 ----
{
/* Declare __eh_alloc (size_t), as defined in exception.cc. */
tree tmp;
! push_permanent_obstack ();
tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (ptr_type_node, tmp));
*************** expand_throw (exp)
*** 973,980 ****
the internal type of a destructor. */
if (cleanup_type == NULL_TREE)
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
cleanup_type = build_pointer_type
(build_function_type
(void_type_node, tree_cons
--- 968,974 ----
the internal type of a destructor. */
if (cleanup_type == NULL_TREE)
{
! push_permanent_obstack ();
cleanup_type = build_pointer_type
(build_function_type
(void_type_node, tree_cons
*************** expand_throw (exp)
*** 1074,1081 ****
/* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
as defined in exception.cc. */
tree tmp;
! push_obstacks_nochange ();
! end_temporary_allocation ();
tmp = tree_cons
(NULL_TREE, ptr_type_node, tree_cons
(NULL_TREE, ptr_type_node, tree_cons
--- 1068,1074 ----
/* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
as defined in exception.cc. */
tree tmp;
! push_permanent_obstack ();
tmp = tree_cons
(NULL_TREE, ptr_type_node, tree_cons
(NULL_TREE, ptr_type_node, tree_cons
*************** expand_throw (exp)
*** 1108,1115 ****
{
/* Declare void __uncatch_exception (void)
as defined in exception.cc. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (void_type_node,
void_list_node));
--- 1101,1107 ----
{
/* Declare void __uncatch_exception (void)
as defined in exception.cc. */
! push_permanent_obstack ();
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (void_type_node,
void_list_node));
Index: cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.117
diff -c -p -r1.117 init.c
*** init.c 1999/08/11 20:22:26 1.117
--- init.c 1999/08/14 09:04:37
*************** build_java_class_ref (type)
*** 2139,2146 ****
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
TREE_STATIC (class_decl) = 1;
DECL_EXTERNAL (class_decl) = 1;
--- 2139,2145 ----
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
{
! push_permanent_obstack ();
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
TREE_STATIC (class_decl) = 1;
DECL_EXTERNAL (class_decl) = 1;
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.133
diff -c -p -r1.133 lex.c
*** lex.c 1999/08/11 20:22:26 1.133
--- lex.c 1999/08/14 09:04:39
*************** get_time_identifier (name)
*** 330,337 ****
time_identifier = get_identifier (buf);
if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
TIME_IDENTIFIER_FILEINFO (time_identifier)
= build_int_2 (0, 1);
--- 330,336 ----
time_identifier = get_identifier (buf);
if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
! push_permanent_obstack ();
TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
TIME_IDENTIFIER_FILEINFO (time_identifier)
= build_int_2 (0, 1);
*************** extern int tree_node_sizes[];
*** 4715,4722 ****
#endif
/* Place to save freed lang_decls which were allocated on the
! permanent_obstack. @@ Not currently used. */
! tree free_lang_decl_chain;
tree
build_lang_decl (code, name, type)
--- 4714,4721 ----
#endif
/* Place to save freed lang_decls which were allocated on the
! permanent_obstack. */
! struct lang_decl *free_lang_decl_chain;
tree
build_lang_decl (code, name, type)
*************** retrofit_lang_decl (t)
*** 4737,4744 ****
tree t;
{
struct obstack *obstack = current_obstack;
! register int i = sizeof (struct lang_decl) / sizeof (int);
! register int *pi;
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
--- 4736,4742 ----
tree t;
{
struct obstack *obstack = current_obstack;
! struct lang_decl *ld;
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
*************** retrofit_lang_decl (t)
*** 4748,4767 ****
if (free_lang_decl_chain && obstack == &permanent_obstack)
{
! pi = (int *)free_lang_decl_chain;
! free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
}
else
! pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
! while (i > 0)
! pi[--i] = 0;
! DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
! LANG_DECL_PERMANENT ((struct lang_decl *) pi)
! = obstack == &permanent_obstack;
! my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
! == TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
DECL_LANGUAGE (t) = lang_cplusplus;
--- 4746,4763 ----
if (free_lang_decl_chain && obstack == &permanent_obstack)
{
! ld = free_lang_decl_chain;
! free_lang_decl_chain = free_lang_decl_chain->u.next;
}
else
! ld = ((struct lang_decl *)
! obstack_alloc (obstack, sizeof (struct lang_decl)));
! bzero (ld, sizeof (struct lang_decl));
! DECL_LANG_SPECIFIC (t) = ld;
! LANG_DECL_PERMANENT (ld) = obstack == &permanent_obstack;
! my_friendly_assert (LANG_DECL_PERMANENT (ld) == TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
DECL_LANGUAGE (t) = lang_cplusplus;
*************** retrofit_lang_decl (t)
*** 4771,4791 ****
DECL_LANGUAGE (t) = lang_java;
else my_friendly_abort (64);
- #if 0 /* not yet, should get fixed properly later */
- if (code == TYPE_DECL)
- {
- tree id;
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (t) = id;
- }
-
- #endif
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
}
tree
build_lang_field_decl (code, name, type)
enum tree_code code;
--- 4767,4781 ----
DECL_LANGUAGE (t) = lang_java;
else my_friendly_abort (64);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
}
+ /* Like build_decl, except that a new lang_decl_flags structure is
+ placed in DECL_LANG_SPECIFIC. */
+
tree
build_lang_field_decl (code, name, type)
enum tree_code code;
*************** build_lang_field_decl (code, name, type)
*** 4795,4822 ****
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = build_decl (code, name, type);
struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_decl_flags) / sizeof (int);
- register int *pi;
- #if 0 /* not yet, should get fixed properly later */
-
- if (code == TYPE_DECL)
- {
- tree id;
- id = get_identifier (build_overload_name (type, 1, 1));
- DECL_ASSEMBLER_NAME (t) = id;
- }
- #endif
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
else
my_friendly_assert (obstack == &permanent_obstack, 235);
-
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
- while (i > 0)
- pi[--i] = 0;
! DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
return t;
}
--- 4785,4800 ----
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = build_decl (code, name, type);
struct obstack *obstack = current_obstack;
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
else
my_friendly_assert (obstack == &permanent_obstack, 235);
! DECL_LANG_SPECIFIC (t)
! = ((struct lang_decl *)
! obstack_alloc (obstack, sizeof (struct lang_decl_flags)));
! bzero (DECL_LANG_SPECIFIC (t), sizeof (struct lang_decl_flags));
return t;
}
Index: cp/lex.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.h,v
retrieving revision 1.8
diff -c -p -r1.8 lex.h
*** lex.h 1999/08/11 20:22:27 1.8
--- lex.h 1999/08/14 09:04:40
*************** extern tree got_object;
*** 131,133 ****
--- 131,135 ----
extern int pending_lang_change;
extern int yylex PROTO((void));
+
+ extern struct lang_decl *free_lang_decl_chain;
Index: cp/parse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.c,v
retrieving revision 1.122
diff -c -p -r1.122 parse.c
*** parse.c 1999/08/12 01:45:34 1.122
--- parse.c 1999/08/14 09:04:44
*************** case 12:
*** 4444,4450 ****
break;}
case 13:
#line 386 "parse.y"
! { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
pop_everything (); ;
break;}
case 14:
--- 4444,4450 ----
break;}
case 13:
#line 386 "parse.y"
! { if (! toplevel_bindings_p ())
pop_everything (); ;
break;}
case 14:
Index: cp/parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.132
diff -c -p -r1.132 parse.y
*** parse.y 1999/08/12 01:45:33 1.132
--- parse.y 1999/08/14 09:04:46
*************** asm_keyword:
*** 383,389 ****
lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); }
extdef
! { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
pop_everything (); }
;
--- 383,389 ----
lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); }
extdef
! { if (! toplevel_bindings_p ())
pop_everything (); }
;
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.326
diff -c -p -r1.326 pt.c
*** pt.c 1999/08/13 08:17:14 1.326
--- pt.c 1999/08/14 09:04:52
*************** static tree build_template_parm_index PR
*** 123,129 ****
--- 123,131 ----
static int inline_needs_template_parms PROTO((tree));
static void push_inline_template_parms_recursive PROTO((tree, int));
static tree retrieve_specialization PROTO((tree, tree));
+ static tree retrieve_local_specialization PROTO((tree, tree));
static tree register_specialization PROTO((tree, tree, tree));
+ static tree register_local_specialization PROTO((tree, tree, tree));
static int unregister_specialization PROTO((tree, tree));
static tree reduce_template_parm_level PROTO((tree, tree, int));
static tree build_template_decl PROTO((tree, tree));
*************** static int coerce_template_template_parm
*** 160,165 ****
--- 162,168 ----
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 void tsubst_default_arguments PROTO((tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
*************** retrieve_specialization (tmpl, args)
*** 756,761 ****
--- 759,776 ----
return NULL_TREE;
}
+ /* Like retrieve_speciailization, but for local declarations. FN is
+ the function in which we are looking for an instantiation. */
+
+ static tree
+ retrieve_local_specialization (tmpl, fn)
+ tree tmpl;
+ tree fn;
+ {
+ tree s = purpose_member (fn, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ return s ? TREE_VALUE (s) : NULL_TREE;
+ }
+
/* Returns non-zero iff DECL is a specialization of TMPL. */
int
*************** unregister_specialization (spec, tmpl)
*** 911,916 ****
--- 926,947 ----
return 0;
}
+ /* Like register_specialization, but for local declarations. FN is
+ the function in which we are registering SPEC, an instantiation of
+ TMPL. */
+
+ static tree
+ register_local_specialization (spec, tmpl, fn)
+ tree spec;
+ tree tmpl;
+ tree fn;
+ {
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = perm_tree_cons (fn, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+
+ return spec;
+ }
+
/* Print the list of candidate FNS in an error message. */
void
*************** push_template_decl_real (decl, is_friend
*** 2356,2362 ****
int is_partial;
/* See if this is a partial specialization. */
! is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
--- 2387,2393 ----
int is_partial;
/* See if this is a partial specialization. */
! is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
*************** push_template_decl_real (decl, is_friend
*** 2374,2380 ****
else
/* Otherwise, if we're currently definining some class, the DECL
is assumed to be a member of the class. */
! ctx = current_class_type;
if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
ctx = NULL_TREE;
--- 2405,2411 ----
else
/* Otherwise, if we're currently definining some class, the DECL
is assumed to be a member of the class. */
! ctx = current_scope ();
if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
ctx = NULL_TREE;
*************** push_template_decl_real (decl, is_friend
*** 2382,2403 ****
if (!DECL_CONTEXT (decl))
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
- /* For determining whether this is a primary template or not, we're really
- interested in the lexical context, not the true context. */
- if (is_friend)
- info = current_class_type;
- else
- info = ctx;
-
/* See if this is a primary template. */
! if (info && TREE_CODE (info) == FUNCTION_DECL)
! primary = 0;
! /* Note that template_class_depth returns 0 if given NULL_TREE, so
! this next line works even when we are at global scope. */
! else if (processing_template_decl > template_class_depth (info))
! primary = 1;
! else
! primary = 0;
if (primary)
{
--- 2413,2420 ----
if (!DECL_CONTEXT (decl))
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
! primary = pseudo_global_level_p ();
if (primary)
{
*************** push_template_decl_real (decl, is_friend
*** 2552,2558 ****
info = perm_tree_cons (tmpl, args, NULL_TREE);
! if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
--- 2569,2575 ----
info = perm_tree_cons (tmpl, args, NULL_TREE);
! if (DECL_IMPLICIT_TYPEDEF_P (decl))
{
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
*************** lookup_template_class (d1, arglist, in_d
*** 3938,3953 ****
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
! /* Create a stub TYPE_DECL for it. */
! type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
! SET_DECL_ARTIFICIAL (type_decl);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
!
DECL_SOURCE_FILE (type_decl)
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
DECL_SOURCE_LINE (type_decl)
= DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
- TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
}
else
type_decl = TYPE_NAME (t);
--- 3955,3967 ----
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
! type_decl = create_implicit_typedef (DECL_NAME (template), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
! TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_FILE (type_decl)
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
DECL_SOURCE_LINE (type_decl)
= DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
}
else
type_decl = TYPE_NAME (t);
*************** instantiate_class_template (type)
*** 5063,5084 ****
}
}
- /* Create the typedef that indicates provides a way of referencing a
- class name within the scope of that class. */
- build_self_reference ();
-
/* Don't replace enum constants here. */
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
! /* If this is the implicit self-reference typedef, skip it, as we
! have handled it above. Note that the usual tsubst machinery
! doesn't work here, since the resulting declaration must have a
! different name than the one it was given originally. */
! if (TREE_CODE (t) == TYPE_DECL
! && TREE_TYPE (t) == pattern
! && DECL_NAME (t) == constructor_name (t)
! && DECL_ARTIFICIAL (t))
! continue;
! else if (TREE_CODE (t) != CONST_DECL)
{
tree r;
--- 5077,5085 ----
}
}
/* Don't replace enum constants here. */
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
! if (TREE_CODE (t) != CONST_DECL)
{
tree r;
*************** instantiate_class_template (type)
*** 5212,5217 ****
--- 5213,5230 ----
TYPE_BEING_DEFINED (type) = 0;
repo_template_used (type);
+ /* Now that the class is complete, instantiate default arguments for
+ any member functions. We don't do this earlier because the
+ default arguments may reference members of the class. */
+ if (!PRIMARY_TEMPLATE_P (template))
+ for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == FUNCTION_DECL
+ /* Implicitly generated member functions will not have tmplate
+ information; they are not instantiations, but instead are
+ created "fresh" for each instantiation. */
+ && DECL_TEMPLATE_INFO (t))
+ tsubst_default_arguments (t);
+
popclass ();
pop_from_top_level ();
pop_tinst_level ();
*************** tsubst_aggr_type (t, args, complain, in_
*** 5436,5441 ****
--- 5449,5514 ----
}
}
+ /* Substitute into the default argument ARG (a default argument for
+ FN), which has the indicated TYPE. */
+
+ tree
+ tsubst_default_argument (fn, type, arg)
+ tree fn;
+ tree type;
+ tree arg;
+ {
+ /* This default argument came from a template. Instantiate the
+ default argument here, not in tsubst. In the case of
+ something like:
+
+ template <class T>
+ struct S {
+ static T t();
+ void f(T = t());
+ };
+
+ we must be careful to do name lookup in the scope of S<T>,
+ rather than in the current class. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+ arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
+
+ if (DECL_CLASS_SCOPE_P (fn))
+ popclass ();
+
+ /* Make sure the default argument is reasonable. */
+ arg = check_default_argument (type, arg);
+
+ return arg;
+ }
+
+ /* Substitute into all the default arguments for FN. */
+
+ static void
+ tsubst_default_arguments (fn)
+ tree fn;
+ {
+ tree arg;
+ tree tmpl_args;
+
+ tmpl_args = DECL_TI_ARGS (fn);
+
+ /* If this function is not yet instantiated, we certainly don't need
+ its default arguments. */
+ if (uses_template_parms (tmpl_args))
+ return;
+
+ for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ arg;
+ arg = TREE_CHAIN (arg))
+ if (TREE_PURPOSE (arg))
+ TREE_PURPOSE (arg) = tsubst_default_argument (fn,
+ TREE_VALUE (arg),
+ TREE_PURPOSE (arg));
+ }
+
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
(already computed) substitution of ARGS into TREE_TYPE (T), if
appropriate. Return the result of the substitution. IN_DECL is as
*************** tsubst_decl (t, args, type, in_decl)
*** 5823,5828 ****
--- 5896,5917 ----
&& (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
+
+ /* We're not supposed to instantiate default arguments
+ until they are called, for a template. But, for a
+ declaration like:
+
+ template <class T> void f ()
+ { extern void g(int i = T()); }
+
+ we should do the substitution when the template is
+ instantiated. We handle the member function case in
+ instantiate_class_template since the default arguments
+ might refer to other members of the class. */
+ if (!member
+ && !PRIMARY_TEMPLATE_P (gen_tmpl)
+ && !uses_template_parms (argvec))
+ tsubst_default_arguments (r);
}
/* Copy the list of befriending classes. */
*************** tsubst_decl (t, args, type, in_decl)
*** 5896,5903 ****
}
break;
- case VAR_DECL:
case TYPE_DECL:
{
tree argvec;
tree gen_tmpl;
--- 5985,6011 ----
}
break;
case TYPE_DECL:
+ if (DECL_IMPLICIT_TYPEDEF_P (t))
+ {
+ /* For an implicit typedef, we just want the implicit
+ typedef for the tsubst'd type. We've already got the
+ tsubst'd type, as TYPE, so we just need it's associated
+ declaration. */
+ r = TYPE_NAME (type);
+ break;
+ }
+ else if (!DECL_LANG_SPECIFIC (t))
+ {
+ /* For a template type parameter, we don't have to do
+ anything special. */
+ r= TYPE_NAME (type);
+ break;
+ }
+
+ /* Fall through. */
+
+ case VAR_DECL:
{
tree argvec;
tree gen_tmpl;
*************** tsubst_decl (t, args, type, in_decl)
*** 5905,5912 ****
tree tmpl;
tree ctx;
! if (!DECL_LANG_SPECIFIC (t) || !DECL_TEMPLATE_INFO (t))
! return t;
if (TYPE_P (DECL_CONTEXT (t)))
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
--- 6013,6020 ----
tree tmpl;
tree ctx;
! my_friendly_assert (DECL_LANG_SPECIFIC (t) &&
! DECL_TEMPLATE_INFO (t), 0);
if (TYPE_P (DECL_CONTEXT (t)))
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
*************** tsubst_decl (t, args, type, in_decl)
*** 5920,5927 ****
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
! spec = retrieve_specialization (gen_tmpl, argvec);
!
if (spec)
{
r = spec;
--- 6028,6039 ----
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
! if (ctx)
! spec = retrieve_specialization (gen_tmpl, argvec);
! else
! spec = retrieve_local_specialization (gen_tmpl,
! current_function_decl);
!
if (spec)
{
r = spec;
*************** tsubst_decl (t, args, type, in_decl)
*** 5960,5969 ****
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
! register_specialization (r, gen_tmpl, argvec);
TREE_CHAIN (r) = NULL_TREE;
! if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
}
break;
--- 6072,6085 ----
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
! if (ctx)
! register_specialization (r, gen_tmpl, argvec);
! else
! register_local_specialization (r, gen_tmpl,
! current_function_decl);
TREE_CHAIN (r) = NULL_TREE;
! if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
}
break;
*************** tsubst_copy (t, args, complain, in_decl)
*** 6776,6790 ****
return t;
/* Unfortunately, we cannot just call lookup_name here.
! Consider:
!
! template <int I> int f() {
! enum E { a = I };
! struct S { void g() { E e = a; } };
! };
!
! When we instantiate f<7>::S::g(), say, lookup_name is not
! clever enough to find f<7>::a. */
enum_type
= tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
/*entering_scope=*/0);
--- 6892,6906 ----
return t;
/* Unfortunately, we cannot just call lookup_name here.
! Consider:
!
! template <int I> int f() {
! enum E { a = I };
! struct S { void g() { E e = a; } };
! };
!
! When we instantiate f<7>::S::g(), say, lookup_name is not
! clever enough to find f<7>::a. */
enum_type
= tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
/*entering_scope=*/0);
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.117
diff -c -p -r1.117 search.c
*** search.c 1999/08/11 20:22:38 1.117
--- search.c 1999/08/14 09:04:54
*************** current_scope ()
*** 622,627 ****
--- 622,638 ----
return current_class_type;
}
+ /* Returns non-zero if we are currently in a function scope. Note
+ that this function returns zero if we are within a local class, but
+ not within a member function body of the local class. */
+
+ int
+ at_function_scope_p ()
+ {
+ tree cs = current_scope ();
+ return cs && TREE_CODE (cs) == FUNCTION_DECL;
+ }
+
/* Return the scope of DECL, as appropriate when doing name-lookup. */
static tree
*************** lookup_field_queue_p (binfo, data)
*** 1212,1220 ****
return binfo;
}
! /* Within the scope of a template class, you can refer to the
! particular to the current specialization with the name of the
! template itself. For example:
template <typename T> struct S { S* sp; }
--- 1223,1231 ----
return binfo;
}
! /* Within the scope of a template class, you can refer to the to the
! current specialization with the name of the template itself. For
! example:
template <typename T> struct S { S* sp; }
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.58
diff -c -p -r1.58 semantics.c
*** semantics.c 1999/08/12 01:45:44 1.58
--- semantics.c 1999/08/14 09:04:55
*************** finish_asm_stmt (cv_qualifier, string, o
*** 780,791 ****
if (TREE_CHAIN (string))
{
if (processing_template_decl)
! {
! /* We need to build the combined string on the permanent
! obstack so that we can use it during instantiations. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
! }
string = combine_strings (string);
--- 780,788 ----
if (TREE_CHAIN (string))
{
if (processing_template_decl)
! /* We need to build the combined string on the permanent
! obstack so that we can use it during instantiations. */
! push_permanent_obstack ();
string = combine_strings (string);
*************** finish_label_stmt (name)
*** 842,849 ****
if (processing_template_decl)
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
decl = build_decl (LABEL_DECL, name, void_type_node);
pop_obstacks ();
DECL_SOURCE_LINE (decl) = lineno;
--- 839,845 ----
if (processing_template_decl)
{
! push_permanent_obstack ();
decl = build_decl (LABEL_DECL, name, void_type_node);
pop_obstacks ();
DECL_SOURCE_LINE (decl) = lineno;
*************** finish_label_stmt (name)
*** 858,863 ****
--- 854,874 ----
}
}
+ /* Create a declaration statement for the declaration given by the
+ DECL. */
+
+ void
+ add_decl_stmt (decl)
+ tree decl;
+ {
+ tree decl_stmt;
+
+ /* We need the type to last until instantiation time. */
+ TREE_TYPE (decl) = copy_to_permanent (TREE_TYPE (decl));
+ decl_stmt = build_min_nt (DECL_STMT, decl);
+ add_tree (decl_stmt);
+ }
+
/* Finish a parenthesized expression EXPR. */
tree
*************** tree
*** 1302,1310 ****
begin_class_definition (t)
tree t;
{
! push_obstacks_nochange ();
! end_temporary_allocation ();
!
if (t == error_mark_node
|| ! IS_AGGR_TYPE (t))
{
--- 1313,1320 ----
begin_class_definition (t)
tree t;
{
! push_permanent_obstack ();
!
if (t == error_mark_node
|| ! IS_AGGR_TYPE (t))
{
*************** finish_typeof (expr)
*** 1725,1737 ****
if (processing_template_decl)
{
tree t;
-
- push_obstacks_nochange ();
- end_temporary_allocation ();
t = make_lang_type (TYPEOF_TYPE);
TYPE_FIELDS (t) = expr;
-
pop_obstacks ();
return t;
--- 1735,1744 ----
if (processing_template_decl)
{
tree t;
+ push_permanent_obstack ();
t = make_lang_type (TYPEOF_TYPE);
TYPE_FIELDS (t) = expr;
pop_obstacks ();
return t;
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.127
diff -c -p -r1.127 tree.c
*** tree.c 1999/08/11 20:22:39 1.127
--- tree.c 1999/08/14 09:04:56
*************** build_cplus_array_type_1 (elt_type, inde
*** 442,448 ****
push_obstacks_nochange ();
! /* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent,
make this permanent too. */
if (TREE_PERMANENT (elt_type)
&& (index_type == 0 || TREE_PERMANENT (index_type)))
--- 442,448 ----
push_obstacks_nochange ();
! /* If both ELT_TYPE and INDEX_TYPE are permanent,
make this permanent too. */
if (TREE_PERMANENT (elt_type)
&& (index_type == 0 || TREE_PERMANENT (index_type)))
*************** copy_template_template_parm (t)
*** 1533,1540 ****
tree t2;
/* Make sure these end up on the permanent_obstack. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
--- 1533,1539 ----
tree t2;
/* Make sure these end up on the permanent_obstack. */
! push_permanent_obstack ();
t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
*************** copy_to_permanent (t)
*** 2086,2096 ****
if (t == NULL_TREE || TREE_PERMANENT (t))
return t;
! push_obstacks_nochange ();
! end_temporary_allocation ();
!
t = mapcar (t, perm_manip);
-
pop_obstacks ();
return t;
--- 2085,2092 ----
if (t == NULL_TREE || TREE_PERMANENT (t))
return t;
! push_permanent_obstack ();
t = mapcar (t, perm_manip);
pop_obstacks ();
return t;
*************** push_expression_obstack ()
*** 2620,2625 ****
--- 2616,2632 ----
{
push_obstacks_nochange ();
current_obstack = expression_obstack;
+ }
+
+ /* Begin allocating on the permanent obstack. When you're done
+ allocating there, call pop_obstacks to return to the previous set
+ of obstacks. */
+
+ void
+ push_permanent_obstack ()
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
}
/* The type of ARG when used as an lvalue. */
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.191
diff -c -p -r1.191 typeck.c
*** typeck.c 1999/08/11 20:22:39 1.191
--- typeck.c 1999/08/14 09:05:00
*************** mark_addressable (exp)
*** 5082,5089 ****
{
/* We thought this would make a good constant variable,
but we were wrong. */
! push_obstacks_nochange ();
! end_temporary_allocation ();
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;
--- 5082,5088 ----
{
/* We thought this would make a good constant variable,
but we were wrong. */
! push_permanent_obstack ();
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;