Synopsis - Cross-Reference
File: /Synopsis/Parsers/IDL/idlscope.cc1// -*- c++ -*- 2// Package : omniidl 3// idlscope.cc Created on: 1999/10/11 4// Author : Duncan Grisby (dpg1) 5// 6// Copyright (C) 1999 AT&T Laboratories Cambridge 7// 8// This file is part of omniidl. 9// 10// omniidl is free software; you can redistribute it and/or modify it 11// under the terms of the GNU General Public License as published by 12// the Free Software Foundation; either version 2 of the License, or 13// (at your option) any later version. 14// 15// This program is distributed in the hope that it will be useful, 16// but WITHOUT ANY WARRANTY; without even the implied warranty of 17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18// General Public License for more details. 19// 20// You should have received a copy of the GNU General Public License 21// along with this program; if not, write to the Free Software 22// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 23// 02111-1307, USA. 24// 25// Description: 26// 27// Scope manipulation 28 29// $Id: idlscope.cc,v 1.18.2.5 2005/05/10 22:07:31 dgrisby Exp $ 30// $Log: idlscope.cc,v $ 31// Revision 1.18.2.5 2005/05/10 22:07:31 dgrisby 32// Merge again. 33// 34// Revision 1.18.2.4 2005/01/06 23:11:14 dgrisby 35// Big merge from omni4_0_develop. 36// 37// Revision 1.18.2.3 2004/10/13 17:58:25 dgrisby 38// Abstract interfaces support; values support interfaces; value bug fixes. 39// 40// Revision 1.18.2.2 2004/02/16 10:10:33 dgrisby 41// More valuetype, including value boxes. C++ mapping updates. 42// 43// Revision 1.18.2.1 2003/03/23 21:01:44 dgrisby 44// Start of omniORB 4.1.x development branch. 45// 46// Revision 1.13.2.8 2003/03/20 10:24:27 dgrisby 47// Warn about use of CORBA 3 keywords in IDL. 48// 49// Revision 1.13.2.7 2001/10/29 17:42:43 dpg1 50// Support forward-declared structs/unions, ORB::create_recursive_tc(). 51// 52// Revision 1.13.2.6 2001/10/17 16:48:33 dpg1 53// Minor error message tweaks 54// 55// Revision 1.13.2.5 2001/06/08 17:12:23 dpg1 56// Merge all the bug fixes from omni3_develop. 57// 58// Revision 1.13.2.4 2000/12/05 17:45:19 dpg1 59// omniidl case sensitivity updates from omni3_develop. 60// 61// Revision 1.13.2.3 2000/10/27 16:31:10 dpg1 62// Clean up of omniidl dependencies and types, from omni3_develop. 63// 64// Revision 1.13.2.2 2000/10/10 10:18:51 dpg1 65// Update omniidl front-end from omni3_develop. 66// 67// Revision 1.11.2.6 2000/09/19 09:14:26 dpg1 68// Scope::Entry::Kind renamed to Scope::Entry::EntryKind to avoid 69// problems with over-keen compilers 70// 71// Revision 1.11.2.5 2000/08/29 15:20:28 dpg1 72// New relativeScope() function. New -i flag to enter interactive loop 73// after parsing 74// 75// Revision 1.11.2.4 2000/08/24 11:33:00 dpg1 76// Typo in error message % format string 77// 78// Revision 1.11.2.3 2000/08/04 09:10:27 dpg1 79// Fix look-up of escaped identifiers broken on 19 July. (Bug 14.) 80// 81// Revision 1.11.2.2 2000/08/01 09:46:47 dpg1 82// No longer complain about inheriting an operation into an interface 83// with the same name. 84// 85// Revision 1.11.2.1 2000/07/19 17:24:54 dpg1 86// omniidl complains if a name which differs only in case is found during 87// name look-up 88// 89// Revision 1.11 1999/11/26 11:33:44 dpg1 90// Bug in findWithInheritance() when inherited interface was not found. 91// 92// Revision 1.10 1999/11/17 17:23:54 dpg1 93// Minor bug when scoped name look-up encounters an identifier which does 94// not form a scope. 95// 96// Revision 1.9 1999/11/17 17:17:00 dpg1 97// Changes to remove static initialisation of objects. 98// 99// Revision 1.8 1999/11/11 10:20:30 dpg1 100// Bug in marking use of fully-scoped names. 101// 102// Revision 1.7 1999/11/04 17:16:55 dpg1 103// Changes for NT. 104// 105// Revision 1.6 1999/11/02 17:07:25 dpg1 106// Changes to compile on Solaris. 107// 108// Revision 1.5 1999/11/02 12:10:51 dpg1 109// Small bug in addUse() 110// 111// Revision 1.4 1999/11/02 10:35:03 dpg1 112// add...() functions now carry on regardless after a keyword clash, to 113// prevent later errors. 114// 115// Revision 1.3 1999/11/02 10:01:46 dpg1 116// Minor fixes. 117// 118// Revision 1.2 1999/10/29 10:01:50 dpg1 119// Global scope initialisation changed. 120// 121// Revision 1.1 1999/10/27 14:05:55 dpg1 122// *** empty log message *** 123// 124 125#include <idlscope.h> 126#include <idlast.h> 127#include <idlerr.h> 128#include <idlutil.h> 129#include <idlconfig.h> 130#include <idlrepoId.h> 131 132#include <string.h> 133 134// Global Scope pointers 135Scope* Scope::global_ = 0; 136Scope* Scope::current_ = 0; 137 138int n_builtins = 0; 139static Decl** builtins = 0; 140 141 142// ScopedName implementation 143ScopedName:: 144ScopedName(const char* identifier, IDL_Boolean absolute) : 145 absolute_(absolute) 146{ 147 Fragment* f = new Fragment(identifier); 148 scopeList_ = f; 149 last_ = f; 150} 151 152ScopedName:: 153ScopedName(const ScopedName* sn) : 154 scopeList_(0), last_(0), absolute_(sn->absolute()) 155{ 156 const Fragment *f; 157 158 for (f = sn->scopeList(); f; f = f->next()) 159 append(f->identifier()); 160} 161 162ScopedName:: 163ScopedName(const ScopedName::Fragment* frags, IDL_Boolean absolute) : 164 scopeList_(0), last_(0), absolute_(absolute) 165{ 166 const Fragment *f; 167 168 for (f = frags; f; f = f->next()) 169 append(f->identifier()); 170} 171 172 173ScopedName:: 174~ScopedName() 175{ 176 Fragment* f; 177 Fragment* g; 178 179 for (f = scopeList_; f; f = g) { 180 g = f->next_; 181 delete f; 182 } 183} 184 185char* 186ScopedName:: 187toString(IDL_Boolean qualify) const 188{ 189 int i; 190 Fragment* f; 191 192 i = (qualify && absolute_) ? 2 : 0; 193 194 for (f = scopeList_; f; f = f->next()) 195 i += strlen(f->identifier()) + 2; 196 197 char* str = new char [i-1]; 198 199 if (qualify && absolute_) { 200 str[0] = ':'; str[1] = ':'; 201 i = 2; 202 } 203 else 204 i = 0; 205 206 const char* fi; 207 for (f = scopeList_; f; f = f->next()) { 208 209 for (fi = f->identifier(); *fi; fi++, i++) 210 str[i] = *fi; 211 212 if (f->next()) { 213 str[i++] = ':'; str[i++] = ':'; 214 } 215 } 216 str[i] = '\0'; 217 return str; 218} 219 220IDL_Boolean 221ScopedName:: 222equal(const ScopedName* sn) const 223{ 224 if (sn->absolute() != absolute()) return 0; 225 226 Fragment *ourf, *theirf; 227 228 // Compare fragments 229 for (ourf = scopeList(), theirf = sn->scopeList(); 230 ourf && theirf; 231 ourf = ourf->next(), theirf = theirf->next()) { 232 233 if (strcmp(ourf->identifier(), theirf->identifier()) != 0) 234 return 0; 235 } 236 237 // If either name has fragments left, names aren't equal 238 if (ourf || theirf) return 0; 239 240 return 1; 241} 242 243void 244ScopedName:: 245append(const char* identifier) 246{ 247 Fragment* f = new Fragment(identifier); 248 249 if (last_) 250 last_->next_ = f; 251 else 252 scopeList_ = f; 253 254 last_ = f; 255} 256 257 258// Scope implementation 259 260Scope:: 261Entry:: 262Entry(const Scope* container, EntryKind k, const char* identifier, 263 Scope* scope, Decl* decl, IdlType* idltype, 264 Scope::Entry* inh_from, const char* file, int line) 265 266 : container_(container), kind_(k), identifier_(idl_strdup(identifier)), 267 scope_(scope), decl_(decl), idltype_(idltype), inh_from_(inh_from), 268 file_(idl_strdup(file)), line_(line), next_(0) 269{ 270 const ScopedName* sn = container->scopedName(); 271 272 if (identifier) { 273 if (sn) { 274 scopedName_ = new ScopedName(sn); 275 scopedName_->append(identifier); 276 } 277 else 278 scopedName_ = new ScopedName(identifier, 1); 279 } 280 else 281 scopedName_ = 0; 282} 283 284Scope:: 285Entry:: 286~Entry() 287{ 288 if (scopedName_) delete scopedName_; 289 if (identifier_) delete [] identifier_; 290 if (file_) delete [] file_; 291} 292 293void 294Scope:: 295EntryList:: 296merge(Scope::EntryList* ml) 297{ 298 EntryList* l; 299 IDL_Boolean add; 300 301 for (; ml; ml = ml->tail()) { 302 add = 1; 303 for (l=this; l; l = l->tail()) { 304 305 if (ml->head() == l->head()) { 306 add = 0; 307 break; 308 } 309 } 310 if (add) append(new EntryList(ml->head())); 311 } 312 delete ml; 313} 314 315 316Scope:: 317Scope(Scope* parent, Scope::Kind k, IDL_Boolean nestedUse, 318 const char* file, int line) 319 320 : parent_(parent), kind_(k), identifier_(0), scopedName_(0), 321 nestedUse_(nestedUse), entries_(0), last_(0), 322 inherited_(0), valueInherited_(0) 323{ 324 if (parent) 325 nestedUse_ |= parent->nestedUse(); 326} 327 328Scope:: 329Scope(Scope* parent, const char* identifier, Scope::Kind k, 330 IDL_Boolean nestedUse, 331 const char* file, int line) 332 333 : parent_(parent), kind_(k), nestedUse_(nestedUse), 334 inherited_(0), valueInherited_(0) 335{ 336 const ScopedName* psn = 0; 337 338 if (identifier && identifier[0] == '_') ++identifier; 339 identifier_ = idl_strdup(identifier); 340 341 if (parent) { 342 psn = parent->scopedName(); 343 nestedUse_ |= parent->nestedUse(); 344 } 345 346 if (psn) { 347 scopedName_ = new ScopedName(psn); 348 scopedName_->append(identifier); 349 } 350 else 351 scopedName_ = new ScopedName(identifier, 1); 352 353 // Add PARENT entry 354 entries_ = new Entry(this, Entry::E_PARENT, identifier, 0, 0, 0, 0, 355 file, line); 356 last_ = entries_; 357} 358 359Scope:: 360~Scope() 361{ 362 Entry *e, *f; 363 for (e=entries_; e; e=f) { 364 f = e->next(); 365 delete e; 366 } 367 if (identifier_) delete [] identifier_; 368 if (scopedName_) delete scopedName_; 369} 370 371void 372Scope:: 373init() 374{ 375 const char* file = "<built in>"; 376 377 assert(global_ == 0); 378 379 Prefix::newFile(); 380 381 global_ = new Scope(0, Scope::S_GLOBAL, 0, file, 0); 382 Scope* s = global_->newModuleScope("CORBA", file, 1); 383 384 global_->addModule("CORBA", s, 0, file, 1); 385 current_ = global_; 386 387 n_builtins = 2; 388 assert (builtins == 0); 389 builtins = new Decl*[n_builtins]; 390 builtins[0] = new Native(file, 2, 0, "TypeCode"); 391 builtins[1] = new Native(file, 3, 0, "Principal"); 392 393 s->addDecl("TypeCode", 0, builtins[0], BaseType::TypeCodeType, file, 2); 394 s->addDecl("Principal", 0, builtins[1], BaseType::PrincipalType, file, 3); 395 396 Prefix::endOuterFile(); 397} 398 399void 400Scope:: 401clear() 402{ 403 assert(global_ != 0); 404 delete global_; 405 global_ = 0; 406 407 for (int i=0; i < n_builtins; i++) 408 delete builtins[i]; 409 410 delete [] builtins; 411 builtins = 0; 412} 413 414void 415Scope:: 416setInherited(InheritSpec* inherited, const char* file, int line) 417{ 418 inherited_ = inherited; 419 420 InheritSpec* is; 421 Entry* e; 422 423 for (is = inherited; is; is = is->next()) { 424 if (!is->scope()) continue; // Skip bad entries from earlier errors 425 426 for (e = is->scope()->entries(); e; e = e->next()) { 427 428 switch (e->kind()) { 429 case Entry::E_CALLABLE: 430 addInherited(e->identifier(), e->scope(), e->decl(), e, file, line); 431 break; 432 case Entry::E_INHERITED: 433 addInherited(e->identifier(), e->scope(), e->decl(), e->inh_from(), 434 file, line); 435 break; 436 default: 437 break; 438 } 439 } 440 } 441} 442 443void 444Scope:: 445setInherited(ValueInheritSpec* inherited, const char* file, int line) 446{ 447 valueInherited_ = inherited; 448 449 ValueInheritSpec* is; 450 Entry* e; 451 452 for (is = inherited; is; is = is->next()) { 453 if (!is->scope()) continue; // Skip bad entries from earlier errors 454 455 for (e = is->scope()->entries(); e; e = e->next()) { 456 457 switch (e->kind()) { 458 case Entry::E_CALLABLE: 459 addInherited(e->identifier(), e->scope(), e->decl(), e, file, line); 460 break; 461 case Entry::E_INHERITED: 462 addInherited(e->identifier(), e->scope(), e->decl(), e->inh_from(), 463 file, line); 464 break; 465 default: 466 break; 467 } 468 } 469 } 470} 471 472void 473Scope:: 474appendEntry(Entry* e) 475{ 476 if (entries_) last_->next_ = e; 477 else entries_ = e; 478 last_ = e; 479} 480 481void 482Scope:: 483startScope(Scope* s) 484{ 485 assert(s->parent() == current_); 486 current_ = s; 487} 488 489void 490Scope:: 491endScope() 492{ 493 assert(current_ != 0); 494 current_ = current_->parent(); 495 assert(current_ != 0); 496} 497 498// Scope creation functions 499 500Scope* 501Scope:: 502newModuleScope(const char* identifier, const char* file, int line) 503{ 504 // Only the global scope and modules can contain modules. The 505 // grammar enforces this 506 assert(kind() == S_GLOBAL || kind() == S_MODULE); 507 508 // If there is already a module entry for this name, return it 509 Entry* e = find(identifier); 510 if (e && e->kind() == Entry::E_MODULE) 511 return e->scope(); 512 513 // If there was an entry but it wasn't a module, carry on anyway, 514 // since addModule() will report the error 515 516 return new Scope(this, identifier, S_MODULE, 0, file, line); 517} 518 519Scope* 520Scope:: 521newInterfaceScope(const char* identifier, const char* file, int line) 522{ 523 assert(kind() == S_GLOBAL || kind() == S_MODULE); 524 return new Scope(this, identifier, S_INTERFACE, 1, file, line); 525} 526 527Scope* 528Scope:: 529newStructScope(const char* identifier, const char* file, int line) 530{ 531 assert(kind() != S_OPERATION); 532 return new Scope(this, identifier, S_STRUCT, 0, file, line); 533} 534 535Scope* 536Scope:: 537newExceptionScope(const char* identifier, const char* file, int line) 538{ 539 assert(kind() != S_OPERATION); 540 return new Scope(this, identifier, S_EXCEPTION, 0, file, line); 541} 542 543Scope* 544Scope:: 545newUnionScope(const char* identifier, const char* file, int line) 546{ 547 assert(kind() != S_OPERATION); 548 return new Scope(this, identifier, S_UNION, 0, file, line); 549} 550 551Scope* 552Scope:: 553newOperationScope(const char* file, int line) 554{ 555 assert(kind() == S_INTERFACE || kind() == S_VALUE); 556 return new Scope(this, S_OPERATION, 0, file, line); 557} 558 559Scope* 560Scope:: 561newValueScope(const char* identifier, const char* file, int line) 562{ 563 assert(kind() == S_GLOBAL || kind() == S_MODULE); 564 return new Scope(this, identifier, S_VALUE, 1, file, line); 565} 566 567 568// Searching functions 569 570Scope::Entry* 571Scope:: 572find(const char* identifier) const 573{ 574 Entry* e; 575 if (identifier[0] == '_') ++identifier; 576 for (e = entries_; e; e = e->next()) { 577 if (!(strcmp(identifier, e->identifier()))) 578 return e; 579 } 580 return 0; 581} 582 583Scope::Entry* 584Scope:: 585iFind(const char* identifier) const 586{ 587 Entry* e; 588 if (identifier[0] == '_') ++identifier; 589 for (e = entries_; e; e = e->next()) { 590 if (Config::caseSensitive) { 591 if (!(strcmp(identifier, e->identifier()))) 592 return e; 593 } 594 else { 595 if (!(strcasecmp(identifier, e->identifier()))) 596 return e; 597 } 598 } 599 return 0; 600} 601 602 603Scope::EntryList* 604Scope:: 605findWithInheritance(const char* identifier) const 606{ 607 const Entry* e; 608 EntryList* el = 0; 609 EntryList* in_el; 610 611 if (identifier[0] == '_') ++identifier; 612 if ((e = find(identifier))) { 613 switch (e->kind()) { 614 case Entry::E_MODULE: 615 case Entry::E_DECL: 616 case Entry::E_CALLABLE: 617 case Entry::E_INHERITED: 618 case Entry::E_INSTANCE: 619 el = new EntryList(e); 620 return el; 621 case Entry::E_USE: 622 case Entry::E_PARENT: 623 break; 624 } 625 } 626 // Not found locally -- try inherited scopes 627 for (InheritSpec* is = inherited_; is; is = is->next()) { 628 if (!is->scope()) continue; // Skip broken entries from earlier errors 629 630 in_el = is->scope()->findWithInheritance(identifier); 631 632 if (el) 633 el->merge(in_el); 634 else 635 el = in_el; 636 } 637 for (ValueInheritSpec* vis = valueInherited_; vis; vis = vis->next()) { 638 if (!vis->scope()) continue; // Skip broken entries from earlier errors 639 640 in_el = vis->scope()->findWithInheritance(identifier); 641 642 if (el) 643 el->merge(in_el); 644 else 645 el = in_el; 646 } 647 return el; 648} 649 650Scope::EntryList* 651Scope:: 652iFindWithInheritance(const char* identifier) const 653{ 654 const Entry* e; 655 EntryList* el = 0; 656 EntryList* in_el; 657 658 if (identifier[0] == '_') ++identifier; 659 if ((e = iFind(identifier))) { 660 switch (e->kind()) { 661 case Entry::E_MODULE: 662 case Entry::E_DECL: 663 case Entry::E_CALLABLE: 664 case Entry::E_INHERITED: 665 case Entry::E_INSTANCE: 666 el = new EntryList(e); 667 return el; 668 case Entry::E_USE: 669 case Entry::E_PARENT: 670 break; 671 } 672 } 673 // Not found locally -- try inherited scopes 674 for (InheritSpec* is = inherited_; is; is = is->next()) { 675 if (!is->scope()) continue; // Skip broken entries from earlier errors 676 677 in_el = is->scope()->iFindWithInheritance(identifier); 678 679 if (el) 680 el->merge(in_el); 681 else 682 el = in_el; 683 } 684 for (ValueInheritSpec* vis = valueInherited_; vis; vis = vis->next()) { 685 if (!vis->scope()) continue; // Skip broken entries from earlier errors 686 687 in_el = vis->scope()->iFindWithInheritance(identifier); 688 689 if (el) 690 el->merge(in_el); 691 else 692 el = in_el; 693 } 694 return el; 695} 696 697const Scope::Entry* 698Scope:: 699findScopedName(const ScopedName* sn, const char* file, int line) const 700{ 701 const Scope* s; 702 703 // Start at relevant Scope 704 if (sn->absolute()) 705 s = global(); 706 else 707 s = this; 708 709 // Find entry for each name component 710 const Entry* e = 0; 711 EntryList* el; 712 ScopedName::Fragment* f = sn->scopeList(); 713 const char* fid; 714 715 IDL_Boolean top_component = 1; 716 717 while (f) { 718 fid = f->identifier(); 719 if (fid[0] == '_') fid++; 720 721 do { 722 el = s->iFindWithInheritance(fid); 723 724 e = 0; 725 if (el) { 726 e = el->head(); 727 728 if (el->tail()) { 729 // Error -- ambiguous 730 if (file) { 731 char* ssn = sn->toString(); 732 IdlError(file, line, "Ambiguous name '%s':", ssn); 733 delete [] ssn; 734 735 for (; el; el = el->tail()) { 736 char* ssn = el->head()->container()->scopedName()->toString(); 737 IdlErrorCont(el->head()->file(), el->head()->line(), 738 "('%s' defined in '%s')", 739 el->head()->identifier(), ssn); 740 delete [] ssn; 741 } 742 } 743 delete el; 744 return 0; 745 } 746 delete el; 747 break; 748 } 749 } while (top_component && (s = s->parent())); 750 top_component = 0; 751 752 if (!e) { 753 if (file) { 754 char* ssn = sn->toString(); 755 IdlError(file, line, "Error in look-up of '%s': '%s' not found", 756 ssn, fid); 757 delete [] ssn; 758 } 759 return 0; 760 } 761 762 if (strcmp(fid, e->identifier())) { 763 // Case clash 764 if (file) { 765 char* ssn = sn->toString(); 766 IdlError(file, line, "Error in look-up of '%s': '%s' differs in case", 767 ssn, fid); 768 delete [] ssn; 769 ssn = e->scopedName()->toString(); 770 IdlErrorCont(e->file(), e->line(), "from '%s' declared here", ssn); 771 delete [] ssn; 772 } 773 return 0; 774 } 775 776 f = f->next(); 777 if (f) { // More name fragments: check that current entry forms a scope 778 s = e->scope(); 779 780 if (!s) { 781 if (file) { 782 char* ssn = sn->toString(); 783 IdlError(file, line, 784 "Error in look-up of '%s': '%s' does not form a scope", 785 ssn, e->identifier()); 786 IdlErrorCont(e->file(), e->line(), "('%s' defined here)", 787 e->identifier()); 788 delete [] ssn; 789 } 790 return 0; 791 } 792 } 793 } 794 return e; 795} 796 797 798const Scope::Entry* 799Scope:: 800findForUse(const ScopedName* sn, const char* file, int line) 801{ 802 const Entry* e = findScopedName(sn, file, line); 803 addUse(sn, file, line); 804 return e; 805} 806 807 808static ScopedName* 809findRelativeScope(const ScopedName::Fragment* from, 810 const ScopedName::Fragment* to, 811 const Scope* fromScope, 812 const Scope::Entry* target) 813{ 814 ScopedName* result = 0; 815 816 if (!to) 817 return 0; 818 819 if (from && !strcmp(from->identifier(), to->identifier())) { 820 // Top name components match -- recursively try next components 821 result = findRelativeScope(from->next(), to->next(), fromScope, target); 822 } 823 824 if (!result && fromScope) { 825 ScopedName* test = new ScopedName(to, 0); 826 const Scope::Entry* find = fromScope->findScopedName(test); 827 828 if (find == target) 829 result = test; 830 else 831 delete test; 832 } 833 return result; 834} 835 836ScopedName* 837Scope::relativeScopedName(const ScopedName* from, const ScopedName* to) 838{ 839 if (!global_) { 840 // Haven't parsed any IDL yet! 841 return 0; 842 } 843 844 if ((from && !from->absolute()) || !to->absolute()) 845 return 0; 846 847 const Scope* fromScope; 848 849 if (from) { 850 const Entry* fromEntry = global_->findScopedName(from); 851 if (!fromEntry) return 0; 852 fromScope = fromEntry->scope(); 853 } 854 else 855 fromScope = global_; 856 857 const Entry* toEntry = global_->findScopedName(to); 858 if (!toEntry) return 0; 859 860 ScopedName* result = findRelativeScope(from ? from->scopeList() : 0, 861 to->scopeList(), fromScope, toEntry); 862 863 if (!result) 864 result = new ScopedName(to); 865 866 return result; 867} 868 869 870// Entry adding functions 871 872void 873Scope:: 874addUse(const ScopedName* sn, const char* file, int line) 875{ 876 if (!sn->absolute()) { 877 const char* id = sn->scopeList()->identifier(); 878 if (id[0] == '_') ++id; 879 880 const Entry* clash = iFind(id); 881 882 if (clash) { 883 if (strcmp(id, clash->identifier())) { 884 char* ssn = sn->toString(); 885 IdlError(file, line, "Use of '%s' clashes with identifier '%s'", 886 ssn, clash->identifier()); 887 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)", 888 clash->identifier()); 889 delete [] ssn; 890 } 891 // Else the identifier is being used in the same scope that it was 892 // declared, so don't mark it as used. 893 } 894 else { 895 Entry* ue = new Entry(this, Entry::E_USE, id, 0, 0, 0, 0, file, line); 896 appendEntry(ue); 897 if (parent_ && parent_->nestedUse()) parent_->addUse(sn, file, line); 898 } 899 } 900} 901 902 903void 904Scope:: 905addModule(const char* identifier, Scope* scope, Decl* decl, 906 const char* file, int line) 907{ 908 if (*identifier == '_') 909 ++identifier; 910 else 911 keywordClash(identifier, file, line); 912 913 Entry* clash = iFind(identifier); 914 915 if (clash) { 916 switch (clash->kind()) { 917 case Entry::E_MODULE: 918 { 919 if (!strcmp(identifier, clash->identifier())) { 920 return; // Reopening the module 921 } 922 IdlError(file, line, 923 "Declaration of module '%s' clashes with declaration " 924 "of module '%s'", identifier, clash->identifier()); 925 IdlErrorCont(clash->file(), clash->line(), 926 "(module '%s' declared here)", clash->identifier()); 927 break; 928 } 929 case Entry::E_DECL: 930 { 931 IdlError(file, line, 932 "Declaration of module '%s' clashes with declaration " 933 "of %s '%s'", identifier, clash->decl()->kindAsString(), 934 clash->identifier()); 935 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 936 clash->decl()->kindAsString(), clash->identifier()); 937 break; 938 } 939 case Entry::E_CALLABLE: 940 case Entry::E_INHERITED: 941 case Entry::E_INSTANCE: 942 case Entry::E_USE: 943 { 944 assert(0); // Should never reach here 945 } 946 case Entry::E_PARENT: 947 { 948 IdlError(file, line, 949 "Declaration of module '%s' clashes with name of " 950 "enclosing module '%s'", identifier, clash->identifier()); 951 IdlErrorCont(clash->file(), clash->line(), 952 "(module '%s' declared here)", clash->identifier()); 953 break; 954 } 955 } 956 } 957 Entry* e = new Entry(this, Entry::E_MODULE, identifier, scope, 958 decl, 0, 0, file, line); 959 appendEntry(e); 960} 961 962 963void 964Scope:: 965addDecl(const char* identifier, Scope* scope, Decl* decl, IdlType* idltype, 966 const char* file, int line) 967{ 968 if (*identifier == '_') 969 ++identifier; 970 else 971 keywordClash(identifier, file, line); 972 973 Entry* clash = iFind(identifier); 974 975 if (clash) { 976 switch (clash->kind()) { 977 case Entry::E_MODULE: 978 { 979 IdlError(file, line, 980 "Declaration of %s '%s' clashes with declaration " 981 "of module '%s'", decl->kindAsString(), 982 identifier, clash->identifier()); 983 IdlErrorCont(clash->file(), clash->line(), 984 "(module '%s' declared here)", clash->identifier()); 985 break; 986 } 987 case Entry::E_DECL: 988 { 989 IdlError(file, line, 990 "Declaration of %s '%s' clashes with earlier declaration " 991 "of %s '%s'", decl->kindAsString(), identifier, 992 clash->decl()->kindAsString(), clash->identifier()); 993 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 994 clash->decl()->kindAsString(), clash->identifier()); 995 break; 996 } 997 case Entry::E_CALLABLE: 998 { 999 IdlError(file, line, 1000 "Declaration of %s '%s' clashes with %s '%s'", 1001 decl->kindAsString(), identifier, 1002 clash->decl()->kindAsString(), clash->identifier()); 1003 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 1004 clash->decl()->kindAsString(), clash->identifier()); 1005 break; 1006 } 1007 case Entry::E_INHERITED: 1008 { 1009 IdlError(file, line, 1010 "Declaration of %s '%s' clashes with inherited %s '%s'", 1011 decl->kindAsString(), identifier, 1012 clash->decl()->kindAsString(), clash->identifier()); 1013 char* inhfrom = 1014 clash->inh_from()->container()->scopedName()->toString(); 1015 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(), 1016 "('%s' declared in %s here)", 1017 clash->identifier(), inhfrom); 1018 delete [] inhfrom; 1019 break; 1020 } 1021 case Entry::E_INSTANCE: 1022 { 1023 IdlError(file, line, 1024 "Declaration of %s '%s' clashes with instance '%s'", 1025 decl->kindAsString(), identifier, clash->identifier()); 1026 IdlErrorCont(clash->file(), clash->line(), 1027 "('%s' declared here)", clash->identifier()); 1028 break; 1029 } 1030 case Entry::E_USE: 1031 { 1032 IdlError(file, line, 1033 "Declaration of %s '%s' clashes with use of " 1034 "identifier '%s'", decl->kindAsString(), 1035 identifier, clash->identifier()); 1036 IdlErrorCont(clash->file(), clash->line(), 1037 "('%s' used here)", clash->identifier()); 1038 break; 1039 } 1040 case Entry::E_PARENT: 1041 { 1042 IdlError(file, line, 1043 "Declaration of %s '%s' clashes with name of " 1044 "enclosing scope '%s'", decl->kindAsString(), 1045 identifier, clash->identifier()); 1046 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)", 1047 clash->identifier()); 1048 break; 1049 } 1050 } 1051 } 1052 Entry* e = new Entry(this, Entry::E_DECL, identifier, scope, 1053 decl, idltype, 0, file, line); 1054 appendEntry(e); 1055} 1056 1057 1058void 1059Scope:: 1060addCallable(const char* identifier, Scope* scope, Decl* decl, 1061 const char* file, int line) 1062{ 1063 if (*identifier == '_') 1064 ++identifier; 1065 else 1066 keywordClash(identifier, file, line); 1067 1068 Entry* clash = iFind(identifier); 1069 1070 if (clash) { 1071 switch (clash->kind()) { 1072 case Entry::E_MODULE: 1073 { 1074 IdlError(file, line, 1075 "Declaration of %s '%s' clashes with declaration " 1076 "of module '%s'", decl->kindAsString(), 1077 identifier, clash->identifier()); 1078 IdlErrorCont(clash->file(), clash->line(), 1079 "(module '%s' declared here)", clash->identifier()); 1080 break; 1081 } 1082 case Entry::E_DECL: 1083 { 1084 IdlError(file, line, 1085 "Declaration of %s '%s' clashes with earlier declaration " 1086 "of %s '%s'", decl->kindAsString(), identifier, 1087 clash->decl()->kindAsString(), clash->identifier()); 1088 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 1089 clash->decl()->kindAsString(), clash->identifier()); 1090 break; 1091 } 1092 case Entry::E_CALLABLE: 1093 { 1094 IdlError(file, line, 1095 "Declaration of %s '%s' clashes with %s '%s'", 1096 decl->kindAsString(), identifier, 1097 clash->decl()->kindAsString(), clash->identifier()); 1098 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 1099 clash->decl()->kindAsString(), clash->identifier()); 1100 break; 1101 } 1102 case Entry::E_INHERITED: 1103 { 1104 IdlError(file, line, 1105 "Declaration of %s '%s' clashes with inherited %s '%s'", 1106 decl->kindAsString(), identifier, 1107 clash->decl()->kindAsString(), clash->identifier()); 1108 char* inhfrom = 1109 clash->inh_from()->container()->scopedName()->toString(); 1110 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(), 1111 "('%s' declared in %s here)", 1112 clash->identifier(), inhfrom); 1113 delete [] inhfrom; 1114 break; 1115 } 1116 case Entry::E_INSTANCE: 1117 { 1118 IdlError(file, line, 1119 "Declaration of %s '%s' clashes with instance '%s'", 1120 decl->kindAsString(), identifier, clash->identifier()); 1121 IdlErrorCont(clash->file(), clash->line(), 1122 "('%s' declared here)", clash->identifier()); 1123 break; 1124 } 1125 case Entry::E_USE: 1126 { 1127 IdlError(file, line, 1128 "Declaration of %s '%s' clashes with use of " 1129 "identifier '%s'", decl->kindAsString(), 1130 identifier, clash->identifier()); 1131 IdlErrorCont(clash->file(), clash->line(), 1132 "('%s' used here)", clash->identifier()); 1133 break; 1134 } 1135 case Entry::E_PARENT: 1136 { 1137 IdlError(file, line, 1138 "Declaration of %s '%s' clashes with name of " 1139 "enclosing scope '%s'", decl->kindAsString(), 1140 identifier, clash->identifier()); 1141 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)", 1142 clash->identifier()); 1143 break; 1144 } 1145 } 1146 } 1147 Entry* e = new Entry(this, Entry::E_CALLABLE, identifier, scope, 1148 decl, 0, 0, file, line); 1149 appendEntry(e); 1150} 1151 1152 1153void 1154Scope:: 1155addInherited(const char* id, Scope* scope, Decl* decl, 1156 Scope::Entry* inh_from, const char* file, int line) 1157{ 1158 if (*id == '_') ++id; 1159 1160 Entry* clash = iFind(id); 1161 1162 if (clash) { 1163 switch (clash->kind()) { 1164 case Entry::E_MODULE: 1165 case Entry::E_DECL: 1166 case Entry::E_CALLABLE: 1167 case Entry::E_INSTANCE: 1168 case Entry::E_USE: 1169 { 1170 assert(0); // Should never reach here 1171 } 1172 case Entry::E_INHERITED: 1173 { 1174 if (inh_from != clash->inh_from()) { 1175 IdlError(file, line, "In definition of '%s': clash between " 1176 "inherited identifiers '%s' and '%s'", 1177 identifier(), id, clash->identifier()); 1178 char* inhfrom = 1179 inh_from->container()->scopedName()->toString(); 1180 IdlErrorCont(inh_from->file(), inh_from->line(), 1181 "(%s '%s' declared in %s here)", 1182 decl->kindAsString(), id, inhfrom); 1183 delete [] inhfrom; 1184 inhfrom = clash->inh_from()->container()->scopedName()->toString(); 1185 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(), 1186 "(%s '%s' declared in %s here)", 1187 clash->decl()->kindAsString(), 1188 clash->identifier(), inhfrom); 1189 delete [] inhfrom; 1190 } 1191 break; 1192 } 1193 case Entry::E_PARENT: 1194 { 1195 // It's not clear whether this is OK, but the spec doesn't say 1196 // it's definitely illegal 1197 1198 IdlWarning(file, line, 1199 "Inherited %s '%s' clashes with interface name '%s'", 1200 decl->kindAsString(), id, clash->identifier()); 1201 IdlWarningCont(decl->file(), decl->line(), 1202 "(%s '%s' declared here)", decl->kindAsString(), id); 1203 break; 1204 } 1205 } 1206 } 1207 Entry* e = new Entry(this, Entry::E_INHERITED, id, scope, 1208 decl, 0, inh_from, file, line); 1209 appendEntry(e); 1210} 1211 1212 1213void 1214Scope:: 1215addInstance(const char* identifier, Decl* decl, IdlType* idltype, 1216 const char* file, int line) 1217{ 1218 if (*identifier == '_') 1219 ++identifier; 1220 else 1221 keywordClash(identifier, file, line); 1222 1223 Entry* clash = iFind(identifier); 1224 1225 if (clash) { 1226 switch (clash->kind()) { 1227 case Entry::E_MODULE: 1228 { 1229 IdlError(file, line, 1230 "Instance identifier '%s' clashes with declaration " 1231 "of module '%s'", identifier, clash->identifier()); 1232 IdlErrorCont(clash->file(), clash->line(), 1233 "(module '%s' declared here)", clash->identifier()); 1234 break; 1235 } 1236 case Entry::E_DECL: 1237 { 1238 IdlError(file, line, 1239 "Instance identifier '%s' clashes with declaration " 1240 "of %s '%s'", identifier, clash->decl()->kindAsString(), 1241 clash->identifier()); 1242 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 1243 clash->decl()->kindAsString(), clash->identifier()); 1244 break; 1245 } 1246 case Entry::E_CALLABLE: 1247 { 1248 IdlError(file, line, 1249 "Instance identifier '%s' clashes with %s '%s'", 1250 identifier, clash->decl()->kindAsString(), 1251 clash->identifier()); 1252 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)", 1253 clash->decl()->kindAsString(), clash->identifier()); 1254 break; 1255 } 1256 case Entry::E_INHERITED: 1257 { 1258 IdlError(file, line, 1259 "Instance identifier '%s' clashes with inherited %s '%s'", 1260 identifier, clash->decl()->kindAsString(), 1261 clash->identifier()); 1262 char* inhfrom = 1263 clash->inh_from()->container()->scopedName()->toString(); 1264 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(), 1265 "('%s' declared in %s here)", 1266 clash->identifier(), inhfrom); 1267 delete [] inhfrom; 1268 break; 1269 } 1270 case Entry::E_INSTANCE: 1271 { 1272 IdlError(file, line, 1273 "Instance identifier '%s' clashes with instance '%s'", 1274 identifier, clash->identifier()); 1275 IdlErrorCont(clash->file(), clash->line(), 1276 "('%s' declared here)", clash->identifier()); 1277 break; 1278 } 1279 case Entry::E_USE: 1280 { 1281 IdlError(file, line, 1282 "Instance identifier '%s' clashes with use of " 1283 "identifier '%s'", identifier, clash->identifier()); 1284 IdlErrorCont(clash->file(), clash->line(), 1285 "('%s' used here)", clash->identifier()); 1286 break; 1287 } 1288 case Entry::E_PARENT: 1289 { 1290 IdlError(file, line, 1291 "Instance identifier '%s' clashes with name of " 1292 "enclosing scope '%s'", identifier, clash->identifier()); 1293 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)", 1294 clash->identifier()); 1295 break; 1296 } 1297 } 1298 } 1299 Entry* e = new Entry(this, Entry::E_INSTANCE, identifier, 0, 1300 decl, idltype, 0, file, line); 1301 appendEntry(e); 1302} 1303 1304 1305void 1306Scope:: 1307remEntry(Scope::Entry* re) 1308{ 1309 if (entries_ == re) { 1310 entries_ = re->next(); 1311 if (!entries_) last_ = 0; 1312 } 1313 else { 1314 Entry *e; 1315 for (e = entries_; e && (e->next() != re); e = e->next()); 1316 assert(e != 0); 1317 e->next_ = re->next(); 1318 if (!e->next_) last_ = e; 1319 } 1320 re->next_ = 0; 1321 delete re; 1322} 1323 1324 1325IDL_Boolean 1326Scope:: 1327keywordClash(const char* identifier, const char* file, int line) 1328{ 1329 static const char* keywords[] = { 1330 "abstract", "any", "attribute", "boolean", "case", "char", "const", 1331 "context", "custom", "default", "double", "enum", "exception", 1332 "factory", "FALSE", "fixed", "float", "in", "inout", "interface", 1333 "local", "long", "module", "native", "Object", "octet", "oneway", 1334 "out", "private", "public", "raises", "readonly", "sequence", 1335 "short", "string", "struct", "supports", "switch", "TRUE", 1336 "truncatable", "typedef", "union", "unsigned", "ValueBase", 1337 "valuetype", "void", "wchar", "wstring", 0 1338 }; 1339 1340 static const char* new_keywords[] = { 1341 "component", "consumes", "emits", "eventtype", "finder", "getraises", 1342 "home", "import", "multiple", "primarykey", "provides", "publishes", 1343 "setraises", "typeid", "typeprefix", "uses", 0 1344 }; 1345 1346 const char** k; 1347 1348 for (k = keywords; *k; k++) { 1349 if (Config::caseSensitive) { 1350 if (!strcmp(*k, identifier)) { 1351 IdlError(file, line, "Identifier '%s' is identical to keyword '%s'", 1352 identifier, *k); 1353 return 1; 1354 } 1355 } 1356 else { 1357 if (!strcasecmp(*k, identifier)) { 1358 IdlError(file, line, "Identifier '%s' clashes with keyword '%s'", 1359 identifier, *k); 1360 return 1; 1361 } 1362 } 1363 } 1364 for (k = new_keywords; *k; k++) { 1365 if (Config::caseSensitive) { 1366 if (!strcmp(*k, identifier)) { 1367 IdlWarning(file, line, "Identifier '%s' is identical to " 1368 "CORBA 3 keyword '%s'.", identifier, *k); 1369 return 1; 1370 } 1371 } 1372 else { 1373 if (!strcasecmp(*k, identifier)) { 1374 IdlWarning(file, line, "Identifier '%s' clashes with " 1375 "CORBA 3 keyword '%s'", identifier, *k); 1376 return 1; 1377 } 1378 } 1379 } 1380 return 0; 1381}