C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

funcnode.cc

Go to the documentation of this file.
00001 // $Id: funcnode.cc,v 1.5 2003/08/07 23:13:04 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "ref_clone_changer.h"
00040 
00041 // --------------------------------------------------------------------
00042 // Constructors
00043 // --------------------------------------------------------------------
00044 
00045 funcNode::funcNode(Type_qualifiers tq, decl_list * args, typeNode * returns,
00046                    const Coord coord)
00047   : typeNode(Func, tq, returns, coord),
00048     _args(),
00049     _is_knr(false)
00050 {
00051   if (args) {
00052     _args.swap(*args);
00053     //delete args;
00054   }
00055 }
00056 
00057 // ------------------------------------------------------------
00058 //  Type Equal
00059 // ------------------------------------------------------------
00060 
00061 bool funcNode::qualified_equal_to(typeNode * node2,
00062                                   bool strict_toplevel, bool strict_recursive)
00063 {
00064   funcNode * n2 = (funcNode *) node2;
00065 
00066   // -- Check the return value...
00067 
00068   if (! equal_to(returns(), n2->returns(),
00069                  strict_recursive, strict_recursive))
00070     return false;
00071 
00072   // -- If either arglist is empty, return successful
00073 
00074   decl_list & args1 = args();
00075   decl_list & args2 = n2->args();
00076 
00077   if (args1.empty() || args2.empty())
00078     return true;
00079 
00080   // -- Check number of args
00081 
00082   if (args1.size() != args2.size())
00083     return false;
00084 
00085   // -- Compare each arg...
00086   decl_list_p p1;
00087   decl_list_p p2;
00088 
00089   for (p1 = args1.begin(), p2 = args2.begin();
00090        (p1 != args1.end()) && (p1 != args2.end()) ;
00091        ++p1, ++p2) {
00092     typeNode * type1;
00093     typeNode * type2;
00094 
00095     // -- If arg is a declaration, get the type...
00096 
00097     if ((*p1)->typ() == Decl)
00098       type1 = ((declNode *)(*p1))->type();
00099     else
00100       type1 = (typeNode *)(*p1);
00101 
00102     if ((*p2)->typ() == Decl)
00103       type2 = ((declNode *)(*p2))->type();
00104     else
00105       type2 = (typeNode *)(*p2);
00106 
00107     if (! equal_to(type1, type2,
00108                    strict_recursive, strict_recursive))
00109       return false;
00110   }
00111 
00112   return true;
00113 }
00114 
00115 // ------------------------------------------------------------
00116 //  Argument list checks
00117 // ------------------------------------------------------------
00118 
00119 bool funcNode::is_void_args()
00120 {
00121   decl_list & the_args = args();
00122 
00123   if (the_args.size() == 1) {
00124     Node * f = the_args.front();
00125     return f->datatype()->is_void();
00126   }
00127   return false;
00128 }
00129 
00130 // ----------------------------------------------------------------------
00131 // FunctionConflict
00132 //
00133 // This routine is called if a function declaration, i.e. an Func, is
00134 // parsed and there is already a declaration.
00135 //
00136 // In general, either of ORIG or NEW could be a declaration, a
00137 // prototype, or the start of a function definition and it is not
00138 // possible to tell which is which.  In particular, the expression
00139 //
00140 //       int f()
00141 //
00142 // may be an old-style function declaration that permits an arbitrary
00143 // number of arguments of types compatible with "the usual unary
00144 // conversions" or it may be a function definition for a function with
00145 // no arguments.
00146 // 
00147 // We assume that In a "standard" program, the original expression is
00148 // an ANSI-C prototype and the create expression is the function
00149 // declaration
00150 //
00151 // In the general case, this confirms that the two specifications are
00152 // the same.  If the create declaration forces a revision of the old
00153 // one
00154 //
00155 //     e.g.    int foo();
00156 //             int foo(void) { ... }
00157 //
00158 // then it is required that the OLD one be mutated accordingly since
00159 // there are already references to the old one
00160 //
00161 // ----------------------------------------------------------------------
00162 
00163 // Must mutate original if changes required for consistency
00164 
00165 bool funcNode::check_conversions()
00166 {
00167   decl_list & the_args = args();
00168   decl_list_p p;
00169 
00170   // -- All parameters must be compatible...
00171 
00172   for (p = the_args.begin(); p != the_args.end(); ++p) {
00173 
00174     // -- Get the argument type
00175 
00176     typeNode * the_type = (*p)->datatype();
00177 
00178     // -- Check conversions..
00179 
00180     typeNode * conv = the_type->usual_unary_conversion_type();
00181     bool compatible = (* the_type == * conv );
00182     //delete conv;
00183 
00184     if ( ! compatible || the_type->is_ellipsis())
00185       return false;
00186   }
00187 
00188   return true;
00189 }
00190 
00191 // -- From ANSI 6.5.4.3
00192 
00193 bool funcNode::is_compatible_with(funcNode * nfunc)
00194 {
00195   funcNode * ofunc = this;
00196 
00197   // -- Return types must be equal...
00198 
00199   if (! (* ofunc->returns() == * nfunc->returns()) )
00200     return false;
00201 
00202   // -- Check the parameters..
00203 
00204   decl_list & oargs = ofunc->args();
00205   decl_list & nargs = nfunc->args();
00206 
00207   // -- CASE: both lists are in prototype form..
00208 
00209   if (! oargs.empty() && ! nargs.empty()) {
00210     decl_list_p optr;
00211     decl_list_p nptr;
00212 
00213     // -- The parameter lists must be of the same length
00214 
00215     if (oargs.size() != nargs.size())
00216       return false;
00217 
00218     // -- All parameters must be compatible...
00219 
00220     for (optr = oargs.begin(), nptr = nargs.begin();
00221          (optr != oargs.end()) && (nptr != nargs.end());
00222          ++optr, ++nptr) {
00223       typeNode * otype = (*optr)->datatype_superior();
00224       typeNode * ntype = (*nptr)->datatype_superior();
00225 
00226       if ( * otype != * ntype ) {
00227         // (*optr) = (*nptr); Why do this?
00228         return false;
00229       }
00230     }
00231 
00232     return true;
00233   }
00234   else
00235     if (oargs.empty() && nargs.empty())
00236       // -- CASE: Both lists are empty
00237       return true;
00238 
00239     else {
00240 
00241       // -- CASE: One of the arguments lists is empty. If the first
00242       // (original) one is empty, copy the arguments to that
00243       // definition.
00244 
00245       if (oargs.empty()) {
00246 
00247         decl_list_p fptr;
00248 
00249         // -- Fill the empty arg-list with copies of the arguments
00250 
00251         for (fptr = oargs.begin();
00252              fptr != oargs.end();
00253              ++fptr)
00254           nargs.push_back((declNode *) ref_clone_changer::clone(*fptr, false));
00255       }
00256 
00257       return true;
00258     }
00259 
00260   // --------- THE REST OF THIS IS NOT USED -------------------------------
00261 
00262   // -- CASE: Check for <Type> f(void)  vs  <Type> f()
00263 
00264   if (ofunc->is_void_args())
00265     return true;
00266 
00267   // -- CASE: Check for <Type> f()  vs  <Type> f(void)
00268 
00269   if (nfunc->is_void_args()) {
00270 
00271     // -- Make a (void) arg list for the original...
00272 
00273     declNode * void_decl = new declNode((typeNode *) new primNode(basic_type::Void), declNode::NONE);
00274     void_decl->decl_location(declNode::FORMAL);
00275 
00276     ofunc->args().push_front(void_decl);
00277     
00278     return true;
00279   }
00280 
00281   // -- CASE: One of the arg lists is empty
00282   // -- The types must be the usual unary conversions...
00283 
00284   if (! ofunc->check_conversions())
00285     return false;
00286 
00287   if (! nfunc->check_conversions())
00288     return false;
00289 
00290   return true;
00291 }
00292 
00293 // ------------------------------------------------------------
00294 // Add parameter types
00295 // ------------------------------------------------------------
00296 
00297 // Support for old-style declaration lists
00298 // AddParameterTypes
00299 //
00300 //   This takes a old-style function declaration `decl', which has a
00301 //   list of identifiers (Id nodes) as its argument list, and and a list of
00302 //   the parameter declarations `types', and converts the list
00303 //   of identifiers to a list of declarations (Decl nodes) with the types
00304 //   determined by the declaration list.  It is called upon the reduction of a
00305 //   procedure defined using the old-sytle function declaration.
00306 //
00307 //   In: decl = (Decl name (Func args=(List Id's) returntype) NULL NULL)
00308 //       types = (List Decl's)
00309 //   Out : (Decl name (Func args=(List Decl's) returntype) NULL NULL)
00310 
00311 void funcNode::add_parameter_types(decl_list * types)
00312 {
00313   decl_list & ids = args();
00314 
00315   decl_list_p ids_p;
00316   decl_list_p types_p;
00317 
00318   bool found;
00319 
00320   // -- Declarator list may be empty or null
00321   if (types) {
00322 
00323     // -- For each declaration...
00324 
00325     for (types_p = types->begin(); types_p != types->end(); ++types_p) {
00326 
00327       declNode * t = ( * types_p );
00328 
00329       const string & the_name = t->name();
00330       found = false;
00331 
00332       // -- Find the matching identifier in the parameter
00333       // list. Because of the way that identifier.list is defined in
00334       // the parser, this is actually a list of declNodes with no
00335       // types.
00336 
00337       for (ids_p = ids.begin(); ids_p != ids.end(); ++ids_p) {
00338 
00339         declNode * the_param = (*ids_p);
00340 
00341         if (the_param->name() == the_name) {
00342 
00343           found = true;  // name does exist
00344 
00345           if (! the_param->type()) {
00346             // if a name appears twice in the identifer list,
00347             //   it will be caught by DefineProc when its adds the
00348             //   formals to the scope of the body
00349 
00350             // -- Replace the identifier with the declaration
00351             //delete  the_param;
00352             (*ids_p) = t;
00353             found = true;
00354 
00355             break;
00356           }
00357           else {
00358             CBZ::SyntaxError(t->coord(),
00359                              string("multiple declarations for parameter `") + 
00360                              the_name + string("'"));
00361             break;
00362           }
00363         }
00364       }
00365 
00366       if (! found)
00367         CBZ::SyntaxError(t->coord(),
00368                          string("declaration for nonexistent parameter `") + 
00369                          the_name + string("'"));
00370 
00371     } // END for types
00372 
00373     //delete types;
00374 
00375   } // END if types
00376 
00377   // check for missing declarations
00378   
00379   for (ids_p = ids.begin(); ids_p != ids.end(); ++ids_p) {
00380 
00381     declNode * dec = (*ids_p);
00382 
00383     if (! dec->type()) {
00384 
00385       // -- Issue a warning and give the parameter a default type..
00386 
00387       CBZ::Warning(2, dec->coord(),
00388                    string("parameter `") + dec->name() + 
00389                    string("' defaults to signed int"));
00390 
00391       dec->type(new primNode(dec->coord()));
00392     }
00393   }
00394 }
00395 
00396 // ------------------------------------------------------------
00397 //  Walker
00398 // ------------------------------------------------------------
00399 
00400 void funcNode::visit(Visitor * the_visitor) 
00401 {
00402   the_visitor->at_func(this);
00403 }
00404 
00405 void funcNode::walk(Walker & the_walker)
00406 {
00407   Walker::Order ord = the_walker.order(); 
00408 
00409   if (ord == Walker::Preorder || ord == Walker::Both)
00410     the_walker.at_func(this, Walker::Preorder);
00411 
00412   if (the_walker.depth() == Walker::Subtree) {
00413     // -- Visit the children 
00414 
00415     list_walker(args(), the_walker);
00416 
00417     if (returns())
00418       returns()->walk(the_walker);
00419   }
00420 
00421   if (ord == Walker::Postorder || ord == Walker::Both)
00422     the_walker.at_func(this, Walker::Postorder);
00423 }
00424 
00425 // ------------------------------------------------------------
00426 // Output
00427 // ------------------------------------------------------------
00428 
00429 void funcNode::output_type(output_context & ct, Node * parent, Assoc context, Type_qualifiers q)
00430 {
00431   if (context == Left) {
00432     const string & qs = type_qualifiers_name();
00433 
00434     if (! qs.empty())
00435       ct.space();
00436     ct << qs;
00437 
00438     returns()->output_type(ct, this, Left, q);
00439   }
00440   else {
00441     ct << '(';
00442     if (is_knr()) {
00443         // output old-style declarator.
00444         // why not stick in the prototypes?
00445         // because ANSI C is more strict about
00446         // arguments matching and will complain
00447         // if the number of args doesn't match.
00448         // it will also try to promote things
00449         // that the author might just want
00450         // reinterpreted.
00451         decl_list_p i=args().begin(); 
00452         for (;;) {
00453             ct << (*i)->name();
00454             i++;
00455             if (i == args().end()) break;
00456             ct << ", ";
00457         }
00458         ct << ")\n";
00459         output_delim_list(args(), ct, this, ';');
00460         ct << ';';
00461     } else {
00462         output_delim_list(args(), ct, this, ',');
00463         ct << ')';
00464     }
00465 
00466     returns()->output_type(ct, this, Right, q);
00467   }
00468 }
00469 
00470 // ------------------------------------------------------------
00471 //  Changer
00472 // ------------------------------------------------------------
00473 
00474 Node * funcNode::change(Changer & the_changer, bool redispatch)
00475 {
00476   Changer::Order ord = the_changer.order(); 
00477   funcNode * the_func = this;
00478 
00479   if ((ord == Changer::Preorder || ord == Changer::Both) && ! redispatch)
00480     the_func = (funcNode *) the_changer.at_func(the_func, Changer::Preorder);
00481 
00482   if (the_func) {
00483 
00484     if (the_func != this)
00485       return the_func->change(the_changer, true);
00486 
00487     change_list(the_func->args(), the_changer);
00488 
00489     typeNode * old_returns = the_func->returns();
00490     if (old_returns) {
00491       typeNode * new_returns = (typeNode *) old_returns->change(the_changer);
00492       if (old_returns != new_returns) {
00493         //if (the_changer.delete_old())
00494           //delete old_returns;
00495         the_func->returns(new_returns);
00496       }
00497     }
00498 
00499   }
00500 
00501   if ((ord == Changer::Postorder || ord == Changer::Both) && ! redispatch)
00502     the_func = (funcNode *) the_changer.at_func(the_func, Changer::Postorder);
00503 
00504   return the_func;
00505 }
00506 
00507 
00508 // ------------------------------------------------------------
00509 // Destructor
00510 // ------------------------------------------------------------
00511 
00512 funcNode::~funcNode()
00513 {
00514   //delete_list(_args);
00515 }

Generated on August 27, 2003
Back to the C-Breeze home page