Patch for local classes
Mark Mitchell
mmitchell@usa.net
Sun Jan 11 19:17:00 GMT 1998
The attached patch improves support for local classes, and fixes a few
other issues. In partciular,
o Member functions of local classes are now given internal linkage.
This avoids the bug that resulted from:
test1.C
-------
static void f() { struct S { int g() {} }; }
test2.C
-------
static void f() { struct S { int g() {} }; }
int main() {}
supernova% g++ test1.C test2.C
/tmp/cca128672.o: In function `f__Fv.0::S::g(void)':
/tmp/cca128672.o(.text+0x0): multiple definition of `f__Fv.0::S::g(void)'
/tmp/cca128671.o(.text+0x0): first defined here
o The linkage specifiers on template declarations are now obeyed, as
required in the standard. So, for example, on:
test.C
------
template <class T> static void f(T t) {}
void g() { f(3); }
we used to give:
supernova% g++ -c test.C
supernova% nm test.o
00000000 W f__H1Zi_X01_v
and now give:
supernova% test-g++ -c test.C
supernova% nm test.o
00000018 t f__H1Zi_X01_v
o Local classes in template functions are now implemented, and seem
to work at least in the simple cases. This fixes the internal
errors reported by Raymond Nijssen on 12/19 and Hans-Helmut
Buehmann in http://www.cygnus.com/ml/egcs-bugs/1997-Dec/0423.html .
The patch below may not apply directly to the latest snapshot, but
should apply after the other patches I have submitted. (Not all of
these made it to the list.)
--
Mark Mitchell mmitchell@usa.net
Stanford University http://www.stanford.edu
Index: gcc/cp/class.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/class.c,v
retrieving revision 1.2
diff -c -p -r1.2 class.c
*** class.c 1998/01/01 01:17:05 1.2
--- class.c 1998/01/11 23:31:53
*************** build_self_reference ()
*** 5511,5513 ****
--- 5511,5531 ----
pushdecl_class_level (value);
return value;
}
+
+
+ /* Returns non-zero iff the TYPE is a local class; i.e., if it is
+ declared in a function context, or within a local class. */
+
+ int
+ is_local_class (type)
+ tree type;
+ {
+ if (type == NULL_TREE || TYPE_CONTEXT (type) == NULL_TREE)
+ return 0;
+
+ if (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
+ return 1;
+
+ return is_local_class (TYPE_CONTEXT (type));
+ }
+
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.6
diff -c -p -r1.6 cp-tree.h
*** cp-tree.h 1998/01/01 01:17:06 1.6
--- cp-tree.h 1998/01/11 22:02:06
*************** extern tree null_node;
*** 1537,1542 ****
--- 1537,1543 ----
extern tree current_template_parms;
extern HOST_WIDE_INT processing_template_decl;
+ extern tree last_tree;
/* The template currently being instantiated, and where the instantiation
was triggered. */
*************** extern void maybe_push_cache_obstack PR
*** 1981,1986 ****
--- 1982,1988 ----
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
extern tree build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree));
+ extern int is_local_class PROTO((tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
*************** extern tree end_template_parm_list PROT
*** 2325,2331 ****
extern void end_template_decl PROTO((void));
extern tree current_template_args PROTO((void));
extern void push_template_decl PROTO((tree));
! extern tree lookup_template_class PROTO((tree, tree, tree));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
--- 2327,2333 ----
extern void end_template_decl PROTO((void));
extern tree current_template_args PROTO((void));
extern void push_template_decl PROTO((tree));
! extern tree lookup_template_class PROTO((tree, tree, tree, tree));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
*************** extern tree do_poplevel PROTO((void))
*** 2345,2350 ****
--- 2347,2354 ----
extern tree get_bindings PROTO((tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
+ extern void begin_tree PROTO((void));
+ extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void));
extern tree most_specialized PROTO((tree, tree));
Index: gcc/cp/decl.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl.c,v
retrieving revision 1.12
diff -c -p -r1.12 decl.c
*** decl.c 1998/01/07 07:39:42 1.12
--- decl.c 1998/01/12 02:19:38
*************** cp_finish_decl (decl, init, asmspec_tree
*** 6468,6476 ****
if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
{
tree stmt = DECL_VINDEX (decl);
! DECL_VINDEX (decl) = NULL_TREE;
! TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! add_tree (stmt);
}
goto finish_end0;
--- 6468,6479 ----
if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
{
tree stmt = DECL_VINDEX (decl);
! if (stmt != NULL_TREE)
! {
! DECL_VINDEX (decl) = NULL_TREE;
! TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! add_tree (stmt);
! }
}
goto finish_end0;
*************** cp_finish_decl (decl, init, asmspec_tree
*** 6756,6762 ****
|| 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 ());
--- 6759,6769 ----
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
! /* We check for FUNCTION_DECL here so that member functions of
! local classes, which will have internal linkage, are not
! given bizarre names by make_decl_rtl. */
! int toplev = toplevel_bindings_p () || pseudo_global_level_p ()
! || TREE_CODE (decl) == FUNCTION_DECL;
int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
*************** grokdeclarator (declarator, declspecs, d
*** 9685,9691 ****
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
! publicp = (! friendp || ! staticp);
decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
--- 9692,9698 ----
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
! publicp = (! friendp || ! staticp) && !is_local_class (ctype);
decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
*************** start_function (declspecs, declarator, a
*** 11730,11736 ****
if (processing_template_decl)
{
- extern tree last_tree;
++minimal_parse_mode;
last_tree = DECL_SAVED_TREE (decl1)
= build_nt (EXPR_STMT, void_zero_node);
--- 11737,11742 ----
*************** finish_function (lineno, call_poplevel,
*** 12454,12462 ****
--- 12460,12480 ----
if (! processing_template_decl)
{
+ int saved_flag_keep_inline_functions =
+ flag_keep_inline_functions;
+
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
+ if (DECL_CONTEXT (fndecl) != NULL_TREE
+ && is_local_class (DECL_CONTEXT (fndecl)))
+ /* Trick rest_of_compilation into not deferring output of this
+ function, even if it is inline, since the rtl_obstack for
+ this function is the function_obstack of the enclosing
+ function and will be deallocated when the enclosing
+ function is gone. See save_tree_status. */
+ flag_keep_inline_functions = 1;
+
/* Run the optimizers and output the assembler code for this
function. */
*************** finish_function (lineno, call_poplevel,
*** 12477,12482 ****
--- 12495,12502 ----
else
rest_of_compilation (fndecl);
+ flag_keep_inline_functions = saved_flag_keep_inline_functions;
+
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{
/* Set DECL_EXTERNAL so that assemble_external will be called as
*************** start_method (declspecs, declarator)
*** 12622,12628 ****
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
! if (processing_template_decl && ! current_function_decl)
push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
--- 12642,12648 ----
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
! if (processing_template_decl)
push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
Index: gcc/cp/decl2.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl2.c,v
retrieving revision 1.1.1.7
diff -c -p -r1.1.1.7 decl2.c
*** decl2.c 1998/01/01 01:04:29 1.1.1.7
--- decl2.c 1998/01/11 23:20:14
*************** import_export_decl (decl)
*** 2788,2794 ****
if (DECL_IMPLICIT_INSTANTIATION (decl)
&& (flag_implicit_templates || DECL_THIS_INLINE (decl)))
{
! if (TREE_CODE (decl) == FUNCTION_DECL)
comdat_linkage (decl);
else
DECL_COMDAT (decl) = 1;
--- 2788,2798 ----
if (DECL_IMPLICIT_INSTANTIATION (decl)
&& (flag_implicit_templates || DECL_THIS_INLINE (decl)))
{
! if (!TREE_PUBLIC (decl))
! /* Templates are allowed to have internal linkage. See
! [basic.link]. */
! ;
! else if (TREE_CODE (decl) == FUNCTION_DECL)
comdat_linkage (decl);
else
DECL_COMDAT (decl) = 1;
Index: gcc/cp/parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.7
diff -c -p -r1.7 parse.y
*** parse.y 1998/01/01 01:17:14 1.7
--- parse.y 1998/01/11 21:44:11
*************** extern int errno;
*** 56,62 ****
extern int end_of_file;
extern int current_class_depth;
- extern tree last_tree;
/* FSF LOCAL dje prefix attributes */
extern tree strip_attrs PROTO((tree));
--- 56,61 ----
*************** end_explicit_instantiation:
*** 900,912 ****
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| TYPENAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
--- 899,911 ----
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| TYPENAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
*************** template_type:
*** 916,922 ****
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
--- 915,921 ----
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
{
! $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
*************** structsp:
*** 2269,2275 ****
$$.new_type_flag = 0; }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly
- { reset_specialization(); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
--- 2268,2273 ----
*************** structsp:
*** 2293,2299 ****
;
else
{
! $<ttype>$ = finish_struct ($1, $4, $6, semi);
if (semi) note_got_semicolon ($<ttype>$);
}
--- 2291,2297 ----
;
else
{
! $<ttype>$ = finish_struct ($1, $3, $5, semi);
if (semi) note_got_semicolon ($<ttype>$);
}
*************** structsp:
*** 2312,2321 ****
}
pending_inlines
{
! $$.t = $<ttype>7;
$$.new_type_flag = 1;
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
}
| class_head %prec EMPTY
{
--- 2310,2322 ----
}
pending_inlines
{
! $$.t = $<ttype>6;
$$.new_type_flag = 1;
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
+
+ /* Undo the begin_tree in left_curly. */
+ end_tree ();
}
| class_head %prec EMPTY
{
*************** left_curly:
*** 2678,2683 ****
--- 2679,2690 ----
if (t && IDENTIFIER_TEMPLATE (t))
overload_template_name (t, 1);
#endif
+ reset_specialization();
+
+ /* In case this is a local class within a template
+ function, we save the current tree structure so
+ that we can get it back later. */
+ begin_tree ();
}
;
Index: gcc/cp/pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.12
diff -c -p -r1.12 pt.c
*** pt.c 1998/01/06 23:12:15 1.12
--- pt.c 1998/01/12 03:03:48
*************** int processing_specialization;
*** 64,69 ****
--- 64,71 ----
int processing_explicit_instantiation;
static int template_header_count;
+ static tree saved_trees;
+
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
*************** static int unify PROTO((tree, tree *, in
*** 71,77 ****
static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name PROTO((tree));
! static char *mangle_class_name_for_template PROTO((char *, tree, tree));
static tree tsubst_expr_values PROTO((tree, tree));
static int comp_template_args PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
--- 73,79 ----
static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name PROTO((tree));
! static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
static tree tsubst_expr_values PROTO((tree, tree));
static int comp_template_args PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
*************** push_template_decl (decl)
*** 1154,1160 ****
args = current_template_args ();
! if (! ctx || TYPE_BEING_DEFINED (ctx))
{
tmpl = build_template_decl (decl, current_template_parms);
--- 1156,1163 ----
args = current_template_args ();
! if (! ctx || TREE_CODE (ctx) == FUNCTION_DECL
! || TYPE_BEING_DEFINED (ctx))
{
tmpl = build_template_decl (decl, current_template_parms);
*************** push_template_decl (decl)
*** 1273,1279 ****
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
! DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (! DECL_LANG_SPECIFIC (decl))
cp_error ("template declaration of `%#D'", decl);
--- 1276,1283 ----
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
! if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
! DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (! DECL_LANG_SPECIFIC (decl))
cp_error ("template declaration of `%#D'", decl);
*************** convert_nontype_parameter (type, expr)
*** 1575,1580 ****
--- 1579,1593 ----
expr_type != unknown_type_node)
return error_mark_node;
+ if (TREE_CODE (expr) == CONSTRUCTOR)
+ {
+ /* A ptr-to-member constant. */
+ if (!comptypes (type, expr_type, 1))
+ return error_mark_node;
+ else
+ return expr;
+ }
+
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
*************** comp_template_args (oldargs, newargs)
*** 1835,1843 ****
for the instantiation. */
static char *
! mangle_class_name_for_template (name, parms, arglist)
char *name;
tree parms, arglist;
{
static struct obstack scratch_obstack;
static char *scratch_firstobj;
--- 1848,1857 ----
for the instantiation. */
static char *
! mangle_class_name_for_template (name, parms, arglist, ctx)
char *name;
tree parms, arglist;
+ tree ctx;
{
static struct obstack scratch_obstack;
static char *scratch_firstobj;
*************** mangle_class_name_for_template (name, pa
*** 1862,1867 ****
--- 1876,1887 ----
#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
#endif
+ if (ctx)
+ {
+ char* s = fndecl_as_string(ctx, 0);
+ cat (s);
+ cat ("::");
+ }
cat (name);
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
*************** classtype_mangled_name (t)
*** 1927,1933 ****
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
return id;
--- 1947,1955 ----
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! CLASSTYPE_TI_ARGS (t),
! (DECL_CONTEXT (t) && TREE_CODE (t) == FUNCTION_DECL) ?
! DECL_CONTEXT (t) : NULL_TREE);
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
return id;
*************** lookup_template_function (fns, arglist)
*** 1989,2000 ****
to keep it from being reclaimed when the decl storage is reclaimed.
IN_DECL, if non-NULL, is the template declaration we are trying to
! instantiate. */
tree
! lookup_template_class (d1, arglist, in_decl)
tree d1, arglist;
tree in_decl;
{
tree template, parmlist;
char *mangled_name;
--- 2011,2027 ----
to keep it from being reclaimed when the decl storage is reclaimed.
IN_DECL, if non-NULL, is the template declaration we are trying to
! instantiate.
!
! If the template class is really a local class in a template
! function, then the FUNCTION_CONTEXT is the function in which it is
! being instantiated. */
tree
! lookup_template_class (d1, arglist, in_decl, function_context)
tree d1, arglist;
tree in_decl;
+ tree function_context;
{
tree template, parmlist;
char *mangled_name;
*************** lookup_template_class (d1, arglist, in_d
*** 2069,2086 ****
}
mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
! parmlist, arglist);
id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = d1;
maybe_push_to_top_level (uses_template_parms (arglist));
t = xref_tag_from_type (TREE_TYPE (template), id, 1);
pop_from_top_level ();
}
else
{
tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
! arglist, in_decl);
id = d1;
arglist = CLASSTYPE_TI_ARGS (ctx);
--- 2096,2130 ----
}
mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
! parmlist,
! arglist,
! function_context);
id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = d1;
maybe_push_to_top_level (uses_template_parms (arglist));
t = xref_tag_from_type (TREE_TYPE (template), id, 1);
+
+ if (function_context != NULL_TREE)
+ {
+ /* Set up the context for the type_decl correctly. Note
+ that we must clear DECL_ASSEMBLER_NAME to fool
+ build_overload_name into creating a new name. */
+ tree type_decl = TYPE_STUB_DECL (t);
+
+ TYPE_CONTEXT (t) = function_context;
+ DECL_CONTEXT (type_decl) = function_context;
+ DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
+ DECL_ASSEMBLER_NAME (type_decl) =
+ get_identifier (build_overload_name (t, 1, 1));
+ }
+
pop_from_top_level ();
}
else
{
tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
! arglist, in_decl, NULL_TREE);
id = d1;
arglist = CLASSTYPE_TI_ARGS (ctx);
*************** tsubst (t, args, nargs, in_decl)
*** 2758,2764 ****
if (uses_template_parms (t))
{
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
! tree r = lookup_template_class (t, argvec, in_decl);
return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t));
}
--- 2802,2816 ----
if (uses_template_parms (t))
{
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
! tree context;
! tree r;
!
! context = (TYPE_CONTEXT (t)
! && TREE_CODE (TYPE_CONTEXT (t)) == FUNCTION_DECL)
! ? tsubst (TYPE_CONTEXT (t), args, nargs, in_decl) : NULL_TREE;
!
! r = lookup_template_class (t, argvec, in_decl, context);
!
return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t));
}
*************** tsubst (t, args, nargs, in_decl)
*** 3142,3148 ****
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
! TREE_PUBLIC (r) = 1;
DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_DEFER_OUTPUT (r) = 0;
--- 3194,3200 ----
DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
! TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_DEFER_OUTPUT (r) = 0;
*************** mark_decl_instantiated (result, extern_p
*** 4771,4777 ****
{
if (DECL_TEMPLATE_INSTANTIATION (result))
SET_DECL_EXPLICIT_INSTANTIATION (result);
! TREE_PUBLIC (result) = 1;
if (! extern_p)
{
--- 4823,4833 ----
{
if (DECL_TEMPLATE_INSTANTIATION (result))
SET_DECL_EXPLICIT_INSTANTIATION (result);
!
! if (TREE_CODE (result) != FUNCTION_DECL)
! /* The TREE_PUBLIC flag for function declarations will have been
! set correctly by tsubst. */
! TREE_PUBLIC (result) = 1;
if (! extern_p)
{
*************** mark_decl_instantiated (result, extern_p
*** 4780,4786 ****
/* For WIN32 we also want to put explicit instantiations in
linkonce sections. */
! if (supports_one_only () && ! SUPPORTS_WEAK)
make_decl_one_only (result);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
--- 4836,4842 ----
/* For WIN32 we also want to put explicit instantiations in
linkonce sections. */
! if (supports_one_only () && ! SUPPORTS_WEAK && TREE_PUBLIC (result))
make_decl_one_only (result);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
*************** add_tree (t)
*** 5462,5467 ****
--- 5518,5541 ----
tree t;
{
last_tree = TREE_CHAIN (last_tree) = t;
+ }
+
+
+ void
+ begin_tree ()
+ {
+ saved_trees = tree_cons (NULL_TREE, last_tree, saved_trees);
+ last_tree = NULL_TREE;
+ }
+
+
+ void
+ end_tree ()
+ {
+ my_friendly_assert (saved_trees != NULL_TREE, 0);
+
+ last_tree = TREE_VALUE (saved_trees);
+ saved_trees = TREE_CHAIN (saved_trees);
}
/* D is an undefined function declaration in the presence of templates with
Index: gcc/testsuite/g++.old-deja/g++.mike/p5840.C
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/testsuite/g++.old-deja/g++.mike/p5840.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 p5840.C
*** p5840.C 1997/11/08 17:54:14 1.1.1.1
--- p5840.C 1998/01/12 02:00:12
*************** public:
*** 17,33 ****
int value (Foo* a) { return (a->*Id)(); }
};
! template class Bar <Derived, &Signal::Name>;
template class Bar <Signal, &Signal::Name>;
template class Bar <Derived, &Derived::Name>;
Derived a;
! Bar<Derived, &Signal::Name> dispatcher1;
Bar<Derived, &Derived::Name> dispatcher2;
main() {
! int i1 = dispatcher1.value(&a);
int i2 = dispatcher2.value(&a);
! return i1 != 1 || i2 != 2;
}
--- 17,35 ----
int value (Foo* a) { return (a->*Id)(); }
};
! /* The following line is illegal under the new rules for non-type
! template arguments in the standard, so it is commented out. */
! /* template class Bar <Derived, &Signal::Name>; */
template class Bar <Signal, &Signal::Name>;
template class Bar <Derived, &Derived::Name>;
Derived a;
! /* Bar<Derived, &Signal::Name> dispatcher1; */
Bar<Derived, &Derived::Name> dispatcher2;
main() {
! /* int i1 = dispatcher1.value(&a); */
int i2 = dispatcher2.value(&a);
! return /* i1 != 1 || */ i2 != 2;
}
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.niklas
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.other
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.pt
Index: gcc/testsuite/g++.old-deja/g++.pt/local1.C
===================================================================
RCS file: local1.C
diff -N local1.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- local1.C Wed Jan 7 12:24:47 1998
***************
*** 0 ****
--- 1,21 ----
+ template <class STRUCT, class MEMBER> inline STRUCT *
+ setback(MEMBER *bp, MEMBER STRUCT::*offset)
+ {
+ if(!bp) return 0;
+ union { int i; MEMBER STRUCT::*of; } u;
+ u.of = offset;
+ return (STRUCT *) ((int) bp - u.i);
+ }
+
+
+ struct S
+ {
+ int i;
+ };
+
+ int main()
+ {
+ S s;
+
+ S* sp = setback (&s.i, &S::i);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local2.C
===================================================================
RCS file: local2.C
diff -N local2.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- local2.C Wed Jan 7 10:34:21 1998
***************
*** 0 ****
--- 1,20 ----
+ extern "C" void abort();
+
+ template <class T>
+ void f(T)
+ {
+ struct S {
+ int i;
+ } s;
+
+ s.i = 3;
+
+ if (s.i != 3)
+ abort();
+ }
+
+
+ int main()
+ {
+ f(7);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local3.C
===================================================================
RCS file: local3.C
diff -N local3.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- local3.C Wed Jan 7 11:09:39 1998
***************
*** 0 ****
--- 1,22 ----
+ extern "C" void abort();
+
+ template <class T>
+ void f(T)
+ {
+ struct S {
+ int i;
+ };
+
+ S s;
+
+ s.i = 3;
+
+ if (s.i != 3)
+ abort();
+ }
+
+
+ int main()
+ {
+ f(7);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local4.C
===================================================================
RCS file: local4.C
diff -N local4.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- local4.C Sun Jan 11 13:33:27 1998
***************
*** 0 ****
--- 1,25 ----
+ extern "C" void abort();
+
+ template <class T>
+ struct S {};
+
+ S<int> si;
+
+ template <class T>
+ int f(T t)
+ {
+ struct S {
+ int g(int i) { return i + 2; }
+ };
+
+ S s;
+
+ return s.g(t) + s.g(t);
+ }
+
+
+ int main()
+ {
+ if (f(3) != 10)
+ abort();
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local5.C
===================================================================
RCS file: local5.C
diff -N local5.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- local5.C Sun Jan 11 18:53:53 1998
***************
*** 0 ****
--- 1,24 ----
+ template <class INT>
+ class b
+ {
+ private:
+ char a(int x)
+ {
+ union {
+ int i;
+ char c;
+ } val;
+ val.i = x;
+ return val.c;
+ };
+
+ public:
+ b() {
+ }
+ };
+
+ int main() {
+ b<int> n;
+ return 0;
+ }
+
More information about the Gcc
mailing list