Index: objc/objc-act.c =================================================================== *** objc/objc-act.c (revision 117415) --- objc/objc-act.c (working copy) *************** objc_finish_file (void) *** 539,546 **** #ifdef OBJCPLUS /* We need to instantiate templates _before_ we emit ObjC metadata; if we do not, some metadata (such as selectors) may go missing. */ ! at_eof = 1; ! instantiate_pending_templates (0); #endif /* Finalize Objective-C runtime data. No need to generate tables --- 539,548 ---- #ifdef OBJCPLUS /* We need to instantiate templates _before_ we emit ObjC metadata; if we do not, some metadata (such as selectors) may go missing. */ ! { ! location_t locus; ! emit_instantiate_pending_templates (&locus); ! } #endif /* Finalize Objective-C runtime data. No need to generate tables Index: objc/objc-act.h =================================================================== *** objc/objc-act.h (revision 117415) --- objc/objc-act.h (working copy) *************** tree objc_get_callee_fndecl (tree); *** 33,38 **** --- 33,39 ---- void objc_finish_file (void); tree objc_fold_obj_type_ref (tree, tree); enum gimplify_status objc_gimplify_expr (tree *, tree *, tree *); + extern void emit_instantiate_pending_templates (location_t *); /* NB: The remaining public functions are prototyped in c-common.h, for the benefit of stub-objc.c and objc-act.c. */ Index: testsuite/obj-c++.dg/template-7.mm =================================================================== *** testsuite/obj-c++.dg/template-7.mm (revision 0) --- testsuite/obj-c++.dg/template-7.mm (revision 0) *************** *** 0 **** --- 1,40 ---- + /* Test that iterative instantiation does not cause objective-c++ + compilation failure. */ + + #include + /* { dg-do compile } */ + + @interface NSNotificationCenter : Object + + (id)defaultCenter; + - (void)removeObserver:(id)observer; + + @end + + class Base + { + public: + Base() { } + virtual ~Base() { } + + void destroy() { delete this; } + }; + + template + class Subclass : public T + { + public: + Subclass() { } + + virtual ~Subclass() + { + [[NSNotificationCenter defaultCenter] removeObserver: __null]; + } + }; + + int main(int argc, const char * argv[]) + { + Subclass* theSubclass = new Subclass(); + + theSubclass->destroy(); // THIS WILL NOT COMPILE + return 0; + } Index: cp/decl.h =================================================================== *** cp/decl.h (revision 117415) --- cp/decl.h (working copy) *************** enum decl_context *** 34,36 **** --- 34,39 ---- extern tree grokdeclarator (const cp_declarator *, const cp_decl_specifier_seq *, enum decl_context, int, tree*); + + /* We need this here to avoid a warning in decl2.c */ + extern void emit_instantiate_pending_templates (location_t *); Index: cp/decl2.c =================================================================== *** cp/decl2.c (revision 117415) --- cp/decl2.c (working copy) *************** build_java_method_aliases (void) *** 3019,3083 **** } } ! /* This routine is called from the last rule in yyparse (). ! Its job is to create all the code needed to initialize and ! destroy the global aggregates. We do the destruction ! first, since that way we only need to reverse the decls once. */ void ! cp_finish_file (void) { - tree vars; bool reconsider; - size_t i; - location_t locus; unsigned ssdf_count = 0; int retries = 0; - tree decl; - locus = input_location; at_eof = 1; - /* Bad parse errors. Just forget about it. */ - if (! global_bindings_p () || current_class_type || decl_namespace_list) - return; - - if (pch_file) - c_common_write_pch (); - - #ifdef USE_MAPPED_LOCATION - /* FIXME - huh? */ - #else - /* Otherwise, GDB can get confused, because in only knows - about source for LINENO-1 lines. */ - input_line -= 1; - #endif - - /* We now have to write out all the stuff we put off writing out. - These include: - - o Template specializations that we have not yet instantiated, - but which are needed. - o Initialization and destruction for non-local objects with - static storage duration. (Local objects with static storage - duration are initialized when their scope is first entered, - and are cleaned up via atexit.) - o Virtual function tables. - - All of these may cause others to be needed. For example, - instantiating one function may cause another to be needed, and - generating the initializer for an object may cause templates to be - instantiated, etc., etc. */ - - timevar_push (TV_VARCONST); - - emit_support_tinfos (); - do { tree t; tree decl; ! reconsider = false; /* If there are templates that we've put off instantiating, do --- 3019,3042 ---- } } ! /* This routine emits pending functions and instatiates pending ! templates iteratively as more opportunities arise. */ void ! emit_instantiate_pending_templates (location_t *locusp) { bool reconsider; unsigned ssdf_count = 0; int retries = 0; at_eof = 1; do { tree t; tree decl; ! size_t i; ! tree vars; reconsider = false; /* If there are templates that we've put off instantiating, do *************** cp_finish_file (void) *** 3150,3156 **** /* Set the line and file, so that it is obviously not from the source file. */ ! input_location = locus; ssdf_body = start_static_storage_duration_function (ssdf_count); /* Make sure the back end knows about all the variables. */ --- 3109,3115 ---- /* Set the line and file, so that it is obviously not from the source file. */ ! input_location = *locusp; ssdf_body = start_static_storage_duration_function (ssdf_count); /* Make sure the back end knows about all the variables. */ *************** cp_finish_file (void) *** 3176,3182 **** /* Finish up the static storage duration function for this round. */ ! input_location = locus; finish_static_storage_duration_function (ssdf_body); /* All those initializations and finalizations might cause --- 3135,3141 ---- /* Finish up the static storage duration function for this round. */ ! input_location = *locusp; finish_static_storage_duration_function (ssdf_body); /* All those initializations and finalizations might cause *************** cp_finish_file (void) *** 3187,3193 **** #ifdef USE_MAPPED_LOCATION /* ??? */ #else ! locus.line++; #endif } --- 3146,3152 ---- #ifdef USE_MAPPED_LOCATION /* ??? */ #else ! locusp->line++; #endif } *************** cp_finish_file (void) *** 3285,3290 **** --- 3244,3304 ---- retries++; } while (reconsider); + } + + /* This routine is called from the last rule in yyparse (). + Its job is to create all the code needed to initialize and + destroy the global aggregates. We do the destruction + first, since that way we only need to reverse the decls once. */ + + void + cp_finish_file (void) + { + bool reconsider; + size_t i; + location_t locus; + tree decl; + + locus = input_location; + at_eof = 1; + + /* Bad parse errors. Just forget about it. */ + if (! global_bindings_p () || current_class_type || decl_namespace_list) + return; + + if (pch_file) + c_common_write_pch (); + + #ifdef USE_MAPPED_LOCATION + /* FIXME - huh? */ + #else + /* Otherwise, GDB can get confused, because in only knows + about source for LINENO-1 lines. */ + input_line -= 1; + #endif + + /* We now have to write out all the stuff we put off writing out. + These include: + + o Template specializations that we have not yet instantiated, + but which are needed. + o Initialization and destruction for non-local objects with + static storage duration. (Local objects with static storage + duration are initialized when their scope is first entered, + and are cleaned up via atexit.) + o Virtual function tables. + + All of these may cause others to be needed. For example, + instantiating one function may cause another to be needed, and + generating the initializer for an object may cause templates to be + instantiated, etc., etc. */ + + timevar_push (TV_VARCONST); + + emit_support_tinfos (); + + emit_instantiate_pending_templates (&locus); + reconsider = false; /* All used inline functions must have a definition at this point. */ for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)