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  

semcheck.cc

Go to the documentation of this file.
00001 // $Id: semcheck.cc,v 1.13 2003/08/07 23:13:52 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 "semcheck.h"
00040 #include "print_walker.h"
00041 #include "ref_clone_changer.h"
00042 
00043 // ------------------------------------------------------------
00044 // Main semantic checker
00045 // ------------------------------------------------------------
00046 
00047 bool semcheck_walker::showErrors = true;
00048 
00049 void semcheck_walker::check(unitNode * u, bool verbose)
00050 {
00051   semcheck_walker sw;
00052   bool old_val = showErrors;
00053   showErrors = verbose;
00054 
00055   u->walk(sw);
00056 
00057   showErrors = old_val;
00058 }
00059 
00060 // ------------------------------------------------------------
00061 // Check different node types
00062 // ------------------------------------------------------------
00063 
00064 void semcheck_walker::at_exprstmt(exprstmtNode * the_exprstmt, Order ord)
00065 {
00066   if (the_exprstmt->expr())
00067     semcheck_expr_visitor::check(the_exprstmt->expr());
00068 }
00069 
00070 void semcheck_walker::at_suespec(suespecNode * the_suespec, Order ord)
00071 {
00072   // -- Compute the actual values for each enum
00073 
00074   if (the_suespec->owner() == Enum) {
00075     decl_list & decls = the_suespec->fields();
00076     int cur_val = 0;            // First enum defaults to zero
00077     char buf[32];
00078 
00079     for (decl_list_p p = decls.begin();
00080          p != decls.end();
00081          ++p)
00082       {
00083         declNode * cur = *p;
00084 
00085         if (cur->init()) {
00086           exprNode * e = cur->init();
00087 
00088           // -- Try to compute a constant value
00089 
00090           semcheck_expr_visitor::check(e);
00091           e->eval();
00092           if (e->value().basic().is_integer())
00093             cur_val = e->value().Integer();
00094           else
00095             break;
00096         }
00097         else {
00098           sprintf(buf,"%d",cur_val);
00099           constNode * val = new constNode(constant(cur_val),
00100                                           buf, the_suespec->coord());
00101           cur->init(val);
00102         }
00103         cur_val++;
00104       }
00105   }
00106 }
00107 
00108 void semcheck_walker::at_decl(declNode * the_decl, Order ord) {
00109   if ( the_decl->init() )
00110     semcheck_expr_visitor::check(the_decl->init());
00111 }
00112 
00113 void semcheck_walker::at_return(returnNode * the_return, Order ord) {
00114   if ( the_return->expr() )
00115     semcheck_expr_visitor::check(the_return->expr());
00116 }
00117 
00118 void semcheck_walker::at_selection(selectionNode * the_selection, Order ord) {
00119   if ( the_selection->expr() )
00120     semcheck_expr_visitor::check(the_selection->expr());
00121 }
00122 
00123 void semcheck_walker::at_case(caseNode * the_case, Order ord) {
00124   if ( the_case->expr() )
00125     semcheck_expr_visitor::check(the_case->expr());
00126 }
00127 
00128 void semcheck_walker::at_loop(loopNode * the_loop, Order ord) {
00129   if ( the_loop->cond() )
00130     semcheck_expr_visitor::check(the_loop->cond());
00131 }
00132 
00133 void semcheck_walker::at_for(forNode * the_for, Order ord) {
00134   if ( the_for->init() )
00135     semcheck_expr_visitor::check(the_for->init());
00136   if ( the_for->cond() )
00137     semcheck_expr_visitor::check(the_for->cond());
00138   if ( the_for->next() )
00139     semcheck_expr_visitor::check(the_for->next());
00140 }
00141 
00142 // ------------------------------------------------------------
00143 // Expression checker
00144 // ------------------------------------------------------------
00145 
00146 // Remove any stale type information from expressions
00147 
00148 class remove_stale_type_walker : public Walker
00149 {
00150 public:
00151 
00152   remove_stale_type_walker()
00153     : Walker(Postorder, Subtree)
00154   {}
00155 
00156   virtual void at_expr(exprNode * the_expr, Order ord)
00157   {
00158     return;
00159     // -- Remove type information from everything but constNode and
00160     // the casts.  Also operandNodes, b/c they don't actually store their
00161     // type information
00162 
00163     if ((the_expr->typ() != Const) &&
00164         (the_expr->typ() != Cast) &&
00165         (the_expr->typ() != Operand)) {
00166       typeNode * t = the_expr->get_type();
00167       //delete t;
00168     }
00169   }
00170 };
00171 
00172 // -- Check one expression tree
00173 
00174 void semcheck_expr_visitor::check(exprNode * e)
00175 {
00176   // -- Remove any old type information
00177   remove_stale_type_walker rstw;
00178 
00179   e->walk(rstw);
00180 
00181   // -- Rebuild the types
00182 
00183   semcheck_expr_visitor sv;
00184 
00185   e->visit(&sv);
00186 }
00187 
00188 // ------------------------------------------------------------
00189 // Visitor functions
00190 // ------------------------------------------------------------
00191 
00192 void semcheck_expr_visitor::at_const(constNode * the_const)
00193 {
00194   // -- Nothing to do for constants
00195 }
00196 
00197 void semcheck_expr_visitor::at_id(idNode * the_id)
00198 {
00199   // -- Set the type from it's declaration...
00200 
00201   declNode * d = the_id->decl();
00202   if (d) {
00203     typeNode * t = d->/* no_tdef_ */ type();
00204     if (t) {
00205       the_id->type((typeNode *) ref_clone_changer::clone(t, false));
00206       return;
00207     }
00208   }
00209   // -- Undeclared identifiers default to void type
00210 
00211   the_id->type(default_type());
00212 }
00213 
00214 void semcheck_expr_visitor::at_binary(binaryNode * the_binary)
00215 {
00216   typeNode * ty;
00217 
00218   // -- Check the sub-expressions...
00219 
00220   the_binary->left()->visit(this);
00221   the_binary->right()->visit(this);
00222 
00223   // -- Depends on the operation...
00224 
00225   exprNode * lhs = the_binary->get_left();
00226   exprNode * rhs = the_binary->get_right();
00227 
00228   unsigned int opid = the_binary->op()->id();
00229 
00230   if (opid == Operator::Index) {
00231 
00232     // --
00233     // -- Array subscript (ANSI 6.3.2.1)
00234     // --
00235 
00236     // -- Perform integral promotion on the index argument...
00237 
00238     rhs = exprNode::integral_promotions(rhs);
00239 
00240     // -- Index must be an integer
00241 
00242     if (! rhs->no_tdef_type()->is_integer())
00243       if (semcheck_walker::showErrors)
00244         CBZ::SyntaxError(rhs->coord(), "Array subscript must be an integral type");
00245 
00246     // -- Name must be an array or pointer to some_type
00247 
00248     typeNode * nt = lhs->no_tdef_type();
00249 
00250     if ((nt->typ() != Array) && (nt->typ() != Ptr)) {
00251       if (semcheck_walker::showErrors)
00252         CBZ::SyntaxError(lhs->coord(),
00253                          "Array subscript must be applied to an array or ptr type");
00254       ty = default_type();
00255     }
00256     else {
00257 
00258       // -- If the name is pointer to some_type, then the result is some_type
00259 
00260       ty = (typeNode *) ref_clone_changer::clone(nt->type(), false);
00261     }
00262   }
00263   else {
00264 
00265     // -- Regular binary operators
00266     // -- Perform the type checking
00267 
00268     ty = check_binary(opid, lhs, rhs, &lhs, &rhs);
00269   }
00270 
00271   // -- Update the node
00272 
00273   the_binary->type(ty);
00274   the_binary->left(lhs);
00275   the_binary->right(rhs);
00276 }
00277 
00278 void semcheck_expr_visitor::at_unary(unaryNode * the_unary)
00279 {
00280   // -- Check the sub-expressions...
00281 
00282   // djimenez
00283   // sizeof(type) doesn't have an expr(), so we have to handle it specially:
00284   // we assume the sizeof_type() field is OK and just make
00285   // this expression of type unsigned int
00286 
00287   if (the_unary->op()->id() == Operator::SIZEOF && the_unary->sizeof_type()) {
00288         typeNode *ty = new primNode(basic_type::UInt);
00289         the_unary->type(ty);
00290         return;
00291   }
00292 
00293   the_unary->expr()->visit(this);
00294 
00295   // -- Depends on the operation...
00296 
00297   exprNode * ex = the_unary->get_expr();
00298 
00299   unsigned int opid = the_unary->op()->id();
00300 
00301   // -- Perform the type checking
00302 
00303   typeNode * ty = check_unary(opid, ex, &ex);
00304 
00305   // -- Update the node
00306 
00307   the_unary->type(ty);
00308   the_unary->expr(ex);
00309 }
00310 
00311 // --
00312 // -- Cast (ANSI 6.3.4)
00313 // --
00314 
00315 void semcheck_expr_visitor::at_cast(castNode * the_cast)
00316 {
00317   // -- Check the sub-expressions...
00318 
00319   the_cast->expr()->visit(this);
00320 
00321   // -- Checks are TBD
00322 
00323   // -- Automatically converts to the given type
00324 }
00325 
00326 // --
00327 // -- Comma (ANSI 6.3.17)
00328 // --
00329 
00330 void semcheck_expr_visitor::at_comma(commaNode * the_comma)
00331 {
00332   // -- Check the sub-expressions...
00333 
00334   list_visitor(the_comma->exprs(), this);
00335 
00336   // -- Result gets the type of the last expression
00337 
00338   typeNode * result_type = the_comma->exprs().back()->type();
00339   the_comma->type((typeNode *) ref_clone_changer::clone(result_type, false));
00340 }
00341 
00342 // --
00343 // -- Ternary operator (ANSI 6.3.15)
00344 // --
00345 
00346 void semcheck_expr_visitor::at_ternary(ternaryNode * the_ternary)
00347 {
00348   // -- Check the sub-expressions...
00349 
00350   the_ternary->cond()->visit(this);
00351   the_ternary->true_br()->visit(this);
00352   the_ternary->false_br()->visit(this);
00353   // djimenez - I think this might fix something
00354   typeNode *result_type = the_ternary->false_br()->type();
00355   the_ternary->type((typeNode *) ref_clone_changer::clone(result_type, false));
00356 
00357   // djimenez - done 
00358 
00359   // -- TBD Rules, rules, rules
00360 }
00361 
00362 // --
00363 // -- Function call (ANSI 6.3.2.2)
00364 // --
00365 
00366 void semcheck_expr_visitor::at_call(callNode * the_call)
00367 {
00368   // -- Check the sub-expressions...
00369 
00370   the_call->name()->visit(this);
00371   list_visitor(the_call->args(), this);
00372 
00373   // -- The name should be a funcNode or ptr to funcNode
00374 
00375   bool ok = false;
00376   typeNode * ft = the_call->name()->no_tdef_type();
00377   typeNode * ret = 0;
00378 
00379   if (ft->typ() == Func) {
00380     ok = true;
00381     ret = ft->no_tdef_type();
00382   }
00383   else
00384     if (ft->typ() == Ptr) {
00385       typeNode * subtype = ft->no_tdef_type();
00386       if (subtype->typ() == Func) {
00387         ok = true;
00388         ret = subtype->no_tdef_type();
00389       }
00390     }
00391 
00392   if (ok) {
00393 
00394     // -- Return type may not be array 
00395 
00396     if (ret->typ() == Array)
00397       if (semcheck_walker::showErrors)
00398         CBZ::SyntaxError(the_call->coord(),
00399                          "Functions may not return arrays");
00400 
00401     // -- Type of the call is the return type of the function
00402 
00403     the_call->type( (typeNode *) ref_clone_changer::clone(ret, false));
00404   }
00405 }
00406 
00407 // --
00408 // --
00409 // --
00410 
00411 void semcheck_expr_visitor::at_initializer(initializerNode * the_initializer)
00412 {
00413   // -- Check the sub-expressions...
00414 
00415   list_visitor(the_initializer->exprs(), this);
00416 }
00417 
00418 // ------------------------------------------------------------
00419 // Checking functions
00420 // ------------------------------------------------------------
00421 
00422 typeNode * semcheck_expr_visitor::check_unary(unsigned int opid, exprNode * ex,
00423                        exprNode ** new_ex)
00424 {
00425   typeNode * result_type = 0;
00426 
00427   // --
00428   // -- Increment and decrement (ANSI 6.3.2.4, ANSI 6.3.3.1)
00429   // --
00430 
00431   if ((opid == Operator::ICR) ||
00432       (opid == Operator::POSTINC) ||
00433       (opid == Operator::PREINC) ||
00434       (opid == Operator::DECR) ||
00435       (opid == Operator::POSTDEC) ||
00436       (opid == Operator::PREDEC)) {
00437 
00438     // -- Apply integral promotions..
00439 
00440     ex = exprNode::integral_promotions(ex);
00441 
00442     // -- Must be scalar and lvalue
00443 
00444     if (! ex->no_tdef_type()->is_scalar() ||
00445         ! ex->is_lvalue()) {
00446       if (semcheck_walker::showErrors)
00447         CBZ::SyntaxError(ex->coord(), "Argument to increment/decrement must be a scalar "
00448                          "and must be a modifiable lvalue");
00449       result_type = default_type();
00450     }
00451     else {
00452       // -- Result type is the same
00453 
00454       result_type = (typeNode *) ref_clone_changer::clone(ex->type(), false);
00455     }
00456   }
00457 
00458   // --
00459   // -- Address and indirection (ANSI 6.3.3.2)
00460   // --
00461 
00462   if (opid == Operator::INDIR) {
00463 
00464     // -- Argument must be point to something
00465 
00466     if (ex->no_tdef_type()->typ() != Ptr 
00467         // djimenez - an array can be "dereferenced" as well
00468         && ex->no_tdef_type()->typ() != Array) {
00469       if (semcheck_walker::showErrors)
00470         CBZ::SyntaxError(ex->coord(),
00471                          "Cannot dereference a non-pointer");
00472       result_type = default_type();
00473     }
00474     else {
00475 
00476       // -- Follow the pointer...
00477 
00478       result_type = (typeNode *) ref_clone_changer::clone(ex->no_tdef_type()->type(), false) ;
00479     }
00480   }
00481 
00482   if (opid == Operator::ADDRESS) {
00483 
00484     // -- Must be an lvalue, and cannot be "register" or bitfield (TBD)
00485 
00486     if (! ex->is_lvalue()) {
00487       if (semcheck_walker::showErrors)
00488         CBZ::SyntaxError(ex->coord(),
00489                          "Cannot take the address of a non-lvalue");
00490       result_type = default_type();
00491     }
00492     else {
00493       // -- Result type is pointer to type of expression
00494 
00495       typeNode * base = (typeNode *) ref_clone_changer::clone(ex->type(), false);
00496       result_type = new ptrNode(typeNode::NONE, base, base->coord());
00497 
00498       /*
00499       output_context oc(cout);
00500       cout << "Type in:";
00501       print_walker::print(ex->type(), cout);
00502       cout << "Type out:";
00503       print_walker::print(result_type, cout);      
00504       */
00505     }
00506   }
00507 
00508   // --
00509   // -- Unary +/-
00510   // --
00511 
00512   if ((opid == Operator::UPLUS) ||
00513       (opid == Operator::UMINUS)) {
00514 
00515     // -- Apply integral promotions..
00516 
00517     ex = exprNode::integral_promotions(ex);
00518 
00519     // -- Must be arithmetic
00520 
00521     typeNode * t = ex->no_tdef_type();
00522 
00523     if ( ! t->is_arithmetic() ) {
00524       if (semcheck_walker::showErrors)
00525         CBZ::SyntaxError(ex->coord(),
00526                          "Argument to unary +/- must be arithmetic");
00527       result_type = default_type();
00528     }
00529     else {
00530       // -- Result is the same type
00531 
00532       result_type = (typeNode *) ref_clone_changer::clone(t, false);
00533     }
00534   }
00535 
00536   // --
00537   // -- Unary ~
00538   // --
00539 
00540   if (opid == '~') {
00541 
00542     // -- Apply integral promotions..
00543 
00544     ex = exprNode::integral_promotions(ex);
00545 
00546     // -- Must be integral
00547 
00548     typeNode * t = ex->no_tdef_type();
00549     if ( ! t->is_integer() ) {
00550       if (semcheck_walker::showErrors)
00551         CBZ::SyntaxError(ex->coord(),
00552                          "Argument to unary ~ must be integral");
00553       result_type = default_type();
00554     }
00555     else {
00556       // -- Result is the same type
00557 
00558       result_type = (typeNode *) ref_clone_changer::clone(t, false);
00559     }
00560   }
00561 
00562   // --
00563   // -- Unary !
00564   // --
00565 
00566   if (opid == '!') {
00567 
00568     // -- Must be scalar
00569 
00570     typeNode * t = ex->no_tdef_type();
00571     if ( ! t->is_scalar() ) {
00572       if (semcheck_walker::showErrors)
00573         CBZ::SyntaxError(ex->coord(),
00574                          "Argument to unary ! must be scalar");
00575       result_type = default_type();
00576     }
00577     else {
00578       // -- Result is int
00579 
00580       result_type = new primNode(ex->coord());
00581     }
00582   }
00583 
00584   // --
00585   // -- Sizeof (ANSI 6.3.3.4)
00586   // --
00587 
00588   if (opid == Operator::SIZEOF) {
00589 
00590     // -- Checks are TBD
00591 
00592     // -- Result is int
00593 
00594     result_type = new primNode(ex->coord());
00595   }
00596 
00597   * new_ex = ex;
00598 
00599   return result_type;
00600 }
00601 
00602 typeNode * semcheck_expr_visitor::check_binary(unsigned int opid, exprNode * lhs, exprNode * rhs,
00603                         exprNode ** new_lhs, exprNode ** new_rhs)
00604 {
00605   typeNode * result_type = 0;
00606   // --
00607   // -- Struct/Union access...
00608   // --
00609 
00610   if ((opid == Operator::ARROW) ||
00611       (opid == '.')) {
00612     typeNode * t = lhs->no_tdef_type();
00613 
00614     // -- Only apply -> to a pointer
00615 
00616     if (opid == Operator::ARROW) {
00617       if (t->typ() != Ptr && t->typ() != Array) {
00618         if (semcheck_walker::showErrors)
00619           CBZ::SyntaxError(lhs->coord(),
00620                            "Left operand of \"->\" must be a pointer");
00621       }
00622       else
00623         t = t->no_tdef_type();
00624     }
00625 
00626     // -- Make sure the LHS is a struct or union
00627 
00628     if ((t->typ() != Struct) &&
00629         (t->typ() != Union)) {
00630       if (semcheck_walker::showErrors)
00631         CBZ::SyntaxError(lhs->coord(),
00632                          "Left operand of \"->\"/\".\" must be a struct or union");
00633       result_type = default_type();
00634     }
00635     else {
00636       sueNode * sue = (sueNode *) t;
00637       suespecNode * sp = sue->spec();
00638       idNode * field = (idNode *) rhs;
00639       string & nm = field->name();
00640 
00641       // -- Try to find the field
00642 
00643       bool found = false;
00644       declNode * field_decl = sp->find_field(nm);
00645       typeNode * field_type = 0;
00646 
00647       if (field_decl) {
00648         field_type = field_decl->type();
00649         found = true;
00650       }
00651 
00652       // -- Set the decl of the field name to point to the field
00653       // declaration.
00654 
00655       field->decl(field_decl);
00656 
00657       // -- If found, the result type is the type of the field
00658 
00659       if (found) {
00660         if (field_type->typ() == Tdef) {
00661                 if (((tdefNode *)field_type)->def() == NULL) 
00662       if (semcheck_walker::showErrors)
00663         CBZ::SyntaxError(rhs->coord(), "internal error: can't"
00664                          " find a typedef definition!");
00665         }
00666         result_type = (typeNode *) ref_clone_changer::clone(field_type, false);
00667       }
00668       else {
00669       if (semcheck_walker::showErrors)
00670         CBZ::SyntaxError(rhs->coord(),
00671                          string("Struct/union \"") + sp->name() + "\" has no field \"" +
00672                          nm + "\".");
00673         result_type = default_type();
00674       }
00675     }
00676 
00677   }
00678 
00679   // --
00680   // -- Multiplicative operators (ANSI 6.3.5)
00681   // --
00682 
00683   if ((opid == '*') ||
00684       (opid == '/') ||
00685       (opid == '%')) {
00686 
00687     // -- Apply the arithmetic conversions
00688 
00689     pair<exprNode *, exprNode *> res =
00690       exprNode::usual_arithmetic_conversions(lhs, rhs);
00691     lhs = res.first;
00692     rhs = res.second;
00693 
00694     // -- Get the resulting types
00695 
00696     typeNode * lt = lhs->no_tdef_type();
00697     typeNode * rt = rhs->no_tdef_type();
00698 
00699     // -- Mod requires integral operands
00700 
00701     if ((opid == '%') &&
00702         (! lt->is_integer() ||
00703          ! rt->is_integer())) {
00704       if (semcheck_walker::showErrors)
00705         CBZ::SyntaxError(lhs->coord(),
00706                          "The mod operator requires integral operands");
00707       result_type = default_type();
00708     }
00709     else
00710 
00711       // -- Mult/div require arithmetic operands
00712 
00713       if (((opid == '*') ||
00714            (opid == '/')) &&
00715           (! lt->is_arithmetic() ||
00716            ! rt->is_arithmetic())) {
00717       if (semcheck_walker::showErrors)
00718         CBZ::SyntaxError(lhs->coord(),
00719                          "The * and / operators require arithmetic operands");
00720         result_type = default_type();
00721       }
00722       else
00723         result_type = (typeNode *) ref_clone_changer::clone(lt, false);
00724   }
00725 
00726   // --
00727   // -- Additive operators (ANSI 6.3.6)
00728   // --
00729 
00730   if ((opid == '+') ||
00731       (opid == '-')) {
00732 
00733     typeNode * lt = lhs->no_tdef_type();
00734     typeNode * rt = rhs->no_tdef_type();
00735 
00736     // -- Check the normal arithmetic case
00737 
00738     if (lt->is_arithmetic() && rt->is_arithmetic()) {
00739 
00740       // -- Apply the arithmetic conversions
00741 
00742       pair<exprNode *, exprNode *> res =
00743         exprNode::usual_arithmetic_conversions(lhs, rhs);
00744       lhs = res.first;
00745       rhs = res.second;
00746 
00747       result_type = (typeNode *) ref_clone_changer::clone(lhs->type(), false);
00748     }
00749     else
00750       // -- Check the subtraction of pointers case
00751 
00752       if (lt->is_pointer() && rt->is_pointer()) {
00753 
00754         // -- This is only allowed for subtraction
00755 
00756         if (opid == '+') {
00757       if (semcheck_walker::showErrors)
00758         CBZ::SyntaxError(lhs->coord(),
00759                          "Addition of pointers is not allowed");
00760           result_type = default_type();
00761         }
00762         else
00763           // -- TBD: pointers must be compatible
00764           // djimenez - ANSI 6.3.6 - the result of pointer
00765           // subtraction is an implementation defined signed
00766           // integral type (not a pointer).
00767 
00768           //result_type = (typeNode *) ref_clone_changer::clone(lt, false);
00769           result_type = new primNode (basic_type::SInt);
00770       }
00771       else
00772         // -- Check the pointer +/- number case
00773 
00774         if (lt->is_pointer() && rt->is_integer()) {
00775 
00776           // -- TBD Do we need integral promotion here?
00777           
00778           result_type = (typeNode *) ref_clone_changer::clone(lt, false);
00779         }
00780         else
00781           // -- Check the number + pointer case
00782 
00783           if (rt->is_pointer() && lt->is_integer() && (opid == '+')) {
00784 
00785             // -- TBD Do we need integral promotion here?
00786           
00787             result_type = (typeNode *) ref_clone_changer::clone(rt, false);
00788           }
00789           else {
00790             // -- None of those cases matched
00791       if (semcheck_walker::showErrors)
00792         CBZ::SyntaxError(lhs->coord(),
00793                          "Illegal operands for + or -");
00794             result_type = default_type();
00795           }
00796   }
00797 
00798   // --
00799   // -- Bitwise shift operators (ANSI 6.3.7)
00800   // --
00801 
00802   if ((opid == Operator::LS) ||
00803       (opid == Operator::RS)) {
00804 
00805     // -- Perform integral promotions
00806 
00807     lhs = exprNode::integral_promotions(lhs);
00808     rhs = exprNode::integral_promotions(rhs);
00809 
00810     // -- Both arguments must be integral
00811 
00812     if (! lhs->no_tdef_type()->is_integer() ||
00813         ! rhs->no_tdef_type()->is_integer()) {
00814       if (semcheck_walker::showErrors)
00815         CBZ::SyntaxError(lhs->coord(),
00816                          "Arguments to bitwise shift must be integral");
00817       result_type = default_type();
00818     }
00819     else {
00820       // -- Apply the arithmetic conversions
00821       
00822       pair<exprNode *, exprNode *> res =
00823         exprNode::usual_arithmetic_conversions(lhs, rhs);
00824       lhs = res.first;
00825       rhs = res.second;
00826 
00827       result_type = (typeNode *) ref_clone_changer::clone(lhs->no_tdef_type(), false);
00828     }
00829   }
00830 
00831   // --
00832   // -- Relational operators (ANSI 6.3.8)
00833   // --
00834 
00835   if ((opid == '>') ||
00836       (opid == '<') ||
00837       (opid == Operator::GE) ||
00838       (opid == Operator::LE)) {
00839 
00840     typeNode * lt = lhs->no_tdef_type();
00841     typeNode * rt = rhs->no_tdef_type();
00842 
00843     // -- Check the normal arithmetic case
00844 
00845     if (lt->is_arithmetic() && rt->is_arithmetic()) {
00846 
00847       // -- Apply the arithmetic conversions
00848 
00849       pair<exprNode *, exprNode *> res =
00850         exprNode::usual_arithmetic_conversions(lhs, rhs);
00851       lhs = res.first;
00852       rhs = res.second;
00853 
00854       // -- Result type is int
00855 
00856       result_type = new primNode(lhs->coord());
00857     }
00858     else
00859       // -- Check the comparison of pointers
00860 
00861       if (lt->is_pointer() && rt->is_pointer()) {
00862 
00863         // -- TBD check pointer compatibility
00864 
00865         // -- Result type is int
00866 
00867         result_type = new primNode(lhs->coord());
00868       }
00869       else {
00870         // -- None of those cases matched
00871       if (semcheck_walker::showErrors)
00872         CBZ::SyntaxError(lhs->coord(),
00873                          "Illegal operands for comparison");
00874         result_type = default_type();
00875       }
00876   }
00877 
00878   // --
00879   // -- Equality operators (ANSI 6.3.9)
00880   // --
00881 
00882   if ((opid == Operator::EQ) ||
00883       (opid == Operator::NE)) {
00884 
00885     typeNode * lt = lhs->no_tdef_type();
00886     typeNode * rt = rhs->no_tdef_type();
00887 
00888     // -- Check the normal arithmetic case
00889 
00890     if (lt->is_arithmetic() && rt->is_arithmetic()) {
00891 
00892       // -- Apply the arithmetic conversions
00893 
00894       pair<exprNode *, exprNode *> res =
00895         exprNode::usual_arithmetic_conversions(lhs, rhs);
00896       lhs = res.first;
00897       rhs = res.second;
00898 
00899       // -- Result type is int
00900 
00901       result_type = new primNode(lhs->coord());
00902     }
00903     else
00904       // -- Check the comparison of pointers
00905 
00906       if (lt->is_pointer() && rt->is_pointer()) {
00907 
00908         // -- TBD check pointer compatibility
00909         // -- Result type is int
00910 
00911         result_type = new primNode(lhs->coord());
00912       }
00913       else
00914         // -- Check comparison of pointer and constant
00915 
00916         if ((lt->is_pointer() && (rt->typ() == Prim)) ||
00917             (rt->is_pointer() && (lt->typ() == Prim))) {
00918 
00919           // -- TBD check pointer compatibility
00920           // -- Result type is int
00921 
00922           result_type = new primNode(lhs->coord());
00923         }
00924         else {
00925           // -- None of those cases matched
00926       if (semcheck_walker::showErrors)
00927         CBZ::SyntaxError(lhs->coord(),
00928                          "Illegal operands for comparison");
00929           result_type = default_type();
00930         }
00931   }
00932 
00933   // --
00934   // -- Bitwise AND, OR, XOR (ANSI 6.3.10 6.3.11 6.3.12)
00935   // --
00936 
00937   if ((opid == '&') ||
00938       (opid == '^') ||
00939       (opid == '|')) {
00940 
00941     // -- Perform integral promotions
00942 
00943     lhs = exprNode::integral_promotions(lhs);
00944     rhs = exprNode::integral_promotions(rhs);
00945 
00946     // -- Both arguments must be integral
00947 
00948     if (! lhs->no_tdef_type()->is_integer() ||
00949         ! rhs->no_tdef_type()->is_integer()) {
00950       if (semcheck_walker::showErrors)
00951         CBZ::SyntaxError(lhs->coord(),
00952                          "Arguments to bitwise operators must be integral");
00953       result_type = default_type();
00954     }
00955     else {
00956       // -- Apply the arithmetic conversions
00957 
00958       pair<exprNode *, exprNode *> res =
00959         exprNode::usual_arithmetic_conversions(lhs, rhs);
00960       lhs = res.first;
00961       rhs = res.second;
00962 
00963       result_type = (typeNode *) ref_clone_changer::clone(lhs->no_tdef_type(), false);
00964     }
00965   }
00966 
00967   // --
00968   // -- Logical AND, OR (ANSI 6.3.13 6.3.14)
00969   // --
00970 
00971   if ((opid == Operator::ANDAND) ||
00972       (opid == Operator::OROR)) {
00973 
00974     typeNode * lt = lhs->no_tdef_type();
00975     typeNode * rt = rhs->no_tdef_type();
00976 
00977     if (lt->is_scalar() && rt->is_scalar())
00978       result_type = new primNode(lhs->coord());
00979     else {
00980       if (semcheck_walker::showErrors)
00981         CBZ::SyntaxError(lhs->coord(),
00982                          "Arguments to &&/|| must be scalar");
00983       result_type = default_type();
00984     }
00985   }
00986 
00987   // --
00988   // -- Simple assignment (6.3.16.1)
00989   // --
00990 
00991   if (opid == '=') {
00992 
00993     if ( ! lhs->is_lvalue() ) {
00994       if (semcheck_walker::showErrors)
00995         CBZ::SyntaxError(lhs->coord(),
00996                          "Left-hand side of assignment must be a modifiable lvalue");
00997       result_type = default_type();
00998     }
00999     else {
01000 
01001       typeNode * lt = lhs->no_tdef_type();
01002       typeNode * rt = rhs->no_tdef_type();
01003 
01004       // TBD check assignment compatibility
01005 
01006       // -- If the types are not the same...
01007 
01008       if ( ! ( *lt <= *rt ))
01009         if (lt->is_arithmetic() &&
01010             rt->is_arithmetic()) {
01011 
01012           // -- Arithmetic types may be different..cast the RHS
01013 
01014           rhs = new castNode((typeNode *) ref_clone_changer::clone(lt, false),
01015                              rhs, true, rhs->coord());
01016           // -- Result type is that of the LHS
01017 
01018           result_type = (typeNode *) ref_clone_changer::clone(lt, false);
01019 
01020           // -- Remove qualifiers
01021 
01022           result_type->type_qualifiers(typeNode::NONE);
01023         }
01024         else {
01025           // djimenez
01026           // a void pointer can be assigned to any pointer type
01027           if (lt->typ() == Ptr 
01028                 && rt->typ() == Ptr 
01029                 && rt->type()->is_void()) {
01030                         result_type = (typeNode *) ref_clone_changer::clone(lt, false);
01031           } else {
01032             if (semcheck_walker::showErrors)
01033               CBZ::SyntaxError(lhs->coord(),
01034                                "Incompatible types for assignment");
01035             result_type = default_type();
01036           }
01037         }
01038       else {
01039 
01040         // -- Result type is that of the LHS
01041 
01042         result_type = (typeNode *) ref_clone_changer::clone(lt, false);
01043 
01044         // -- Remove qualifiers
01045 
01046         result_type->type_qualifiers(typeNode::NONE);
01047       }
01048     }
01049   }
01050 
01051   // --
01052   // -- Compound assignment (6.3.16.2)
01053   // --
01054 
01055   if (opid == Operator::MULTassign) {
01056     typeNode * rtype = check_binary('*', lhs, rhs, &lhs, &rhs);
01057     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01058     //delete rtype;
01059   }
01060 
01061   if (opid == Operator::DIVassign) {
01062     typeNode * rtype = check_binary('/', lhs, rhs, &lhs, &rhs);
01063     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01064     //delete rtype;
01065   }
01066 
01067   if (opid == Operator::MODassign) {
01068     typeNode * rtype = check_binary('%', lhs, rhs, &lhs, &rhs);
01069     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01070     //delete rtype;
01071   }
01072 
01073   if (opid == Operator::PLUSassign) {
01074     typeNode * rtype = check_binary('+', lhs, rhs, &lhs, &rhs);
01075 // djimenez
01076 // this is a little different from the other op*assigns because
01077 // we may need to do something like pointer += integer.
01078     typeNode * save = rhs->type();
01079     rhs->type (rtype);
01080     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01081     rhs->type (save);
01083   }
01084 
01085   if (opid == Operator::MINUSassign) {
01086 // same thing as above
01087     typeNode * rtype = check_binary('-', lhs, rhs, &lhs, &rhs);
01088     typeNode * save = rhs->type();
01089     rhs->type (rtype);
01090     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01091     rhs->type (save);
01092   }
01093 
01094   if (opid == Operator::LSassign) {
01095     typeNode * rtype = check_binary(Operator::LS, lhs, rhs, &lhs, &rhs);
01096     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01097     //delete rtype;
01098   }
01099 
01100   if (opid == Operator::RSassign) {
01101     typeNode * rtype = check_binary(Operator::RS, lhs, rhs, &lhs, &rhs);
01102     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01103     //delete rtype;
01104   }
01105 
01106   if (opid == Operator::ANDassign) {
01107     typeNode * rtype = check_binary('&', lhs, rhs, &lhs, &rhs);
01108     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01109     //delete rtype;
01110   }
01111 
01112   if (opid == Operator::ERassign) {
01113     typeNode * rtype = check_binary('^', lhs, rhs, &lhs, &rhs);
01114     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01115     //delete rtype;
01116   }
01117 
01118   if (opid == Operator::ORassign) {
01119     typeNode * rtype = check_binary('|', lhs, rhs, &lhs, &rhs);
01120     result_type = check_binary('=', lhs, rhs, &lhs, &rhs);
01121     //delete rtype;
01122   }
01123 
01124   * new_lhs = lhs;
01125   * new_rhs = rhs;
01126 
01127   return result_type;
01128 }
01129 
01130 typeNode * semcheck_expr_visitor::default_type()
01131 {
01132   return new primNode(typeNode::NONE, basic_type::Void);
01133 }
01134 

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