Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

init_handler.cc

Go to the documentation of this file.
00001 // AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
00002 
00003 #include "init_handler.h"
00004 #include "init_handler_i.h"
00005 
00006 
00007 #line 146 "init_handler.cpp"
00008 
00010 static Ptree*
00011 get_string_literal(Ptree* t);
00012 
00013 #line 167 "init_handler.cpp"
00014 
00015 static bool
00016 is_character_type(Type t);
00017 
00018 #line 48 "init_handler.cpp"
00019 
00024 Init_reader::Init_reader(Ptree* tree)
00025     : tree(tree)
00026 { }
00027 
00028 #line 56 "init_handler.cpp"
00029 
00031 bool
00032 Init_reader::is_compound()
00033 {
00034     return tree && dynamic_cast<PtreeBrace*>(tree->Car());
00035 }
00036 
00037 #line 63 "init_handler.cpp"
00038 
00040 Ptree*
00041 Init_reader::get()
00042 {
00043     if (tree) {
00044         Ptree* rv = tree->Car();
00045         if ((tree = tree->Cdr()))
00046             tree = tree->Cdr();
00047         return rv;
00048     } else
00049         return 0;
00050 }
00051 
00052 #line 76 "init_handler.cpp"
00053 
00055 Ptree*
00056 Init_reader::get_nondestructive() const
00057 {
00058     return tree ? tree->Car() : 0;
00059 }
00060 
00061 #line 90 "init_handler.cpp"
00062 
00063 void
00064 Init_reader::dump(std::ostream& os)
00065 {
00066     tree->Display2(os);
00067 }
00068 
00069 #line 103 "init_handler.cpp"
00070 
00071 
00072 Init_maker::Init_maker()
00073     : tree(0)
00074 { }
00075 
00076 #line 108 "init_handler.cpp"
00077 
00079 void
00080 Init_maker::add(Ptree* p)
00081 {
00082     if (tree) {
00083         Ptree::Snoc(tree, make_static_leaf(","));
00084         Ptree::Snoc(tree, p);
00085     } else {
00086         tree = Ptree::List(p);
00087     }
00088 }
00089 
00090 #line 120 "init_handler.cpp"
00091 
00093 Ptree*
00094 Init_maker::make_init() const
00095 {
00096     return new PtreeBrace(make_static_leaf("{"),
00097                           Ptree::List(tree, make_static_leaf("}")));
00098 }
00099 
00100 #line 128 "init_handler.cpp"
00101 
00102 /****************************** Init_handler ******************************/
00103 
00111 Init_handler::Init_handler(Abstract_scope* scope, Ptree* tree, bool zero_init)
00112     : tree(tree), scope(scope), zero_init(zero_init)
00113 { }
00114 
00115 #line 141 "init_handler.cpp"
00116 
00117 
00118 Init_handler::~Init_handler()
00119 { }
00120 
00121 #line 145 "init_handler.cpp"
00122 
00125 static Ptree*
00126 get_string_literal(Ptree* t)
00127 {
00128     if (!t) {
00129         return 0;
00130     } else if (dynamic_cast<PtreeParenExpr*>(t)) {
00131         return get_string_literal(t->Second());
00132     } else if (t->IsLeaf()) {
00133         const char* c = t->GetPosition();
00134         int l = t->GetLength();
00135         if (l >= 2 && (*c == '"' || ((*c == 'L' || *c == 'l') && c[1] == '"')))
00136             return t;
00137         else
00138             return 0;
00139     } else {
00140         return 0;
00141     }
00142 }
00143 
00144 #line 166 "init_handler.cpp"
00145 
00147 static bool
00148 is_character_type(Type t)
00149 {
00150     return t.is_same_unqualified_type(char_type) || t.is_same_unqualified_type(wchar_type)
00151         || t.is_same_unqualified_type(uchar_type) || t.is_same_unqualified_type(schar_type);
00152 }
00153 
00154 #line 174 "init_handler.cpp"
00155 
00157 Ptree*
00158 Init_handler::make_constructor_call(Type t, Ptree* args)
00159 {
00160     if (t.is_class_type()) {
00161         /* look for a constructor */
00162         Class_symbol* csym = downcast<Class_symbol*>(t.get_type_symbol());
00163         Function_symbol* fsym = dynamic_cast<Function_symbol*>(csym->lookup_helper(Symbol_name::CONSTRUCTOR_NAME).untag);
00164         if (!fsym)
00165             compile_error("class `" + csym->get_name() + "' has no ctor (huh?)");
00166 
00167         Overload_resolver resolver(false /* no operator */);
00168         Expr_annotator(scope, &Source::instance()).add_parms_from_arglist(&resolver, args);
00169         resolver.add_function(fsym, false);
00170 
00171         bool is_ambig;
00172         Overload_candidate* cand = resolver.get_best(&is_ambig);
00173         if (is_ambig)
00174             compile_error("initialisation is ambiguous");
00175         else if (!cand)
00176             compile_error("invalid parameter list for constructor");
00177 
00178         Annotated_funcall_maker afm(make_name(cand->fsig), t);
00179         for (unsigned i = 0; i < resolver.get_arg_count(); ++i)
00180             afm.add_arg(resolver.get_arg(i).get_tree());
00181         return afm.make_funcall();
00182     } else if (t.is_scalar_type() || t.get_kind() == Type::k_Reference) {
00183         Ptree* arg;
00184         if (!args)
00185             if (t.get_kind() == Type::k_Reference)
00186                 compile_error("can't default-initialize a reference");
00187             else
00188                 arg = make_static_leaf("0");
00189         else if (args->Length() == 1)
00190             arg = args->First();
00191         else
00192             compile_error("expression in initializer for scalar or reference type must have only one expression");
00193 
00194         Expr_result r = Expr_annotator(scope, &Source::instance()).visit(arg);
00195         Implicit_conversion* ics = generate_implicit_conversion(r, t, 0,
00196                                                                 true /* with user-def */,
00197                                                                 false /* not copy-init */,
00198                                                                 false /* not IOA */);
00199         if (!ics)
00200             compile_error("type mismatch for initializer");
00201 
00202         /* turn it into a copy-initializer */
00203         return ics->make_tree(r).get_tree();
00204     } else
00205         compile_error("can't direct-initialize that");
00206 }
00207 
00208 #line 226 "init_handler.cpp"
00209 
00216 Ptree*
00217 Init_handler::process_initializer(Type t)
00218 {
00219     /* shortcut: if we're given an empty tree, get default initializer */
00220     if (!tree)
00221         return get_default_initializer_for_type(t);
00222 
00223     /* The initializer can have the form
00224        [= expression]
00225        [= { brace }]
00226        [( args )] */
00227     if (tree->First()->Eq('(')) {
00228         /* (pseudo) constructor call */
00229         Ptree* args = tree->Second();
00230         expect_ptree(tree->Third(), ')');
00231         return make_constructor_call(t, args);
00232     } else if (tree->First()->Eq('=')) {
00233         /* assignment */
00234         if (dynamic_cast<PtreeBrace*>(tree->Second())) {
00235             if (t.get_kind() == Type::k_Array || t.is_class_type() || t.is_scalar_type()) {
00236                 /* scalar, array or class */
00237                 NonLeaf tmp(tree->Second(), 0);
00238                 Init_reader r(&tmp);
00239                 return process_brace(t, &r);
00240             } else
00241                 compile_error("can't brace-initialize that");
00242         } else {
00243             /* copy-assignment */
00244             if (t.get_kind() == Type::k_Array) {
00245                 if (is_character_type(t.get_basis_type())) {
00246                     Ptree* ct = get_string_literal(tree->Second());
00247                     if (ct)
00248                         return new Annotated<Leaf>(t, 0, *downcast<Leaf*>(ct));
00249                 }
00250                 compile_error("can't copy-initialize that");
00251             }
00252             NonLeaf tmp(tree->Second(), 0);
00253             Init_reader r(&tmp);
00254             return process_brace(t, &r);
00255         }
00256     } else
00257         bogus_ptree_error("strange initializer", tree);
00258 }
00259 
00260 #line 276 "init_handler.cpp"
00261 
00265 Ptree*
00266 Init_handler::process_brace(Type t, Init_reader* reader)
00267 {
00268     if (t.is_class_type()) {
00269         Class_symbol* csym = downcast<Class_symbol*>(t.get_type_symbol());
00270         if (csym->is_aggregate()) {
00271             if (reader->is_compound()) {
00272                 Init_reader sub(reader->get()->Second());
00273                 Ptree* rv = process_class(csym, &sub);
00274                 if (sub.get_nondestructive())
00275                     compile_error("too many initializers for type `" + csym->get_name() + "'");
00276                 return rv;
00277             } else
00278                 return process_class(csym, reader);
00279         }
00280         /* fall through to normal conversion */
00281     } else if (t.get_kind() == Type::k_Array) {
00282         Type base = t.get_basis_type();
00283         if (is_character_type(base)) {
00284             /* might be initialisation with string literal */
00285             Ptree* tree;
00286             if (reader->is_compound()) {
00287                 Init_reader sub(reader->get_nondestructive()->Second());
00288                 tree = sub.get();
00289                 if (sub.get())
00290                     tree = 0;
00291                 else
00292                     tree = get_string_literal(tree);
00293             } else
00294                 tree = get_string_literal(reader->get_nondestructive());
00295 
00296             if (tree) {
00297                 /* is initialisation with string literal */
00298                 reader->get();
00299                 assert(tree->IsLeaf());
00300                 return new Annotated<Leaf>(t, 0, *downcast<Leaf*>(tree));
00301             }
00302         }
00303 
00304         if (reader->is_compound()) {
00305             Init_reader sub(reader->get()->Second());
00306             Ptree* rv = process_array(t.get_basis_type(), &sub);
00307             if (sub.get())
00308                 /* can not happen currently */
00309                 compile_error("too many initializers for array");
00310             return rv;
00311         } else {
00312             compile_warning("partially bracketed initializer for array; interpretation might be wrong", reader->get_nondestructive());
00313             return process_array(t.get_basis_type(), reader);
00314         }
00315     }
00316 
00317     /* here, we expect a scalar or a simple conversion, i.e.
00318        'std::string foo[] = { "bar", "blub" }' */
00319     Ptree* ele;
00320     if (reader->is_compound()) {
00321         if (!t.is_scalar_type())
00322             compile_error("only scalar types can be initialized with braced value");
00323         Init_reader sub(reader->get()->Second());
00324         ele = sub.get();
00325         if (!ele || sub.get())
00326             compile_error("initializer for non-aggregate must contain exactly one element");
00327     } else
00328         ele = reader->get();
00329 
00330     if (!ele) {
00331         return get_default_initializer_for_type(t);
00332     } else {
00333         Expr_result res = Expr_annotator(scope, &Source::instance()).visit(ele);
00334         Implicit_conversion* ics = generate_implicit_conversion(res, t, 0,
00335                                                                 true, true, false);
00336         if (!ics)
00337             compile_error("type mismatch");
00338         return ics->make_tree(res).get_tree();
00339     }
00340 }
00341 
00342 #line 356 "init_handler.cpp"
00343 
00344 Ptree*
00345 Init_handler::process_array(Type t, Init_reader* reader)
00346 {
00347     Init_maker obi;
00348     if (reader->empty())
00349         compile_warning("zero-length array initializer?", reader->get_nondestructive());
00350 
00351     while (!reader->empty())
00352         obi.add(process_brace(t, reader));
00353 
00354     return obi.make_init();
00355 }
00356 
00357 #line 369 "init_handler.cpp"
00358 
00359 Ptree*
00360 Init_handler::process_class(Class_symbol* csym, Init_reader* reader)
00361 {
00362     if (!reader->is_compound() && reader->get_nondestructive()) {
00363         /* special case: if the argument is convertible to csym,
00364            initialize with it. We're here only when the class is an
00365            aggregate, in which case its only constructors are the
00366            default and copy constructors (i.e., nothing ugly). */
00367         // FIXME: this parses the expression twice when it fails.
00368         // Probably not worth bothering with.
00369         Expr_result res = Expr_annotator(scope, &Source::instance()).visit(reader->get_nondestructive());
00370         Implicit_conversion* ics = generate_implicit_conversion(res, csym->get_type(),
00371                                                                 0, true /* with user */,
00372                                                                 true /* is copy-init */,
00373                                                                 false /* is IOA */);
00374         if (ics) {
00375             // FIXME: encode a copy ctor call?
00376             reader->get();
00377             return ics->make_tree(res).get_tree();
00378         }
00379     }
00380 
00381     Init_maker hornbach;
00382     for (Class_symbol::members_t::const_iterator i = csym->mem_begin(); i != csym->mem_end(); ++i) {
00383         Variable_symbol* vsym = *i;
00384         if (vsym->is_member_variable()) {
00385             hornbach.add(process_brace(vsym->get_type(), reader));
00386             if (csym->get_kind() == Symbol::k_Union)
00387                 break;
00388         }
00389     }
00390     return hornbach.make_init();
00391 }
00392 
00393 #line 403 "init_handler.cpp"
00394 
00395 /************************** Default Initializer **************************/
00396 
00398 Ptree*
00399 Init_handler::get_default_initializer_for_type(Type t)
00400 {
00401     if (t.is_class_type()) {
00402         Class_symbol* csym = downcast<Class_symbol*>(t.get_type_symbol());
00403         Function_symbol* fsym = dynamic_cast<Function_symbol*>(csym->lookup_helper(Symbol_name::CONSTRUCTOR_NAME).untag);
00404         if (fsym) {
00405             /* we have a constructor. Attempt to call it with no args. */
00406             Overload_resolver resolver(false);
00407             resolver.add_function(fsym, false);
00408 
00409             Overload_candidate* cand = resolver.get_best(0);
00410             if (cand)
00411                 return Annotated_funcall_maker(make_name(cand->fsig), t).make_funcall();
00412         }
00413         if (csym->is_aggregate()) {
00414             /* if it is an aggregate, try brace-initialisation with empty brace. */
00415             Init_reader reader(0);
00416             return process_class(csym, &reader);
00417         }
00418         /* when we're here, it has a constructor but no default
00419            constructor */
00420         compile_error("unable to default-initialize that");
00421     } else if (t.get_kind() == Type::k_Array) {
00422         /* we can't default-initialize an array, because we don't know
00423            the dimensions */
00424         compile_warning("default-initialisation of an array requested", 0);
00425         return Init_maker().make_init();
00426     } else if (t.get_kind() == Type::k_Reference) {
00427         /* 8.5p5: a program that calls for default-initialisation of
00428            a reference is ill-formed */
00429         compile_error("can't default-initialize a reference");
00430     } else if (t.is_scalar_type()) {
00431         if (!zero_init)
00432             return 0;
00433         Leaf tmp_leaf("0", 1);
00434         Expr_result r (new Annotated<Leaf>(int_type, 0, tmp_leaf), Expr_result::k_RValue);
00435         Implicit_conversion* ics = generate_implicit_conversion(r, t, 0,
00436                                                                 true /* with user-def */,
00437                                                                 false /* not copy-init */,
00438                                                                 false /* not IOA */);
00439         if (!ics)
00440             compile_error("can't happen: type mismatch for initializer");
00441         return ics->make_tree(r).get_tree();
00442     } else {
00443         compile_error("can't default-initialize `" + t.get_human_readable_type() + "'");
00444     }
00445 }

Generated on Mon Feb 10 17:32:50 2003 for VFiasco Semantics Compiler by doxygen1.2.15