/*ident "@(#)cls4:src/template.h 1.12" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ /****************************************************************************** * Copyright (c) 1989 by Object Design, Inc., Burlington, Mass. * All rights reserved. *******************************************************************************/ enum bool { false, true }; extern Pclass current_instantiation; extern Pfct current_fct_instantiation; // typedef unsigned char uchar; // sun's types.h: u_char typedef class templ *Ptempl; typedef class funct_inst *Pfunct_inst; typedef class templ_inst *Ptempl_inst; typedef class basic_inst *Pbase_inst; typedef class basic_template *Ptempl_base; typedef class function_template *Pfunt; typedef class data_template *Pdata; typedef class templ_state *Ptstate; typedef class templ_classdef *Ptclass; typedef class templ_fct *Ptfct; typedef class Pslot *Pbinding; typedef class cons *Pcons; class cons { /* A Lisp style cons cell to help build lists. * The parameterized type facility should obviate * the need for this type-unsafe nonsense. */ public: void *car; cons *cdr; cons(void *pcar, cons *pcdr) { car=pcar; cdr=pcdr; }; }; /***************************************************************************** * * * The class template_compilation holds the state, and the associated methods * * used during template compilation. There is exactly one instance of the * * type, it is mainly a device used to enforce modularity. In reality, it * * would never need to be instantiated since all it's members are static. * * However, since the type::mem for a reference is not supported as * * yet(cfront 1.2), we need an instantiation to get to the members via * * pointer syntax instead. * * * * ***** should change to pure static class ***** * * * * A templ_compilation holds the state relevant to the syntax analysis of a * * class or member function template definition. * * * *****************************************************************************/ /***************************************************************************** * will merge class and function handling by having owner be a basic template * * pointer -- first, let's get functions up and running. then do it right * *****************************************************************************/ class templ_state { /* save relevant information when parsing friend * template within a class: currently, only instance * where a nested template can occur */ public: templ_state(); // save ~templ_state(); // restore private: Plist param_end; Plist params; Pcons templ_refs; Pcons friend_templ_refs; Pcons last_cons; Pcons last_friend_cons; Ptempl owner; }; class templ_compilation { /* A templ_compilation holds the state relevant to the syntax * analysis of a class or member function template definition. * * There is exactly one instance of the type. It mainly serves * as a device used to enforce modularity. */ public: static Plist param_end; // make append easier static Ptempl list; // list of class templates for compilation static Pfunt f_list; // list of function templates for compilation static Pfunt f_owner; // template when compiling a function static Ptempl owner; // template when compiling a member function static Ptempl_base parsed_template; // template immediately parsed static Plist params; // list of parameters to the template static Pexpr actuals; // list of actuals for explicit class template static Ptable templates; // templates defined during compilation static bool in_progress; static Ptstate save_templ; /* instantiation parameter parsing in progress. Used in the lexer * to ensure that name string are consed in the heap, rather than * being retained as pointers into the lex buffer. */ static int parameters_in_progress; static bool formals_in_progress; // the list of templates referenced by the top level definition being compiled. static Pcons templ_refs; static Pcons friend_templ_refs; static Pcons last_cons; static Pcons last_friend_cons; void start(); // initialize templ_compilation state void end(Pname class_name); void end_of_compilation(); // Done with compilation, instantiate bodies Pname forward_declaration(Pname class_name); void introduce_class_templ(Pname cnamep); void introduce_funct_templ(Pname fnamep); void append_ref(Ptempl_inst ref); // add to templ_refs void append_friend_ref(Ptempl_inst ref); // add to friend_templ_refs void instantiate_ref_templ(); // instantiate templ_refs void clear_ref_templ(); // zero-out templ_refs void clear_friend_ref_templ(); // zero-out friend_templ_refs void collect(TOK parm_type, Pname namep); // collect type parameter void collect(Pname); // collect expression parameter void append_parameter(Pname); // place them in params void enter_parameters(); int get_formals_count(); // how many formals Pname check_tname(Pname p); bool current_template(Pname p, Pexpr actuals); bool friend_template(Pexpr actuals); Ptempl is_template(Pname); Ptempl is_template(char*); Pfunt is_template(char*,TOK); }; /* * The canonical template_compilation instance. * templ_compilation exists as a class simply to provide * a code and data packaging mechanism. * There is exactly one generated instance of it. */ extern templ_compilation *templp; // should actually be static member functions of templ_compilation Pname parametrized_typename (Pname p, Pexpr actuals, bit=0) ; Pbase parametrized_basetype (Pname p, Pexpr actuals) ; void check_formals_for_dups(Plist formals); void check_funct_formals(Plist formals, Pname namep); class basic_template { /* the basis for class and member function templates */ friend class templ_compilation; friend void display_templ_refs( basic_template* ); friend void handle_bound_friend( Ptempl_base, Pname ); protected: Plist formals; // The formal arguments to the template Pcons templ_refs; // The templates referenced by this template /* Use these state variables to set up the correct state for error processing. * They are used by the "error" routines for statement numbers. */ Pname Cdcl; Pstmt Cstmt; // used to detect loops during instantiation; a count greater than two is // indicative of a non-terminating instantiation sequence int open_instantiations; int extrapolated; // extrapolated friend declaration // ensure that use of formals is consistent across, class, member and // forward declarations void check_formals(Plist formals) ; public: virtual void dummy(); // for optimal vtbl laydown virtual int has_friend(Pname)=0; Plist get_formals() { return formals; } int get_formals_count(); // should probably define a member bool is_extrapolated() { return extrapolated ? true : false; } }; class templ : public basic_template { /* the template class representation */ friend class templ_inst; friend class function_template; friend class data_template; friend class classdef; private: Ptempl_inst insts; // template instantiations Pbase basep; // template COBJ basetype Pfunt fns; // member function declarations Pfunt fns_end; Pdata data; // static data member declarations Pdata data_end; public: Ptempl_inst get_match(Pexpr,Ptempl_inst,bool); bool check_actual_args(Pexpr); Ptempl next; // connects all the class templates in the comp Pname namep; // the TNAME for the template class bool defined; // actual definition seen Pname members; // note the members to catch redefinition errors Ptempl_inst get_inst(Pexpr,Ptempl_inst=0); templ(Plist,Pname); void resolve_forward_decl(Plist,Pclass); void instantiate_forward_decl(); Pbase basetype() {return basep; } // uninstantiated base type Pbase inst_basetype(Pexpr actuals); // specific instantiation basetype Pclass classtype() { return Pclass(basep->b_name->tp); } Pname typename(Pexpr actuals); Pfunt collect_function_member(Pname); Pdata collect_data_member(Pname); bool instantiate_bodies(); int has_friend(Pname); }; // Member function templates class function_template : public basic_template { /* SBL: go through these */ friend Pbinding is_ftempl_match(Pexpr,Pfunt); friend Pname has_templ_instance(Pname,Pexpr,bit=0); friend class templ_compilation; friend class templ; friend class templ_inst; friend class funct_inst; friend class basic_inst; friend class templ_fct; Pname fn; // The name of the member function Pfunt next; // connects the list of functions Pfunt gen_list; // connects overloaded instances public: Pfunct_inst insts; // instantiations of the template function_template(templ&,Plist,Pname); // member functions function_template(Plist,Pname); // function templates Pname func_name() { return fn; } void instantiate_forward_decl(); Pfunct_inst get_match(Pexpr,Pfunct_inst,bool); Pfunct_inst get_inst(Pexpr,Pfunct_inst=0); int has_friend(Pname); }; class data_template : public basic_template { // explicitly initialized static data members friend class templ; friend class basic_inst; friend class templ_inst; Pname dat_mem; Pdata next; public: data_template(templ&,Plist,Pname); int has_friend(Pname); // need override pure virtual }; // Global state variables that must be saved around an instantiation. The // saving of state was required in the implementstion that interspersed decl // processing and instantiation, rather than the current strategy, which only // forces instantiations at the top level outside of any dcl-processing // context. It is retained in case we ever go back to the "interspersed" style // of instantiation. class state { public: Pname Cdcl ; // the global variables used by the error routines Pstmt Cstmt ; Pname dcl_list ; // Holds the list of typedef names that are hidden Loc curloc ; int curr_file ; Pexpr curr_expr ; Pin curr_icall ; Pstmt curr_loop; Pblock curr_block; Pstmt curr_switch; int bound ; int inline_restr ; Loc last_line ; state() {} ; // prevent used before set warnings. void save() ; void init() ; void restore() ; } ; class pointer_hash ; class tree_copy_info ; // A template starts out being uninstantiated, and is class_instantiated when // there is a refrence to it with actual arguments. It is body_instantiated at // the end of compilation, when all its function members are instantiated. enum inst_status { uninstantiated, function_instantiated, data_instantiated, class_instantiated, body_instantiated }; // templ_inst captures the arguments used in the instantiation of a template. // These instantiations are rooted in the templ object. class basic_inst { /* SBL: go through these */ friend class template_instantiation; friend class templ; friend class function_template; friend class templ_classdef; friend Pcons make_ref_copy(pointer_hash&,tree_copy_info&,Pcons); public: Pname get_tname() { return tname; } Pname get_namep() { return namep; } void print_error_loc(int=0); // Wants to be a static function virtual void dummy(); // for optimal vtbl laydown virtual void print_pretty_name() = 0; // for nice error reporting virtual char *mangled_name(char*) = 0; // mangle template class/function names Pexpr actuals; // instantiation arguments, chained using ELIST // as an expression "cons" node, e1 is the car // and e2 the cdr. The car points to a name node. Plist inst_formals; // the instantiation's copy of the formals static Pbase_inst head; // head of list of active instantiations. protected: TOK isa; // for the moment: CLASS,FCT Pname tname; // name of instantiation Pname namep; // version of name in ktbl (class) or gtbl(funct) state context; // the context of this instantiation Plist hidden_globals; // list of globals hidden during instantiation // Plist inst_formals; // the instantiation's copy of the formals inst_status status; Pbase_inst next_active; // list of currently active instantiations. char *instantiation_string(); // The class correspondence table. This table is initialized // when the class definition is instantiated. Subsequently, it is used to // initial member correspondence tables before copy process is initiated. pointer_hash *corr; Pcons ref_copy(pointer_hash&,tree_copy_info&,Pcons); // save and restore state around the template instantiation void save_state(Pname p) ; void restore_state() ; void expose_parameter_names(); void hide_parameter_names(); TOK isA() { return isa; } }; struct Pslot { Pname param; Ptype typ; }; class funct_inst : public basic_inst { friend class template_instantiation; friend class function_template; friend class templ_fct; private: Pfunct_inst next; // list of template instantiations Pfunct_inst tfct_copy(Pcons&,bool); void bind_formals(); public: funct_inst( Pexpr act, Pfunt owner ); void instantiate( bool reinstantiate = false ); void print_pretty_name(); // virtual char *mangled_name(char*); // virtual bool actuals_match(Pexpr); Pfunt def; // template definition; this is an instantiation. bool refp; // notes template references during a C++ definition bool friend_refp; // notes template references during a C++ definition Pbinding binding; // actual types binding to formals bool f_copy_hook(Pnode&); }; class templ_inst : public basic_inst { friend class template_instantiation; friend class templ; friend class classdef; friend class templ_classdef; friend Pcons make_ref_copy(pointer_hash&,tree_copy_info&,Pcons); private: Ptempl_inst next; // linked list of template instantiations Ptempl_inst forward; // this instantiation same as `forward' public: templ_inst (Pexpr act, Ptempl owner); templ_inst (Pexpr act, Ptempl owner, TOK csu); bool actuals_match(Pexpr check_actuals); /* merge this and function's */ void instantiate_match(Ptempl_inst match) ; void kludge_copy(Pbase source_base) ; // create a copy of the class type subtree preparatory to the ensuing // instantiation. Return a non-zero value, only if there was no need to // create a copy, ie. an identical instantiation already existed. Ptempl_inst class_copy(Pcons &templ_refs, bool recopy) ; // Used to collect references to this template by a definition Ptempl_inst note_ref() ; public: Ptempl def; // The template definition, for which this is an // instantiation. bool refp ; // flag to note template references during a C++ // definition bool friend_refp ; // flag to note template references during a C++ void explicit_inst(); // Bind the formals before an instantiation void bind_formals() ; Ptempl_inst canonical_instantiation() { return ( forward ? forward : this ) ; } // get the class associated with this instantiation Pclass get_class() { return Pclass(Pbase(tname->tp)->b_name->tp) ;} Ptempl_inst instantiate(bool reinstantiate = false) ; void print_pretty_name(); // virtual char *mangled_name(char *buffer); // virtual // The uninstantiated basetype Pbase def_basetype() { return def->basep ; } ; // A general way of determining whether two template instantiations are // the same bool same(Ptempl_inst t) ; bool copy_hook(Pnode&) ; // return a copy of the function tree starting with it's name Pname function_copy(Pfunt,Pcons&); Pname data_copy(Pdata,Pcons&); // special check for instantiations used in qualifiers for template function // member declarations. bool check_qualifier(Plist formals) ; Pname get_parameter(char *s) ; } ; // Experimental debugging toggle ??? extern int zdebug; // The class node used for template classes. // Rep invariant: // class_base == UNINSTANTIATED || // class_base == INSTANTIATED class templ_classdef : public classdef { public: // a pointer to the instantiation; the instantiation // also points back to it via tname->cobj->name->class Ptempl_inst inst; templ_classdef(Ptempl_inst i); templ_classdef(Ptempl_inst i, TOK csu); Pname unparametrized_tname() {return inst->def->namep;} }; class templ_fct : public fct { public: Pfunct_inst inst; // pointer to the instantiation templ_fct(Pfunct_inst i); Pname unparametrized_tname() {return inst->def->fn;} void *operator new(size_t); void operator delete(void*,size_t); static Ptfct ptfct_free; }; // Safe accessor functions for navigating through COBJ base classes extern Templ_type get_class_base (Pbase b); extern Ptclass get_template_class (Pbase b); extern Ptempl_inst get_templ_inst(Pbase b); // functions and data structures needed for directed instantiation #include "Block.h" Blockdeclare(Pchar); extern Block(Pchar) instfct; extern int noinst; extern Block(Pchar) instdata; extern int nodatainst; extern bit tempdcl; extern bit mk_zero_init_flag; extern int first_file; extern bit all_flag,alltc_flag,data_flag,ft_flag,none_flag; extern void set_flags(); extern Pname righttname;