Synopsis - Cross-Reference

File: /Synopsis/Parsers/IDL/idlast.cc
   1// -*- c++ -*-
   2//                          Package   : omniidl
   3// idlast.cc                Created on: 1999/10/20
   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//   Abstract Syntax Tree objects and support functions
  28
  29// $Id: idlast.cc,v 1.22.2.4 2005/05/10 22:07:31 dgrisby Exp $
  30// $Log: idlast.cc,v $
  31// Revision 1.22.2.4  2005/05/10 22:07:31  dgrisby
  32// Merge again.
  33//
  34// Revision 1.22.2.3  2004/02/16 10:10:33  dgrisby
  35// More valuetype, including value boxes. C++ mapping updates.
  36//
  37// Revision 1.22.2.2  2003/09/04 14:00:24  dgrisby
  38// ValueType IDL updates.
  39//
  40// Revision 1.22.2.1  2003/03/23 21:01:48  dgrisby
  41// Start of omniORB 4.1.x development branch.
  42//
  43// Revision 1.16.2.12  2002/04/30 14:59:37  dgrisby
  44// omniidl segfault when checking a non-existent identifier is not a forward.
  45//
  46// Revision 1.16.2.11  2001/11/08 16:31:20  dpg1
  47// Minor tweaks.
  48//
  49// Revision 1.16.2.10  2001/10/29 17:42:42  dpg1
  50// Support forward-declared structs/unions, ORB::create_recursive_tc().
  51//
  52// Revision 1.16.2.9  2001/10/17 16:48:32  dpg1
  53// Minor error message tweaks
  54//
  55// Revision 1.16.2.8  2001/08/29 11:55:22  dpg1
  56// Enumerator nodes record their value.
  57//
  58// Revision 1.16.2.7  2001/06/12 11:35:25  dpg1
  59// Minor omniidl tweaks for valuetype.
  60//
  61// Revision 1.16.2.6  2001/06/08 17:12:22  dpg1
  62// Merge all the bug fixes from omni3_develop.
  63//
  64// Revision 1.16.2.5  2001/03/13 10:32:11  dpg1
  65// Fixed point support.
  66//
  67// Revision 1.16.2.4  2000/11/01 12:45:56  dpg1
  68// Update to CORBA 2.4 specification.
  69//
  70// Revision 1.16.2.3  2000/10/27 16:31:08  dpg1
  71// Clean up of omniidl dependencies and types, from omni3_develop.
  72//
  73// Revision 1.16.2.2  2000/10/10 10:18:50  dpg1
  74// Update omniidl front-end from omni3_develop.
  75//
  76// Revision 1.14.2.9  2000/08/29 10:20:26  dpg1
  77// Operations and attributes now have repository ids.
  78//
  79// Revision 1.14.2.8  2000/08/25 13:33:02  dpg1
  80// Multiple comments preceding a declaration are now properly attached on
  81// all platforms
  82//
  83// Revision 1.14.2.7  2000/08/07 15:34:36  dpg1
  84// Partial back-port of long long from omni3_1_develop.
  85//
  86// Revision 1.14.2.6  2000/07/26 10:59:14  dpg1
  87// Incorrect error report when inheriting typedef to forward declared
  88// interface
  89//
  90// Revision 1.14.2.5  2000/06/08 14:36:19  dpg1
  91// Comments and pragmas are now objects rather than plain strings, so
  92// they can have file,line associated with them.
  93//
  94// Revision 1.14.2.4  2000/06/05 18:13:26  dpg1
  95// Comments can be attached to subsequent declarations (with -K). Better
  96// idea of most recent decl in operation declarations
  97//
  98// Revision 1.14.2.3  2000/03/16 17:35:21  dpg1
  99// Bug with comments in input when keepComments is false.
 100//
 101// Revision 1.14.2.2  2000/03/07 10:31:26  dpg1
 102// More sensible idea of the "most recent" declaration.
 103//
 104// Revision 1.14.2.1  2000/03/06 15:03:49  dpg1
 105// Minor bug fixes to omniidl. New -nf and -k flags.
 106//
 107// Revision 1.14  2000/02/03 14:50:07  dpg1
 108// Native declarations can now be used as types.
 109//
 110// Revision 1.13  2000/01/05 11:21:08  dpg1
 111// Removed warning about signed/unsigned comparison.
 112// * can only be the last character of a context key.
 113//
 114// Revision 1.12  1999/12/28 18:15:45  dpg1
 115// Bounds of string constants now checked.
 116//
 117// Revision 1.11  1999/11/30 18:06:19  dpg1
 118// Alias dereferencing bugs.
 119//
 120// Revision 1.10  1999/11/22 11:07:46  dpg1
 121// Correctly report error with interface which tries to inherit from
 122// CORBA::Object.
 123//
 124// Revision 1.9  1999/11/17 17:17:00  dpg1
 125// Changes to remove static initialisation of objects.
 126//
 127// Revision 1.8  1999/11/04 17:15:52  dpg1
 128// Typo.
 129//
 130// Revision 1.7  1999/11/02 17:07:27  dpg1
 131// Changes to compile on Solaris.
 132//
 133// Revision 1.6  1999/11/01 20:19:57  dpg1
 134// Support for union switch types declared inside the switch statement.
 135//
 136// Revision 1.5  1999/11/01 16:38:40  dpg1
 137// Missed an update when adding recursive union detection.
 138//
 139// Revision 1.4  1999/11/01 10:05:00  dpg1
 140// New file attribute to AST.
 141//
 142// Revision 1.3  1999/10/29 15:42:43  dpg1
 143// DeclaredType() now takes extra DeclRepoId* argument.
 144// Code to detect recursive structs and unions.
 145//
 146// Revision 1.2  1999/10/29 10:00:43  dpg1
 147// Added code to find a value for the default case in a union.
 148//
 149// Revision 1.1  1999/10/27 14:05:59  dpg1
 150// *** empty log message ***
 151//
 152
 153#include <idlast.h>
 154#include <idlrepoId.h>
 155#include <idlvalidate.h>
 156#include <idlerr.h>
 157#include <idlconfig.h>
 158
 159#include <string.h>
 160#include <ctype.h>
 161
 162// Globals from lexer
 163extern FILE* yyin;
 164extern char* currentFile;
 165extern int   yylineno;
 166
 167AST*     AST::tree_           = 0;
 168Decl*    Decl::mostRecent_    = 0;
 169Comment* Comment::mostRecent_ = 0;
 170Comment* Comment::saved_      = 0;
 171
 172
 173// Static error message functions
 174static void
 175checkNotForward(const char* file, int line, IdlType* t)
 176{
 177  if (!t) return;
 178
 179  if (t->kind() == IdlType::ot_structforward) {
 180    StructForward* f = (StructForward*)((DeclaredType*)t)->decl();
 181
 182    if (!f->definition()) {
 183      char* ssn = f->scopedName()->toString();
 184      IdlError(file, line,
 185	       "Cannot use forward-declared struct '%s' before it is "
 186	       "fully defined", ssn);
 187      IdlErrorCont(f->file(), f->line(),
 188		   "('%s' forward-declared here)", f->identifier());
 189      delete [] ssn;
 190    }
 191  }
 192  else if (t->kind() == IdlType::ot_unionforward) {
 193    UnionForward* f = (UnionForward*)((DeclaredType*)t)->decl();
 194
 195    if (!f->definition()) {
 196      char* ssn = f->scopedName()->toString();
 197      IdlError(file, line,
 198	       "Cannot use forward-declared union '%s' before it is "
 199	       "fully defined", ssn);
 200      IdlErrorCont(f->file(), f->line(),
 201		   "('%s' forward-declared here)", f->identifier());
 202      delete [] ssn;
 203    }
 204  }
 205}
 206
 207static
 208void
 209checkValidType(const char* file, int line, IdlType* t)
 210{
 211  t = t->unalias();
 212  if (!t) return;  // Ignore if earlier errors.
 213
 214  checkNotForward(file, line, t);
 215
 216  if (t && t->kind() == IdlType::tk_sequence) {
 217
 218    while (t && t->kind() == IdlType::tk_sequence)
 219      t = ((SequenceType*)t)->seqType()->unalias();
 220
 221    checkNotForward(file, line, t);
 222  }
 223}
 224
 225
 226// Pragma
 227void
 228Pragma::
 229add(const char* pragmaText, const char* file, int line)
 230{
 231  if (Decl::mostRecent())
 232    Decl::mostRecent()->addPragma(pragmaText, file, line);
 233  else
 234    AST::tree()->addPragma(pragmaText, file, line);
 235}
 236
 237// Comment
 238
 239void
 240Comment::
 241add(const char* commentText, const char* file, int line)
 242{
 243  if (Config::keepComments) {
 244    if (Config::commentsFirst) {
 245      if (saved_) {
 246	// C++ says that the order of value evaluation is undefined.
 247	// Comment's constructor sets mostRecent_, so the innocent-
 248	// looking mostRecent_->next_ = new Comment... does the wrong
 249	// thing with some compilers :-(
 250	Comment* mr = mostRecent_;
 251	mr->next_ = new Comment(commentText, file, line);
 252      }
 253      else
 254	saved_ = new Comment(commentText, file, line);
 255    }
 256    else {
 257      if (Decl::mostRecent())
 258	Decl::mostRecent()->addComment(commentText, file, line);
 259      else
 260	AST::tree()->addComment(commentText, file, line);
 261    }
 262  }
 263}
 264
 265void
 266Comment::
 267append(const char* commentText)
 268{
 269  if (Config::keepComments) {
 270    assert(mostRecent_ != 0);
 271    char* newText = new char[(strlen(mostRecent_->commentText_) +
 272			      strlen(commentText) + 1)];
 273    strcpy(newText, mostRecent_->commentText_);
 274    strcat(newText, commentText);
 275    delete [] mostRecent_->commentText_;
 276    mostRecent_->commentText_ = newText;
 277  }
 278}
 279
 280Comment*
 281Comment::
 282grabSaved()
 283{
 284  Comment* ret = saved_;
 285  saved_ = 0;
 286  return ret;
 287}
 288
 289
 290// AST
 291AST::AST() : declarations_(0), file_(0),
 292	     pragmas_(0), lastPragma_(0),
 293	     comments_(0), lastComment_(0) {}
 294
 295AST::~AST() {
 296  if (declarations_) delete declarations_;
 297  if (file_)         delete [] file_;
 298  if (pragmas_)      delete pragmas_;
 299  if (comments_)     delete comments_;
 300}
 301
 302void
 303AST::
 304addPragma(const char* pragmaText, const char* file, int line)
 305{
 306  Pragma* p = new Pragma(pragmaText, file, line);
 307  if (pragmas_)
 308    lastPragma_->next_ = p;
 309  else
 310    pragmas_ = p;
 311  lastPragma_ = p;
 312}
 313
 314void
 315AST::
 316addComment(const char* commentText, const char* file, int line)
 317{
 318  Comment* p = new Comment(commentText, file, line);
 319  if (comments_)
 320    lastComment_->next_ = p;
 321  else
 322    comments_ = p;
 323  lastComment_ = p;
 324}
 325
 326
 327AST*
 328AST::
 329tree()
 330{
 331  if (!tree_) tree_ = new AST();
 332  assert(tree_ != 0);
 333  return tree_;
 334}
 335
 336IDL_Boolean
 337AST::
 338process(FILE* f, const char* name)
 339{
 340  IdlType::init();
 341  Scope::init();
 342
 343  yyin        = f;
 344  currentFile = idl_strdup(name);
 345  Prefix::newFile();
 346
 347  tree()->setFile(name);
 348
 349  int yr = yyparse();
 350  if (yr) IdlError(currentFile, yylineno, "Syntax error");
 351
 352  if (Config::keepComments && Config::commentsFirst)
 353    tree()->comments_ = Comment::grabSaved();
 354
 355  Prefix::endOuterFile();
 356
 357  return IdlReportErrors();
 358}
 359
 360void
 361AST::
 362clear()
 363{
 364  if (tree_) {
 365    delete tree_;
 366    tree_ = 0;
 367  }
 368  Scope::clear();
 369  Decl::clear();
 370  Comment::clear();
 371}
 372
 373void
 374AST::
 375setFile(const char* file)
 376{
 377  if (file_) {
 378    if (!strcmp(file_, file)) return;
 379    delete [] file_;
 380  }
 381  file_ = idl_strdup(file);
 382}
 383
 384void
 385AST::
 386setDeclarations(Decl* d)
 387{
 388  assert(declarations_ == 0);
 389  declarations_ = d;
 390
 391  // Validate the declarations
 392  AstValidateVisitor v;
 393  accept(v);
 394}
 395
 396
 397// Base Decl
 398Decl::
 399Decl(Kind kind, const char* file, int line, IDL_Boolean mainFile)
 400
 401  : kind_(kind), file_(idl_strdup(file)), line_(line),
 402    mainFile_(mainFile), inScope_(Scope::current()),
 403    pragmas_(0), lastPragma_(0),
 404    comments_(0), lastComment_(0),
 405    next_(0)
 406{
 407  last_       = this;
 408  mostRecent_ = this;
 409
 410  if (Config::keepComments && Config::commentsFirst)
 411    comments_ = Comment::grabSaved();
 412}
 413
 414Decl::
 415~Decl()
 416{
 417  if (file_)     delete [] file_;
 418  if (pragmas_)  delete pragmas_;
 419  if (comments_) delete comments_;
 420  if (next_)     delete next_;
 421}
 422
 423Decl*
 424Decl::
 425scopedNameToDecl(const char* file, int line, const ScopedName* sn)
 426{
 427  const Scope::Entry* se = Scope::current()->findScopedName(sn, file, line);
 428
 429  if (se) {
 430    switch (se->kind()) {
 431
 432    case Scope::Entry::E_MODULE:
 433    case Scope::Entry::E_DECL:
 434    case Scope::Entry::E_CALLABLE:
 435    case Scope::Entry::E_INHERITED:
 436      return se->decl();
 437
 438    default:
 439      {
 440	char* ssn = sn->toString();
 441	IdlError(file, line, "'%s' is not a declaration", ssn);
 442	IdlErrorCont(se->file(), se->line(), "('%s' created here)", ssn);
 443	delete [] ssn;
 444      }
 445    }
 446  }
 447  return 0;
 448}
 449
 450void
 451Decl::
 452addPragma(const char* pragmaText, const char* file, int line)
 453{
 454  Pragma* p = new Pragma(pragmaText, file, line);
 455  if (pragmas_)
 456    lastPragma_->next_ = p;
 457  else
 458    pragmas_ = p;
 459  lastPragma_ = p;
 460}
 461
 462void
 463Decl::
 464addComment(const char* commentText, const char* file, int line)
 465{
 466  Comment* p = new Comment(commentText, file, line);
 467  if (comments_)
 468    lastComment_->next_ = p;
 469  else
 470    comments_ = p;
 471  lastComment_ = p;
 472}
 473
 474
 475
 476// Module
 477Module::
 478Module(const char* file, int line, IDL_Boolean mainFile,
 479       const char* identifier)
 480
 481  : Decl(D_MODULE, file, line, mainFile),
 482    DeclRepoId(identifier),
 483    definitions_(0)
 484{
 485  Scope* s = Scope::current()->newModuleScope(identifier, file, line);
 486  Scope::current()->addModule(identifier, s, this, file, line);
 487  Scope::startScope(s);
 488  Prefix::newScope(identifier);
 489}
 490
 491Module::
 492~Module()
 493{
 494  if (definitions_) delete definitions_;
 495}
 496
 497void
 498Module::
 499finishConstruction(Decl* defs)
 500{
 501  definitions_ = defs;
 502  Prefix::endScope();
 503  Scope::endScope();
 504  mostRecent_ = this;
 505}
 506
 507
 508// Interface
 509InheritSpec::
 510InheritSpec(const ScopedName* sn, const char* file, int line)
 511
 512  : interface_(0), decl_(0), scope_(0), next_(0)
 513{
 514  const Scope::Entry* se = Scope::current()->findScopedName(sn, file, line);
 515
 516  if (se) {
 517    if (se->kind() == Scope::Entry::E_DECL) {
 518
 519      decl_      = se->decl();
 520      IdlType* t = se->idltype()->unalias();
 521
 522      if (!t) return;
 523
 524      if (t->kind() == IdlType::tk_objref ||
 525	  t->kind() == IdlType::tk_abstract_interface ||
 526	  t->kind() == IdlType::tk_local_interface) {
 527
 528	Decl* d = ((DeclaredType*)t)->decl();
 529
 530	if (!d) {
 531	  char* ssn = sn->toString();
 532	  IdlError(file, line, "Cannot inherit from CORBA::Object");
 533	  IdlErrorCont(se->file(), se->line(),
 534		       "(accessed through typedef '%s')", ssn);
 535	  delete [] ssn;
 536	  return;
 537	}
 538	else if (d->kind() == Decl::D_INTERFACE) {
 539	  interface_ = (Interface*)d;
 540	  scope_     = interface_->scope();
 541	  return;
 542	}
 543	else if (d->kind() == Decl::D_FORWARD) {
 544	  Interface* def = ((Forward*)d)->definition();
 545	  if (def) {
 546	    interface_ = def;
 547	    scope_     = interface_->scope();
 548	    return;
 549	  }
 550	  else {
 551	    char* ssn = ((Forward*)d)->scopedName()->toString();
 552	    IdlError(file, line,
 553		     "Inherited interface '%s' must be fully defined", ssn);
 554
 555	    if (decl_ != d) {
 556	      char* tssn = sn->toString();
 557	      IdlErrorCont(se->file(), se->line(),
 558			   "('%s' reached through typedef '%s')",
 559			   ssn, tssn);
 560	      delete [] tssn;
 561	    }
 562	    IdlErrorCont(d->file(), d->line(),
 563			 "('%s' forward declared here)", ssn);
 564	    delete [] ssn;
 565	    return;
 566	  }
 567	}
 568      }
 569    }
 570    char* ssn = sn->toString();
 571    IdlError(file, line,
 572	     "'%s' used in inheritance specification is not an interface",
 573	     ssn);
 574    IdlErrorCont(se->file(), se->line(), "('%s' declared here)", ssn);
 575    delete [] ssn;
 576  }
 577}
 578
 579void
 580InheritSpec::
 581append(InheritSpec* is, const char* file, int line)
 582{
 583  InheritSpec *i, *last;
 584
 585  if (is->interface()) {
 586    for (i=this; i; i = i->next_) {
 587      last = i;
 588      if (is->interface() == i->interface()) {
 589	char* ssn = is->interface()->scopedName()->toString();
 590	IdlError(file, line,
 591		 "Cannot specify '%s' as a direct base interface "
 592		 "more than once", ssn);
 593	delete [] ssn;
 594	delete is;
 595	return;
 596      }
 597    }
 598    last->next_ = is;
 599  }
 600}
 601
 602Interface::
 603Interface(const char* file, int line, IDL_Boolean mainFile,
 604	  const char* identifier, IDL_Boolean abstract, IDL_Boolean local,
 605	  InheritSpec* inherits)
 606
 607  : Decl(D_INTERFACE, file, line, mainFile),
 608    DeclRepoId(identifier),
 609    abstract_(abstract),
 610    local_(local),
 611    inherits_(inherits),
 612    contents_(0)
 613{
 614  // Look for forward interface
 615  Scope::Entry* se = Scope::current()->find(identifier);
 616
 617  if (se &&
 618      se->kind() == Scope::Entry::E_DECL &&
 619      se->decl() &&
 620      se->decl()->kind() == Decl::D_FORWARD) {
 621
 622    Forward* f = (Forward*)se->decl();
 623
 624    if (strcmp(f->prefix(), prefix())) {
 625
 626      IdlError(file, line,
 627	       "In declaration of interface '%s', repository id "
 628	       "prefix '%s' differs from that of forward declaration",
 629	       identifier, prefix());
 630
 631      IdlErrorCont(f->file(), f->line(),
 632		   "('%s' forward declared here with prefix '%s')",
 633		   f->identifier(), f->prefix());
 634    }
 635    if (abstract && !f->abstract()) {
 636      IdlError(file, line,
 637	       "Declaration of abstract interface '%s' conflicts with "
 638	       "forward declaration as non-abstract", identifier);
 639      IdlErrorCont(f->file(), f->line(),
 640		   "('%s' forward declared as non-abstract here)");
 641    }
 642    else if (!abstract && f->abstract()) {
 643      IdlError(file, line,
 644	       "Declaration of non-abstract interface '%s' conflicts with "
 645	       "forward declaration as abstract", identifier);
 646      IdlErrorCont(f->file(), f->line(),
 647		   "('%s' forward declared as abstract here)");
 648    }
 649    if (local && !f->local()) {
 650      IdlError(file, line,
 651	       "Declaration of local interface '%s' conflicts with "
 652	       "forward declaration as unconstrained", identifier);
 653      IdlErrorCont(f->file(), f->line(),
 654		   "('%s' forward declared as unconstrained here)");
 655    }
 656    else if (!local && f->local()) {
 657      IdlError(file, line,
 658	       "Declaration of unconstrained interface '%s' conflicts with "
 659	       "forward declaration as local", identifier);
 660      IdlErrorCont(f->file(), f->line(),
 661		   "('%s' forward declared as local here)");
 662    }
 663    if (f->repoIdSet()) setRepoId(f->repoId(), f->rifile(), f->riline());
 664
 665    f->setDefinition(this);
 666    Scope::current()->remEntry(se);
 667  }
 668  scope_ = Scope::current()->newInterfaceScope(identifier, file, line);
 669
 670  if (abstract_) {
 671    thisType_ = new DeclaredType(IdlType::tk_abstract_interface, this, this);
 672
 673    // Check that all inherited interfaces are abstract
 674    for (InheritSpec* inh = inherits; inh; inh = inh->next()) {
 675      if (!inh->interface()->abstract()) {
 676	char* ssn = inh->scope()->scopedName()->toString();
 677	IdlError(file, line,
 678		 "In declaration of abstract interface '%s', inherited "
 679		 "interface '%s' is not abstract", identifier, ssn);
 680	IdlErrorCont(inh->interface()->file(), inh->interface()->line(),
 681		     "(%s declared here)", ssn);
 682	delete [] ssn;
 683      }
 684    }
 685  }
 686  else if (local_) {
 687    thisType_ = new DeclaredType(IdlType::tk_local_interface, this, this);
 688    thisType_->setLocal();
 689  }
 690  else {
 691    thisType_ = new DeclaredType(IdlType::tk_objref, this, this);
 692
 693    // Check that all inherited interfaces are unconstrained
 694    for (InheritSpec* inh = inherits; inh; inh = inh->next()) {
 695      if (inh->interface() && inh->interface()->local()) {
 696	char* ssn = inh->scope()->scopedName()->toString();
 697	IdlError(file, line,
 698		 "In declaration of unconstrained interface '%s', inherited "
 699		 "interface '%s' is local", identifier, ssn);
 700	IdlErrorCont(inh->interface()->file(), inh->interface()->line(),
 701		     "(%s declared here)", ssn);
 702	delete [] ssn;
 703      }
 704    }
 705  }
 706  scope_->setInherited(inherits, file, line);
 707  Scope::current()->addDecl(identifier, scope_, this, thisType_, file, line);
 708  Scope::startScope(scope_);
 709  Prefix::newScope(identifier);
 710}
 711
 712Interface::
 713~Interface()
 714{
 715  if (inherits_) delete inherits_;
 716  if (contents_) delete contents_;
 717  delete thisType_;
 718}
 719
 720IDL_Boolean
 721Interface::isDerived(const Interface* base) const
 722{
 723  if (base == this)
 724    return 1;
 725
 726  for (InheritSpec* is = inherits_; is; is = is->next()) {
 727    if (is->interface() == base || is->interface()->isDerived(base))
 728      return 1;
 729  }
 730  return 0;
 731}
 732
 733
 734void
 735Interface::
 736finishConstruction(Decl* decls)
 737{
 738  contents_ = decls;
 739  Prefix::endScope();
 740  Scope::endScope();
 741  mostRecent_ = this;
 742
 743  if (!local_) {
 744    for (Decl* d = decls; d; d = d->next()) {
 745
 746      if (d->kind() == D_ATTRIBUTE) {
 747	Attribute* a = (Attribute*)d;
 748
 749	if (a->attrType() && a->attrType()->local()) {
 750	  DeclaredType* dt = (DeclaredType*)a->attrType();
 751	  assert(dt->declRepoId());
 752	  char* ssn = dt->declRepoId()->scopedName()->toString();
 753
 754	  IdlError(a->file(), a->line(),
 755		   "In unconstrained interface '%s', attribute '%s' has "
 756		   "local type '%s'",
 757		   identifier(), a->declarators()->identifier(), ssn);
 758	  IdlErrorCont(dt->decl()->file(), dt->decl()->line(),
 759		       "(%s declared here)", ssn);
 760	  delete [] ssn;
 761	}
 762      }
 763      else if (d->kind() == D_OPERATION) {
 764	Operation* o = (Operation*)d;
 765
 766	if (o->returnType() && o->returnType()->local()) {
 767	  DeclaredType* dt = (DeclaredType*)o->returnType();
 768	  assert(dt->declRepoId());
 769	  char* ssn = dt->declRepoId()->scopedName()->toString();
 770
 771	  IdlError(o->file(), o->line(),
 772		   "In unconstrained interface '%s', operation '%s' has "
 773		   "local return type '%s'",
 774		   identifier(), o->identifier(), ssn);
 775	  IdlErrorCont(dt->decl()->file(), dt->decl()->line(),
 776		       "(%s declared here)", ssn);
 777	  delete [] ssn;
 778	}
 779	for (Parameter* p = o->parameters(); p; p = (Parameter*)p->next()) {
 780	  if (p->paramType() && p->paramType()->local()) {
 781	    DeclaredType* dt = (DeclaredType*)p->paramType();
 782	    assert(dt->declRepoId());
 783	    char* ssn = dt->declRepoId()->scopedName()->toString();
 784
 785	    IdlError(p->file(), p->line(),
 786		     "In unconstrained interface '%s', operation '%s' has "
 787		     "parameter '%s' with local type '%s'",
 788		     identifier(), o->identifier(), p->identifier(), ssn);
 789	    IdlErrorCont(dt->decl()->file(), dt->decl()->line(),
 790			 "(%s declared here)", ssn);
 791	    delete [] ssn;
 792	  }
 793	}
 794	for (RaisesSpec* r = o->raises(); r; r = r->next()) {
 795	  if (r->exception() && r->exception()->local()) {
 796	    char* ssn = r->exception()->scopedName()->toString();
 797
 798	    IdlError(o->file(), o->line(),
 799		     "In unconstrained interface '%s', operation '%s' raises "
 800		     "local exception '%s'", identifier(),
 801		     o->identifier(), ssn);
 802	    IdlErrorCont(r->exception()->file(), r->exception()->line(),
 803			 "(%s declared here)", ssn);
 804	    delete [] ssn;
 805	  }
 806	}
 807      }
 808    }
 809  }
 810}
 811
 812
 813// Forward
 814Forward::
 815Forward(const char* file, int line, IDL_Boolean mainFile,
 816	const char* identifier, IDL_Boolean abstract, IDL_Boolean local)
 817
 818  : Decl(D_FORWARD, file, line, mainFile),
 819    DeclRepoId(identifier),
 820    abstract_(abstract),
 821    local_(local),
 822    definition_(0),
 823    firstForward_(0),
 824    thisType_(0)
 825{
 826  Scope::Entry* se  = Scope::current()->find(identifier);
 827  IDL_Boolean   reg = 1;
 828
 829  if (se && se->kind() == Scope::Entry::E_DECL) {
 830
 831    if (se->decl()->kind() == D_INTERFACE) {
 832      Interface* i = (Interface*)se->decl();
 833      definition_  = i;
 834
 835      if (strcmp(i->prefix(), prefix())) {
 836
 837	IdlError(file, line,
 838		 "In forward declaration of interface '%s', repository "
 839		 "id prefix '%s' differs from that of earlier declaration",
 840		 identifier, prefix());
 841
 842	IdlErrorCont(i->file(), i->line(),
 843		     "('%s' fully declared here with prefix '%s')",
 844		     i->identifier(), i->prefix());
 845      }
 846      if (abstract && !i->abstract()) {
 847	IdlError(file, line,
 848		 "Forward declaration of abstract interface '%s' conflicts "
 849		 "with earlier full declaration as non-abstract",
 850		 identifier);
 851	IdlErrorCont(i->file(), i->line(),
 852		     "('%s' declared as non-abstract here)");
 853      }
 854      else if (!abstract && i->abstract()) {
 855	IdlError(file, line,
 856		 "Forward declaration of non-abstract interface '%s' "
 857		 "conflicts with earlier full declaration as abstract",
 858		 identifier);
 859	IdlErrorCont(i->file(), i->line(),
 860		     "('%s' declared as abstract here)");
 861      }
 862      if (local && !i->local()) {
 863	IdlError(file, line,
 864		 "Forward declaration of local interface '%s' conflicts "
 865		 "with earlier full declaration as unconstrained",
 866		 identifier);
 867	IdlErrorCont(i->file(), i->line(),
 868		     "('%s' declared as unconstrained here)");
 869      }
 870      else if (!local && i->local()) {
 871	IdlError(file, line,
 872		 "Forward declaration of unconstrained interface '%s' "
 873		 "conflicts with earlier full declaration as local",
 874		 identifier);
 875	IdlErrorCont(i->file(), i->line(),
 876		     "('%s' declared as abstract here)");
 877      }
 878      reg = 0;
 879    }
 880    else if (se->decl()->kind() == D_FORWARD) {
 881      Forward* f    = (Forward*)se->decl();
 882      firstForward_ = f;
 883
 884      if (strcmp(f->prefix(), prefix())) {
 885	IdlError(file, line,
 886		 "In forward declaration of interface '%s', repository "
 887		 "id prefix '%s' differs from that of earlier declaration",
 888		 identifier, prefix());
 889
 890	IdlErrorCont(f->file(), f->line(),
 891		     "('%s' forward declared here with prefix '%s')",
 892		     f->identifier(), f->prefix());
 893      }
 894      if (abstract && !f->abstract()) {
 895	IdlError(file, line,
 896		 "Forward declaration of abstract interface '%s' conflicts "
 897		 "with earlier forward declaration as non-abstract",
 898		 identifier);
 899	IdlErrorCont(f->file(), f->line(),
 900		     "('%s' forward declared as non-abstract here)");
 901      }
 902      else if (!abstract && f->abstract()) {
 903	IdlError(file, line,
 904		 "Forward declaration of non-abstract interface '%s' "
 905		 "conflicts  with earlier forward declaration as abstract",
 906		 identifier);
 907	IdlErrorCont(f->file(), f->line(),
 908		     "('%s' forward declared as abstract here)");
 909      }
 910      if (local && !f->local()) {
 911	IdlError(file, line,
 912		 "Forward declaration of local interface '%s' conflicts "
 913		 "with earlier forward declaration as unconstrained",
 914		 identifier);
 915	IdlErrorCont(f->file(), f->line(),
 916		     "('%s' forward declared as unconstrained here)");
 917      }
 918      else if (!local && f->local()) {
 919	IdlError(file, line,
 920		 "Forward declaration of unconstrained interface '%s' "
 921		 "conflicts  with earlier forward declaration as local",
 922		 identifier);
 923	IdlErrorCont(f->file(), f->line(),
 924		     "('%s' forward declared as local here)");
 925      }
 926      //***?      if (f->repoIdSet()) setRepoId(f->repoId(), f->rifile(), f->riline());
 927      reg = 0;
 928    }
 929  }
 930  if (reg) {
 931    if (abstract) {
 932      thisType_ = new DeclaredType(IdlType::tk_abstract_interface, this, this);
 933    }
 934    else if (local) {
 935      thisType_ = new DeclaredType(IdlType::tk_local_interface, this, this);
 936      thisType_->setLocal();
 937    }
 938    else {
 939      thisType_ = new DeclaredType(IdlType::tk_objref, this, this);
 940    }
 941    Scope::current()->addDecl(identifier, 0, this, thisType_, file, line);
 942  }
 943}
 944
 945Forward::
 946~Forward()
 947{
 948  delete thisType_;
 949}
 950
 951Interface*
 952Forward::
 953definition() const
 954{
 955  if (firstForward_)
 956    return firstForward_->definition();
 957  else
 958    return definition_;
 959}
 960
 961void
 962Forward::
 963setDefinition(Interface* defn)
 964{
 965  definition_ = defn;
 966}
 967
 968
 969// Const
 970
 971Const::
 972Const(const char* file, int line, IDL_Boolean mainFile,
 973      IdlType* constType, const char* identifier, IdlExpr* expr)
 974
 975  : Decl(D_CONST, file, line, mainFile),
 976    DeclRepoId(identifier),
 977    constType_(constType)
 978{
 979  if (constType) delType_ = constType->shouldDelete();
 980  else           delType_ = 0;
 981
 982  if (!constType || !expr) return; // Ignore nulls due to earlier errors
 983
 984  IdlType* t = constType->unalias();
 985
 986  if (!t) { // Broken alias due to earlier error
 987    constKind_ = IdlType::tk_null;
 988    delete expr;
 989    return;
 990  }
 991  constKind_ = t->kind();
 992
 993  switch (constKind_) {
 994  case IdlType::tk_short:      v_.short_      = expr->evalAsShort();     break;
 995  case IdlType::tk_long:       v_.long_       = expr->evalAsLong();      break;
 996  case IdlType::tk_ushort:     v_.ushort_     = expr->evalAsUShort();    break;
 997  case IdlType::tk_ulong:      v_.ulong_      = expr->evalAsULong();     break;
 998  case IdlType::tk_float:      v_.float_      = expr->evalAsFloat();     break;
 999  case IdlType::tk_double:     v_.double_     = expr->evalAsDouble();    break;
1000  case IdlType::tk_boolean:    v_.boolean_    = expr->evalAsBoolean();   break;
1001  case IdlType::tk_char:       v_.char_       = expr->evalAsChar();      break;
1002  case IdlType::tk_octet:      v_.octet_      = expr->evalAsOctet();     break;
1003  case IdlType::tk_string:
1004    {
1005      v_.string_      = idl_strdup(expr->evalAsString());
1006      IDL_ULong bound = ((StringType*)t)->bound();
1007
1008      if (bound && strlen(v_.string_) > bound) {
1009	IdlError(file, line,
1010		 "Length of bounded string constant exceeds bound");
1011      }
1012      break;
1013    }
1014#ifdef HAS_LongLong
1015  case IdlType::tk_longlong:   v_.longlong_   = expr->evalAsLongLong();  break;
1016  case IdlType::tk_ulonglong:  v_.ulonglong_  = expr->evalAsULongLong(); break;
1017#endif
1018#ifdef HAS_LongDouble
1019  case IdlType::tk_longdouble: v_.longdouble_ = expr->evalAsLongDouble();break;
1020#endif
1021  case IdlType::tk_wchar:      v_.wchar_      = expr->evalAsWChar();     break;
1022  case IdlType::tk_wstring:
1023    {
1024      v_.wstring_     = idl_wstrdup(expr->evalAsWString());
1025      IDL_ULong bound = ((WStringType*)t)->bound();
1026
1027      if (bound && (unsigned)idl_wstrlen(v_.wstring_) > bound) {
1028	IdlError(file, line,
1029		 "Length of bounded wide string constant exceeds bound");
1030      }
1031      break;
1032    }
1033  case IdlType::tk_fixed:
1034    {
1035      IDL_Fixed* f = expr->evalAsFixed();
1036
1037      FixedType* ft = (FixedType*)t;
1038      if (ft->digits()) {
1039	// Check constant fits in the target type
1040	IDL_Fixed* g = new IDL_Fixed(f->truncate(ft->scale()));
1041
1042	if (g->fixed_digits() > ft->digits()) {
1043	  IdlError(file, line,
1044		   "Fixed point constant has too many digits to "
1045		   "fit fixed<%u,%u>",
1046		   ft->digits(), ft->scale());
1047	}
1048	else if (f->fixed_scale() > g->fixed_scale()) {
1049	  IdlWarning(file, line,
1050		     "Fixed point constant truncated to fit fixed<%u,%u>",
1051		     ft->digits(), ft->scale());
1052	}
1053	delete f;
1054	f = g;
1055      }
1056      v_.fixed_ = f;
1057      break;
1058    }
1059  case IdlType::tk_enum:
1060    v_.enumerator_ = expr->evalAsEnumerator((Enum*)((DeclaredType*)t)->decl());
1061    break;
1062
1063  default:
1064    IdlError(file, line, "Invalid type for constant: %s", t->kindAsString());
1065    break;
1066  }
1067  delete expr;
1068
1069  Scope::current()->addDecl(identifier, 0, this, constType, file, line);
1070}
1071
1072Const::
1073~Const()
1074{
1075  if (constKind_ == IdlType::tk_string)  delete [] v_.string_;
1076  if (constKind_ == IdlType::tk_wstring) delete [] v_.wstring_;
1077  if (constKind_ == IdlType::tk_fixed)   delete    v_.fixed_;
1078  if (delType_) delete constType_;
1079}
1080
1081#define CONST_AS(rt, op, tk, un) \
1082rt Const::op() const { \
1083  assert(constKind_ == IdlType::tk); \
1084  return v_.un; \
1085}
1086
1087CONST_AS(IDL_Short,        constAsShort,      tk_short,      short_)
1088CONST_AS(IDL_Long,         constAsLong,       tk_long,       long_)
1089CONST_AS(IDL_UShort,       constAsUShort,     tk_ushort,     ushort_)
1090CONST_AS(IDL_ULong,        constAsULong,      tk_ulong,      ulong_)
1091CONST_AS(IDL_Float,        constAsFloat,      tk_float,      float_)
1092CONST_AS(IDL_Double,       constAsDouble,     tk_double,     double_)
1093CONST_AS(IDL_Boolean,      constAsBoolean,    tk_boolean,    boolean_)
1094CONST_AS(IDL_Char,         constAsChar,       tk_char,       char_)
1095CONST_AS(IDL_Octet,        constAsOctet,      tk_octet,      octet_)
1096CONST_AS(const char*,      constAsString,     tk_string,     string_)
1097#ifdef HAS_LongLong
1098CONST_AS(IDL_LongLong,     constAsLongLong,   tk_longlong,   longlong_)
1099CONST_AS(IDL_ULongLong,    constAsULongLong,  tk_ulonglong,  ulonglong_)
1100#endif
1101#ifdef HAS_LongDouble
1102CONST_AS(IDL_LongDouble,   constAsLongDouble, tk_longdouble, longdouble_)
1103#endif
1104CONST_AS(IDL_WChar,        constAsWChar,      tk_wchar,      wchar_)
1105CONST_AS(const IDL_WChar*, constAsWString,    tk_wstring,    wstring_)
1106CONST_AS(Enumerator*,      constAsEnumerator, tk_enum,       enumerator_)
1107
1108IDL_Fixed*
1109Const::constAsFixed() const {
1110  assert(constKind_ == IdlType::tk_fixed);
1111
1112  // Have to copy the fixed object to get the memory management right
1113  return new IDL_Fixed(*v_.fixed_);
1114}
1115
1116
1117// Declarator
1118Declarator::
1119Declarator(const char* file, int line, IDL_Boolean mainFile,
1120	   const char* identifier, ArraySize* sizes)
1121
1122  : Decl(D_DECLARATOR, file, line, mainFile),
1123    DeclRepoId(identifier),
1124    sizes_(sizes),
1125    thisType_(0),
1126    alias_(0),
1127    attribute_(0)
1128{
1129}
1130
1131Declarator::
1132~Declarator()
1133{
1134  if (sizes_)    delete sizes_;
1135  if (thisType_) delete thisType_;
1136}
1137
1138const char*
1139Declarator::
1140kindAsString() const
1141{
1142  if (alias_)     return "typedef declarator";
1143  if (attribute_) return "attribute declarator";
1144                  return "declarator";
1145}
1146
1147void
1148Declarator::
1149setAlias(Typedef* td)
1150{
1151  alias_    = td;
1152  thisType_ = new DeclaredType(IdlType::tk_alias, this, this);
1153  if (td->aliasType() && td->aliasType()->local()) thisType_->setLocal();
1154  if (sizes_) checkValidType(file(), line(), td->aliasType());
1155}
1156
1157void
1158Declarator::
1159setAttribute(Attribute* at)
1160{
1161  attribute_ = at;
1162}
1163
1164// Typedef
1165Typedef::
1166Typedef(const char* file, int line, IDL_Boolean mainFile,
1167	IdlType* aliasType, IDL_Boolean constrType,
1168	Declarator* declarators)
1169
1170  : Decl(D_TYPEDEF, file, line, mainFile),
1171    aliasType_(aliasType),
1172    constrType_(constrType),
1173    declarators_(declarators)
1174{
1175  if (aliasType) delType_ = aliasType->shouldDelete();
1176  else           delType_ = 0;
1177
1178  if (aliasType) checkNotForward(file, line, aliasType);
1179
1180  for (Declarator* d = declarators; d; d = (Declarator*)d->next()) {
1181    d->setAlias(this);
1182    Scope::current()->addDecl(d->eidentifier(), 0, d, d->thisType(),
1183			      d->file(), d->line());
1184  }
1185}
1186
1187Typedef::
1188~Typedef()
1189{
1190  if (delType_)     delete aliasType_;
1191  if (declarators_) delete declarators_;
1192}
1193
1194
1195// Member
1196Member::
1197Member(const char* file, int line, IDL_Boolean mainFile,
1198       IdlType* memberType, IDL_Boolean constrType,
1199       Declarator* declarators)
1200
1201  : Decl(D_MEMBER, file, line, mainFile),
1202    memberType_(memberType),
1203    constrType_(constrType),
1204    declarators_(declarators)
1205{
1206  if (memberType) delType_ = memberType->shouldDelete();
1207  else {
1208    delType_ = 0;
1209    return;
1210  }
1211  checkNotForward(file, line, memberType);
1212
1213  IdlType* bareType = memberType->unalias();
1214
1215  if (bareType->kind() == IdlType::tk_struct) {
1216    Struct* s = (Struct*)((DeclaredType*)bareType)->decl();
1217    if (!s->finished()) {
1218      IdlError(file, line,
1219	       "Cannot create an instance of struct '%s' inside "
1220	       "its own definition", s->identifier());
1221    }
1222  }
1223  else if (bareType->kind() == IdlType::tk_union) {
1224    Union* u = (Union*)((DeclaredType*)bareType)->decl();
1225    if (!u->finished()) {
1226      IdlError(file, line,
1227	       "Cannot create an instance of union '%s' inside "
1228	       "its own definition", u->identifier());
1229    }
1230  }
1231  else if (bareType->kind() == IdlType::tk_sequence) {
1232    // Look for recursive sequence
1233    IdlType* t = bareType;
1234    while (t && t->kind() == IdlType::tk_sequence)
1235      t = ((SequenceType*)t)->seqType()->unalias();
1236
1237    if (!t) return; // Sequence of undeclared type
1238
1239    if (t->kind() == IdlType::tk_struct) {
1240      Struct* s = (Struct*)((DeclaredType*)t)->decl();
1241      if (!s->finished()) {
1242	s->setRecursive();
1243	IdlWarning(file, line,
1244		   "Anonymous sequences for recursive structures "
1245		   "are deprecated. Use a forward declaration instead.");
1246      }
1247    }
1248    else if (t->kind() == IdlType::tk_union) {
1249      Union* u = (Union*)((DeclaredType*)t)->decl();
1250      if (!u->finished()) {
1251	u->setRecursive();
1252	IdlWarning(file, line,
1253		   "Anonymous sequences for recursive unions "
1254		   "are deprecated. Use a forward declaration instead.");
1255      }
1256    }
1257    else if (t->kind() == IdlType::ot_structforward) {
1258      StructForward* f = (StructForward*)((DeclaredType*)t)->decl();
1259      Struct* s = f->definition();
1260      if (s) {
1261	if (!s->finished())
1262	  s->setRecursive();
1263      }
1264      else {
1265	char* ssn = f->scopedName()->toString();
1266	IdlError(file, line,
1267		 "Cannot use sequence of forward-declared struct '%s' "
1268		 "before it is fully defined", ssn);
1269	IdlErrorCont(f->file(), f->line(),
1270		     "('%s' forward-declared here)", f->identifier());
1271	delete [] ssn;
1272      }
1273    }
1274    else if (t->kind() == IdlType::ot_unionforward) {
1275      UnionForward* f = (UnionForward*)((DeclaredType*)t)->decl();
1276      Union* u = f->definition();
1277      if (u) {
1278	if (!u->finished())
1279	  u->setRecursive();
1280      }
1281      else {
1282	char* ssn = f->scopedName()->toString();
1283	IdlError(file, line,
1284		 "Cannot use sequence of forward-declared union '%s' "
1285		 "before it is fully defined", ssn);
1286	IdlErrorCont(f->file(), f->line(),
1287		     "('%s' forward-declared here)", f->identifier());
1288	delete [] ssn;
1289      }
1290    }
1291  }
1292  for (Declarator* d = declarators; d; d = (Declarator*)d->next()) {
1293    Scope::current()->addInstance(d->eidentifier(), d, memberType,
1294				  d->file(), d->line());
1295  }
1296}
1297
1298Member::
1299~Member()
1300{
1301  if (declarators_) delete declarators_;
1302  if (delType_)     delete memberType_;
1303}
1304
1305// Struct
1306Struct::
1307Struct(const char* file, int line, IDL_Boolean mainFile,
1308       const char* identifier)
1309
1310  : Decl(D_STRUCT, file, line, mainFile),
1311    DeclRepoId(identifier),
1312    members_(0),
1313    recursive_(0),
1314    finished_(0)
1315{
1316  // Look for forward struct
1317  Scope::Entry* se = Scope::current()->find(identifier);
1318
1319  if (se &&
1320      se->kind() == Scope::Entry::E_DECL &&
1321      se->decl()->kind() == Decl::D_STRUCTFORWARD) {
1322
1323    StructForward* f = (StructForward*)se->decl();
1324
1325    if (strcmp(f->file(), file)) {
1326      IdlError(file, line,
1327	       "Struct '%s' defined in different source file to "
1328	       "its forward declaration", identifier);
1329      IdlErrorCont(f->file(), f->line(),
1330		   "('%s' forward declared here)", identifier);
1331    }
1332    if (strcmp(f->prefix(), prefix())) {
1333      IdlError(file, line,
1334	       "In declaration of struct '%s', repository id "
1335	       "prefix '%s' differs from that of forward declaration",
1336	       identifier, prefix());
1337
1338      IdlErrorCont(f->file(), f->line(),
1339		   "('%s' forward declared here with prefix '%s')",
1340		   f->identifier(), f->prefix());
1341    }
1342    if (f->repoIdSet()) setRepoId(f->repoId(), f->rifile(), f->riline());
1343    f->setDefinition(this);
1344    Scope::current()->remEntry(se);
1345  }
1346  Scope* s  = Scope::current()->newStructScope(identifier, file, line);
1347  thisType_ = new DeclaredType(IdlType::tk_struct, this, this);
1348  Scope::current()->addDecl(identifier, s, this, thisType_, file, line);
1349  Scope::startScope(s);
1350  Prefix::newScope(identifier);
1351}
1352
1353Struct::
1354~Struct()
1355{
1356  if (members_) delete members_;
1357  delete thisType_;
1358}
1359
1360void
1361Struct::
1362finishConstruction(Member* members)
1363{
1364  // Is this a local type?
1365  for (Member* m = members; m; m = (Member*)m->next()) {
1366    if (m->memberType() && m->memberType()->local()) {
1367      thisType()->setLocal();
1368      break;
1369    }
1370  }
1371  members_ = members;
1372  Prefix::endScope();
1373  Scope::endScope();
1374  finished_ = 1;
1375  mostRecent_ = this;
1376}
1377
1378// StructForward
1379StructForward::
1380StructForward(const char* file, int line, IDL_Boolean mainFile,
1381	      const char* identifier)
1382  : Decl(D_STRUCTFORWARD, file, line, mainFile),
1383    DeclRepoId(identifier),
1384    definition_(0),
1385    firstForward_(0),
1386    thisType_(0)
1387{
1388  Scope::Entry* se  = Scope::current()->find(identifier);
1389  IDL_Boolean   reg = 1;
1390
1391  if (se && se->kind() == Scope::Entry::E_DECL) {
1392
1393    if (se->decl()->kind() == D_STRUCT) {
1394      Struct* s = (Struct*)se->decl();
1395      definition_ = s;
1396
1397      if (strcmp(s->file(), file)) {
1398	IdlError(file, line,
1399		 "Struct '%s' forward declared in different source file to "
1400		 "its definition", identifier);
1401	IdlErrorCont(s->file(), s->line(),
1402		     "('%s' defined here)", identifier);
1403      }
1404      if (strcmp(s->prefix(), prefix())) {
1405	IdlError(file, line,
1406		 "In forward declaration of struct '%s', repository "
1407		 "id prefix '%s' differs from that of earlier declaration",
1408		 identifier, prefix());
1409
1410	IdlErrorCont(s->file(), s->line(),
1411		     "('%s' fully declared here with prefix '%s')",
1412		     s->identifier(), s->prefix());
1413      }
1414      reg = 0;
1415    }
1416    else if (se->decl()->kind() == D_STRUCTFORWARD) {
1417      StructForward* s = (StructForward*)se->decl();
1418      firstForward_ = s;
1419
1420      if (strcmp(s->file(), file)) {
1421	IdlError(file, line,
1422		 "Struct '%s' forward declared in more than one "
1423		 "source file", identifier);
1424	IdlErrorCont(s->file(), s->line(),
1425		     "('%s' also forward declared here)", identifier);
1426      }
1427      if (strcmp(s->prefix(), prefix())) {
1428	IdlError(file, line,
1429		 "In forward declaration of struct '%s', repository "
1430		 "id prefix '%s' differs from that of earlier declaration",
1431		 identifier, prefix());
1432
1433	IdlErrorCont(s->file(), s->line(),
1434		     "('%s' forward declared here with prefix '%s')",
1435		     s->identifier(), s->prefix());
1436      }
1437      reg = 0;
1438    }
1439  }
1440  if (reg) {
1441    thisType_ = new DeclaredType(IdlType::ot_structforward, this, this);
1442    Scope::current()->addDecl(identifier, 0, this, thisType_, file, line);
1443  }
1444}
1445
1446StructForward::
1447~StructForward()
1448{