00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "c_breeze.h"
00039 #include "scope_walker.h"
00040 #include "id_lookup_walker.h"
00041
00042
00043
00044
00045
00046 id_lookup_walker::id_lookup_walker(unitNode * u, bool verb)
00047 : scope_walker(u),
00048 _verbose(verb)
00049 {}
00050
00051
00052
00053
00054
00055 class clear_ids_walker : public Walker
00056 {
00057 public:
00058
00059 static void clear(unitNode * u)
00060 {
00061 clear_ids_walker ciw;
00062
00063 u->walk(ciw);
00064 }
00065
00066 private:
00067
00068 clear_ids_walker()
00069 : Walker(Preorder, Subtree)
00070 {}
00071
00072 public:
00073
00074 virtual void at_tdef(tdefNode * the_tdef, Order ord)
00075 {
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 }
00087
00088 virtual void at_id(idNode * the_id, Order ord)
00089 {
00090 the_id->decl(0);
00091 }
00092 };
00093
00094
00095
00096
00097
00098 void id_lookup_walker::fixup(unitNode * u, bool verb)
00099 {
00100 id_lookup_walker idw(u,verb);
00101 clear_ids_walker::clear(u);
00102
00103 u->walk(idw);
00104 }
00105
00106 id_lookup_walker * id_lookup_walker::fixup_and_return(unitNode * u, bool verb)
00107 {
00108 id_lookup_walker * idw = new id_lookup_walker(u,verb);
00109 clear_ids_walker::clear(u);
00110
00111 u->walk(*idw);
00112
00113 return idw;
00114 }
00115
00116
00117
00118
00119
00120 void id_lookup_walker::conflict(const Coord & c, const string & msg)
00121 {
00122 if (_verbose)
00123 CBZ::SyntaxError(c, msg);
00124 }
00125
00126
00127
00128
00129
00130 void id_lookup_walker::at_proc(procNode * the_proc, Order ord)
00131 {
00132 if (ord == Preorder) {
00133
00134
00135
00136 enter_scope();
00137
00138 funcNode * f = (funcNode *) the_proc->decl()->type();
00139 decl_list & as = f->args();
00140
00141 for (decl_list_p p = as.begin(); p != as.end(); ++p) {
00142
00143 if ((*p)->datatype()->is_ellipsis() ||
00144 (*p)->datatype()->is_void())
00145 ;
00146 else
00147 if (! (*p)->name().empty()) {
00148
00149
00150
00151 declNode * a_decl = (declNode *) (*p);
00152 declNode * o_decl = ids()->insert(a_decl->name(), a_decl);
00153
00154
00155 if (o_decl)
00156 conflict(a_decl->coord(),
00157 string("formal `") +
00158 o_decl->name() + string("' used multiple times"));
00159
00160 } else
00161 conflict((*p)->coord(),
00162 string("argument without a name"));
00163 }
00164
00165
00166
00167 enter_scope();
00168 }
00169
00170 if (ord == Postorder) {
00171
00172
00173
00174 the_proc->decl()->decl_location(declNode::PROC);
00175
00176
00177
00178 exit_scope();
00179
00180
00181
00182 exit_scope();
00183 }
00184
00185 }
00186
00187 void id_lookup_walker::at_decl(declNode * the_decl, Order ord)
00188 {
00189
00190
00191
00192
00193 if (ord == Preorder) {
00194
00195 declNode * orig;
00196
00197
00198
00199 if (the_decl->name().empty()) {
00200
00201 if (in_formals()) {
00202 the_decl->decl_location(declNode::FORMAL);
00203 } else if (in_su()) {
00204 the_decl->decl_location(declNode::SU);
00205 }
00206 return;
00207 }
00208
00209
00210
00211 the_decl->references(0);
00212
00213
00214
00215 if (in_formals()) {
00216 the_decl->decl_location(declNode::FORMAL);
00217
00218 if ((the_decl->storage_class() != declNode::NONE) &&
00219 (the_decl->storage_class() != declNode::REGISTER)) {
00220 conflict(the_decl->coord(),
00221 string("illegal storage class for parameter `") +
00222 the_decl->name() + string("'"));
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 return;
00249 }
00250
00251
00252
00253 if ((the_decl->type()->typ() == Func) ||
00254 (the_decl->storage_class() == declNode::EXTERN)) {
00255
00256
00257
00258
00259 orig = externs()->insert(the_decl->name(), the_decl);
00260 if (orig) {
00261
00262 if (the_decl->type()->typ() == Func) {
00263 funcNode * the_func = (funcNode *) the_decl->type();
00264 funcNode * ofunc = (funcNode *) orig->type();
00265
00266
00267
00268 if (! ofunc->is_compatible_with(the_func)) {
00269 conflict(the_func->coord(),
00270 string("function identifier `") + the_decl->name() +
00271 "' redeclared\n Previous declaration: " +
00272 orig->coord().to_string());
00273 }
00274 }
00275 else {
00276
00277
00278
00279 if (! (* orig->type() == * the_decl->type()) ) {
00280 conflict(the_decl->coord(),
00281 string("extern `") + orig->name() +
00282 "' redeclared\n Previous declaration: " +
00283 orig->coord().to_string());
00284 }
00285 }
00286 }
00287 }
00288 else
00289 if (! in_su() ) {
00290
00291
00292
00293 orig = ids()->insert(the_decl->name(), the_decl);
00294 if ((orig) && (orig != the_decl)) {
00295 conflict(the_decl->coord(),
00296 string("variable `") + orig->name() +
00297 "' redeclared\n Previous declaration: " +
00298 orig->coord().to_string());
00299 }
00300 }
00301
00302
00303
00304 if (in_su())
00305 the_decl->decl_location(declNode::SU);
00306 else
00307 if (in_enum())
00308 the_decl->decl_location(declNode::ENUM);
00309 else
00310 if (symbol_level() == 0)
00311 the_decl->decl_location(declNode::TOP);
00312 else
00313 the_decl->decl_location(declNode::BLOCK);
00314 }
00315 }
00316
00317
00318
00319
00320
00321 void id_lookup_walker::at_call(callNode * the_call, Order ord)
00322 {
00323 if ((ord == Preorder) &&
00324 (the_call->name()->typ() == Id)) {
00325 idNode * id = (idNode *) the_call->name();
00326 declNode * var;
00327
00328 var = ids()->lookup(id->name());
00329 if (! var) {
00330 var = externs()->lookup(id->name());
00331 if (var) {
00332 id->decl(var);
00333 var->inc_references();
00334 }
00335 else {
00336
00337
00338 var = new declNode(id->name().c_str(), declNode::EXTERN,
00339 new funcNode(typeNode::NONE, (decl_list *)0,
00340 new primNode(id->coord()),
00341 id->coord()),
00342 (exprNode *)0,
00343 (exprNode *)0,
00344 id->coord());
00345
00346 var->decl_location(declNode::TOP);
00347 var->inc_references();
00348 id->decl(var);
00349
00350 unit()->undef_funcs().push_back(var);
00351
00352 declNode * tmp;
00353 tmp = ids()->insert(id->name(), var);
00354 tmp = externs()->insert(id->name(), var);
00355 }
00356 }
00357 }
00358 }
00359
00360 void id_lookup_walker::at_tdef(tdefNode * the_tdef, Order ord)
00361 {
00362 if (ord == Postorder) {
00363 declNode * d1 = ids()->lookup(the_tdef->name());
00364 declNode * d2 = externs()->lookup(the_tdef->name());
00365 declNode * d;
00366 if (d1 || d2) {
00367 if (d1) d = d1;
00368 if (d2) d = d2;
00369
00370 the_tdef->def(d->type());
00371 d->inc_references();
00372 }
00373 }
00374 }
00375
00376 void id_lookup_walker::at_id(idNode * the_id, Order ord)
00377 {
00378 if (ord == Postorder) {
00379
00380
00381
00382 if (the_id->decl())
00383 return;
00384
00385 declNode * d1 = ids()->lookup(the_id->name());
00386 declNode * d2 = externs()->lookup(the_id->name());
00387 declNode * d;
00388 if (d1 || d2) {
00389 if (d1)
00390 d = d1;
00391 else if (d2)
00392 d = d2;
00393
00394 the_id->decl(d);
00395 d->inc_references();
00396 }
00397 else
00398 conflict(the_id->coord(), string("undeclared variable `") +
00399 the_id->name() + string("'"));
00400 }
00401 }
00402
00403 void id_lookup_walker::at_binary(binaryNode * the_binary, Order ord)
00404 {
00405
00406
00407
00408 unsigned int opid = the_binary->op()->id();
00409
00410 if ((ord == Preorder) &&
00411 ((opid == Operator::ARROW) ||
00412 (opid == '.')) &&
00413 the_binary->left()->type())
00414 {
00415 idNode * field = (idNode *) the_binary->right();
00416 exprNode * left = the_binary->left();
00417 typeNode * left_type = left->no_tdef_type();
00418
00419 if (opid == Operator::ARROW) {
00420 if (left_type->typ() != Ptr)
00421 CBZ::SyntaxError(left->coord(),
00422 "Left operand of \"->\" must be a pointer");
00423
00424 left_type = left_type->no_tdef_type();
00425 }
00426
00427
00428
00429 if ((left_type->typ() != Struct) &&
00430 (left_type->typ() != Union)) {
00431 CBZ::SyntaxError(left->coord(),
00432 "Left operand of \"->\"/\".\" must be a struct or union");
00433 }
00434 else {
00435 sueNode * sue = (sueNode *) left_type;
00436 suespecNode * sp = sue->spec();
00437
00438 declNode * field_decl = sp->find_field(field->name());
00439
00440 field->decl(field_decl);
00441 if (field_decl)
00442 field_decl->inc_references();
00443 }
00444 }
00445 }