sa_class_declaration.cc

Go to the documentation of this file.
00001 /*
00002    The lestes compiler suite
00003    Copyright (C) 2002, 2003, 2004, 2005 Miroslav Tichy
00004    Copyright (C) 2002, 2003, 2004, 2005 Petr Zika
00005    Copyright (C) 2002, 2003, 2004, 2005 Vojtech Hala
00006    Copyright (C) 2002, 2003, 2004, 2005 Jiri Kosina
00007    Copyright (C) 2002, 2003, 2004, 2005 Pavel Sanda
00008    Copyright (C) 2002, 2003, 2004, 2005 Jan Zouhar
00009    Copyright (C) 2002, 2003, 2004, 2005 Rudolf Thomas
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; version 2 of the License.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    See the full text of the GNU General Public License version 2, and
00021    the limitations in the file doc/LICENSE.
00022 
00023    By accepting the license the licensee waives any and all claims
00024    against the copyright holder(s) related in whole or in part to the
00025    work, its use, and/or the inability to use it.
00026  
00027  */
00028 #include <lestes/lang/cplus/sem/as_access_specifier_to_ss_access_specifier.g.hh>
00029 #include <lestes/lang/cplus/sem/as_base_specifier_to_ss_base_specifier.g.hh>
00030 #include <lestes/lang/cplus/sem/as_class_key_to_ss_access_specifier.g.hh>
00031 #include <lestes/lang/cplus/sem/as_class_key_to_ss_struct_base.g.hh>
00032 #include <lestes/lang/cplus/sem/as_decl.g.hh>
00033 #include <lestes/lang/cplus/sem/as_id_to_declaration_set.g.hh>
00034 #include <lestes/lang/cplus/sem/as_id_to_ss_decl_name.g.hh>
00035 #include <lestes/lang/cplus/sem/li_class_by_name_in_single_scope.g.hh>
00036 #include <lestes/lang/cplus/sem/sa_class_declaration.g.hh>
00037 #include <lestes/lang/cplus/sem/sa_class_declaration.m.hh>
00038 #include <lestes/lang/cplus/sem/sa_context.g.hh>
00039 #include <lestes/lang/cplus/sem/sa_decl_seq_compound_pair_creator.g.hh>
00040 #include <lestes/lang/cplus/sem/sa_loggers.hh>
00041 #include <lestes/lang/cplus/sem/ss_decl_name.g.hh>
00042 #include <lestes/lang/cplus/sem/ss_declaration.g.hh>
00043 #include <lestes/lang/cplus/sem/ss_declaration_to_ss_decl_seq.g.hh>
00044 #include <lestes/lang/cplus/sem/ss_enums.g.hh>
00045 #include <lestes/lang/cplus/sem/ss_misc.g.hh>
00046 #include <lestes/lang/cplus/sem/ss_statement.g.hh>
00047 #include <lestes/lang/cplus/sem/ss_type.g.hh>
00048 #include <lestes/lang/cplus/sem/ss_type2info.g.hh>
00049 #include <lestes/lang/cplus/syn/manager.hh>
00050 #include <lestes/lang/cplus/syn/token.hh>
00051 #include <lestes/msg/logger.hh>
00052 #include <lestes/msg/logger_util.hh>
00053 
00054 /*! \file
00055   \brief Handling of class declarations.
00056   
00057   Hint: when processing undeclared: (1) pretend forward (2) fixup as in already
00058   declared case
00059   
00060   \todo TMA declared/undeclared distinction
00061   \todo TMA class name; and similar handling (forward declaration)
00062   \todo TMA int foo(class A * x) handling (invisible forward)
00063   \author TMA
00064  */
00065 
00066 package(lestes);
00067 package(lang);
00068 package(cplus);
00069 package(sem);
00070 
00071 /*!
00072   This method installs the context of the class to the current context by
00073   pushing the new context over the previous.
00074 
00075   The method only wraps its arguments into an acceptable sa_context
00076   instance that is subsequently pushed on the sa_context_manager's stack.
00077  */
00078 void sa_class_declaration::new_context(ptr< source_location > location, ss_access_specifier::type access_specifier, ptr< ss_decl_seq > scope, ptr< as_name > name)
00079 {
00080         ptr < as_access_specifier > acc_spec;
00081 
00082         switch (access_specifier) {
00083                 case ss_access_specifier::ACCESS_PUBLIC:
00084                         acc_spec = as_access_specifier_public::create(location);
00085                         break;
00086                 case ss_access_specifier::ACCESS_PRIVATE:
00087                         acc_spec = as_access_specifier_private::create(location);
00088                         break;
00089                 default:
00090                         lassert2(false, "Default access specifier for a class has to be either public or private.");
00091                         
00092         }
00093 
00094         ptr < sa_context > new_ctx = sa_context::create(
00095                         sa_as_context::create(name, acc_spec), 
00096                         sa_ss_context::create(scope, access_specifier),
00097                         sa_sa_context::create());
00098         sa_context_manager::instance()->push(new_ctx);
00099 }
00100 
00101 /*!
00102   This method processes a class header (up to the class' opening brace) and
00103   adds all the structures necessary to the context. Then the context is
00104   switched, so that the subsequent declarations found in the class body are
00105   inserted to the proper context.
00106 
00107   A special care has to be observed, because the class might be already forward
00108   declared. In such a case no new ss_class object shall be created, because for
00109   every class there shall be just one such object.  Also the issue is further
00110   complicated by the visibility/invisibility of such previous declaration.
00111  */
00112 void sa_class_declaration::process(ptr < as_class_specifier > cs)
00113 {
00114         sa_class_logger << "sa_class_declaration::process begin\n" << msg::eolog;
00115         if (::lestes::lang::cplus::syn::manager::in_disambiguation()) {
00116                 sa_class_logger << "nop -- in disambiguation\n" << msg::eolog;
00117         } else {
00118                 sa_class_logger << "sa_class_declaration:: location\n" << msg::eolog;
00119                 ptr < source_location > location = cs->location_get();
00120 
00121                 //sa_class_logger << "sa_class_declaration:: name\n" << msg::eolog;
00122                 //ptr < ss_decl_name > decl_name = as_id_to_ss_decl_name::instance()->process(cs->name_get()->identifier_get());;
00123                 //lassert(decl_name);
00124 
00125                 sa_class_logger << "sa_class_declaration:: former declaration?\n" << msg::eolog;
00126                 
00127                 sa_class_logger << "sa_class_declaration:: name\n" << msg::eolog;
00128                 ptr < ss_decl_name > decl_name = as_id_to_ss_decl_name::instance()->process(cs->name_get()->identifier_get());;
00129                 lassert(decl_name);
00130 
00131                 sa_class_logger << "sa_class_declaration:: determine scope into which the declaration belongs\n" << msg::eolog;
00132                 ptr < ss_decl_seq > seq;
00133                 if (cs->name_get()->was_qualified_get()) {
00134                         ptr < ::lestes::std::set < srp < ss_declaration > > > qual_declarations =
00135                                 as_id_to_declaration_set::instance()->process(
00136                                         cs->name_get()->qualification_get()->identifier_get());
00137                         lassert2(qual_declarations->size() == 1,
00138                                 "Qualification should unambiguously name a single scope declaration");
00139                         seq = ss_declaration_to_ss_decl_seq::instance()->process(*qual_declarations->begin());
00140                         /* FIXME: shall qualified declaration of invisible classes be handled differently? */
00141                 } else {
00142                         seq = sa_context_manager::instance()->current()->ss_get()->scope_get();
00143                 }
00144                 lassert(seq);
00145 
00146                 /* FIXME: maybe heed visibility in the qname case... */
00147                 sa_class_logger << "sa_class_declaration:: lookup for potentionaly invisible former declaration\n" << msg::eolog;
00148                 ptr < ss_structure_declaration > decl = li_class_by_name_in_single_scope::create()->process(decl_name, seq);
00149 
00150                 if (decl) {
00151                         sa_class_logger << "sa_class_declaration:: process_declared\n" << msg::eolog;
00152                         process_declared(cs, decl);
00153                 } else {
00154                         sa_class_logger << "sa_class_declaration:: process_undeclared\n" << msg::eolog;
00155                         process_undeclared(cs);
00156                 }
00157         }
00158         sa_class_logger << "sa_class_declaration::process end\n" << msg::eolog;
00159 }
00160 
00161 /*!
00162   \brief Handles the already declared case.
00163 
00164   The declaration is made visible, based on the assumption that the class
00165   specifier containing the body of the class cannot introduce an invisible
00166   name, because such class specifiers are forbidden in the contexts leading to
00167   a invisible declaration introduction.
00168 
00169   \invariant !syn::manager::in_disambiguation()
00170   \invariant the type does not name a complete type
00171  */
00172 void sa_class_declaration::process_declared(ptr < as_class_specifier > cs, ptr < ss_structure_declaration > class_decl)
00173 {
00174         lassert(!syn::manager::in_disambiguation());
00175 
00176         sa_class_declaration_logger << "sa_class_declaration::process_declared begin\n" << msg::eolog;
00177         /* location */
00178         ptr < source_location > location = cs->location_get();
00179 
00180         /* visibility */
00181         sa_class_declaration_logger << "visibility\n" << msg::eolog;
00182         ptr < ss_declaration_time > dt
00183                 = ss_declaration_time::create(cs->location_get()->order_get());
00184 
00185         lassert2(dt->is_before(class_decl->type_get().dncast<ss_struct_base>()->completion_time_get()), "FIXME: report error");
00186         if (!class_decl->visible_since_get()->is_before(dt)) {
00187                 sa_class_declaration_logger << "visibility adjusted\n" << msg::eolog;
00188                 class_decl->visible_since_set(dt);
00189         }
00190 
00191         /* handle default access */
00192         /* access specifier that is the default for this kind of struct/class/union */
00193         sa_class_declaration_logger << "determine default access specifier\n" << msg::eolog;
00194         ss_access_specifier::type access_specifier =
00195                 as_class_key_to_ss_access_specifier::create()->process(cs->key_get());
00196         /* handle bases */
00197         /* bases */
00198         sa_class_type_logger << "bases: AS->SS transform\n" << msg::eolog;
00199         ptr < ::lestes::std::list < srp < ss_base_specifier > > > bases =
00200                 as_base_specifier_to_ss_base_specifier::create(
00201                         access_specifier)->process_list(cs->base_specifiers_get());
00202         /* modify the class to reflect the supplied bases */
00203         sa_class_type_logger << "bases: fill in right place\n" << msg::eolog;
00204         ptr < ss_type > type = class_decl->type_get();
00205         // DIE reflections maimer, DIE
00206         if (type && dynamic_cast<ss_class *>(type.operator->())) {
00207                 ptr < ss_class > a_class = type.dncast<ss_class>();
00208                 a_class->bases_get()->splice(
00209                                 a_class->bases_get()->end(), *bases);
00210         }
00211 
00212         /* switch context */
00213         sa_class_declaration_logger << "context switch\n" << msg::eolog;
00214         new_context(location, access_specifier, class_decl->body_get(), cs->name_get());
00215 
00216         sa_class_declaration_logger << "sa_class_declaration::process_declared end\n" << msg::eolog;
00217 }
00218 
00219 /*!
00220   \invariant !syn::manager::in_disambiguation()
00221  */
00222 void sa_class_declaration::process_undeclared(ptr < as_class_specifier > cs)
00223 {
00224         lassert(!syn::manager::in_disambiguation());
00225 
00226         sa_class_declaration_logger << "sa_class_declaration::process_undeclared begin\n" << msg::eolog;
00227 
00228         sa_class_declaration_logger << "parent declseq get\n" << msg::eolog;
00229         ptr < ss_decl_seq > parent_scope = sa_context_manager::instance()->current()->ss_get()->scope_get();
00230 
00231         ptr < ss_structure_declaration > class_decl =
00232                 insert_class_forward_into_scope(cs, true, parent_scope);
00233 
00234         process_declared(cs, class_decl);
00235 
00236         sa_class_declaration_logger << "sa_class_declaration::process_undeclared end\n" << msg::eolog;
00237 }
00238 
00239 
00240 /*!
00241   \invariant !syn::manager::in_disambiguation()
00242  */
00243 void sa_class_declaration::process_end(ptr < source_location > location)
00244 {
00245         sa_class_logger << "sa_class_declaration::process_end begin\n" << msg::eolog;
00246         lassert(!syn::manager::in_disambiguation());
00247 
00248         sa_class_logger << "mark class as complete\n" << msg::eolog;
00249         sa_context_manager::instance()->current()->ss_get()->scope_get()->declared_by_get()->type_get().dncast<ss_struct_base>()->completion_time_set(ss_declaration_time::create(location->order_get()));
00250         sa_class_logger << "context pop\n" << msg::eolog;
00251         sa_context_manager::instance()->pop();
00252         sa_class_logger << "sa_class_declaration::process_end end\n" << msg::eolog;
00253 }
00254 
00255 /*!
00256   \invariant !syn::manager::in_disambiguation()
00257  */
00258 ptr < ::lestes::lang::cplus::sem::ss_structure_declaration > sa_class_declaration::insert_class_forward_into_scope(ptr < ::lestes::lang::cplus::sem::as_class_specifier > cs, bool visibly, ptr < ::lestes::lang::cplus::sem::ss_decl_seq > parent_scope)
00259 {
00260         lassert(!syn::manager::in_disambiguation());
00261 
00262         if (syn::manager::in_disambiguation())
00263                 return NULL;
00264         /* location */
00265         ptr < source_location > location = cs->location_get();
00266 
00267         sa_class_logger << "sa_class_declaration:: name\n" << msg::eolog;
00268         ptr < ss_decl_name > decl_name = as_id_to_ss_decl_name::instance()->process(cs->name_get()->identifier_get());;
00269         lassert(decl_name);
00270 
00271         sa_class_declaration_logger << "declseq & compound\n" << msg::eolog;
00272         ptr < ::lestes::std::pair < srp < ss_decl_seq >, srp < ss_compound_stmt > > > p = 
00273                 sa_decl_seq_compound_pair_creator::instance()->process(location, 
00274                         parent_scope,
00275                         parent_scope->compound_stmt_get()
00276                 );
00277         lassert(p);
00278 
00279         ptr < ss_decl_seq > decl_seq = p->first;
00280         ptr < ss_compound_stmt > stmt = p->second;
00281         lassert(decl_seq && stmt);
00282 
00283         sa_class_declaration_logger << "type\n" << msg::eolog;
00284         ptr < ss_struct_base > type =
00285                 as_class_key_to_ss_struct_base::create(
00286                         decl_seq,
00287                         ::lestes::std::list < srp < ss_base_specifier > >::create()
00288                         )->process(cs->key_get());
00289 
00290         sa_class_declaration_logger << "proper\n" << msg::eolog;
00291         ptr < ss_structure_declaration > class_decl = ss_structure_declaration::create(
00292                         location, // location
00293                         visibly
00294                                 ? ss_declaration_time::create(location->order_get())
00295                                 : ss_declaration_time::infinity(), // visible
00296                         ss_declaration_time::create(location->order_get()), // decl time
00297                         decl_name, //name
00298                         parent_scope, // contained in
00299                         type, // type
00300                         // FIXME: determine linkage according to parent scope
00301                         ss_linkage::create("C++",ss_linkage::LINKAGE_EXTERNAL), // linkage
00302                         sa_context_manager::instance()->current()->ss_get()->access_specifier_get(), // access specifier
00303                         ss_storage_class::ST_NONE, // storage class
00304                         ::lestes::std::set< srp< ss_struct_base > >::create(), // friends
00305                         decl_seq
00306                         );
00307 
00308         sa_class_declaration_logger << "injected\n" << msg::eolog;
00309         ptr < ss_injected_class_declaration > class_decl_alias = ss_injected_class_declaration::create(
00310                         location, // location
00311                         ss_declaration_time::create(location->order_get()), // visible
00312                         ss_declaration_time::create(location->order_get()), // decl time
00313                         decl_name, //name
00314                         decl_seq, // contained in
00315                         type, // type
00316                         // FIXME: correct?
00317                         class_decl->linkage_get(), // linkage
00318                         ss_access_specifier::ACCESS_PUBLIC, // access specifier
00319                         ss_storage_class::ST_NONE, // storage class
00320                         class_decl // real class
00321                         );
00322 
00323         sa_class_declaration_logger << "fixup circular structures\n" << msg::eolog;
00324         /* fill right values */
00325         type->decl_set(class_decl);
00326         decl_seq->declared_by_set(class_decl);
00327         decl_seq->contents_get()->push_back(class_decl_alias);
00328         parent_scope->contents_get()->push_back(class_decl);
00329 
00330         return class_decl;
00331 
00332 }
00333 
00334 /*!
00335   \todo TMA invisible former declarations shall be made visible, visible former
00336   declarations shall be left untouched. In the remaining cases, a new visible
00337   declaration shall be inserted.
00338  */
00339 void sa_class_declaration::process_forward_declaration(ptr < as_class_specifier > cs)
00340 {
00341         if (!syn::manager::in_disambiguation()) {
00342                 ptr<ss_decl_seq> ds =
00343                         sa_context_manager::instance()->current()->ss_get()->scope_get();
00344                 insert_class_forward_into_scope(cs, true, ds);
00345         }
00346 }
00347 
00348 end_package(sem);
00349 end_package(cplus);
00350 end_package(lang);
00351 end_package(lestes);
00352 

Generated on Mon Feb 12 18:23:11 2007 for lestes by doxygen 1.5.1-20070107