source: translator/Parser.old/DeclarationNode.cc @ 3c70d38

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since 3c70d38 was 51b7345, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

initial commit

  • Property mode set to 100644
File size: 30.3 KB
Line 
1#include <string>
2#include <list>
3#include <iterator>
4#include <algorithm>
5#include <cassert>
6
7#include "ParseNode.h"
8#include "TypeData.h"
9#include "utility.h"
10#include "SynTree/Declaration.h"
11#include "SynTree/Expression.h"
12#include "SynTree/Initializer.h"
13#include "SemanticError.h"
14#include "UniqueName.h"
15#include "LinkageSpec.h"
16
17using namespace std;
18
19/* these must remain in the same order as the corresponding DeclarationNode enumerations */
20const char *DeclarationNode::qualifierName[] = { "const", "restrict", "volatile", "lvalue" };
21const char *DeclarationNode::basicTypeName[] = { "char", "int", "float", "double", "void", "bool", "complex", "imaginary" };
22const char *DeclarationNode::modifierName[] = { "signed", "unsigned", "short", "long" };
23const char *DeclarationNode::tyConName[] = { "struct", "union", "context" };
24const char *DeclarationNode::typeClassName[] = { "type", "dtype", "ftype" };
25
26UniqueName DeclarationNode::anonymous( "__anonymous" );
27
28extern LinkageSpec::Type linkage;               /* defined in cfa.y */
29
30DeclarationNode*
31DeclarationNode::clone() const
32{
33  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
34  newnode->type = maybeClone( type );
35  newnode->name = name;
36  newnode->storageClasses = storageClasses;
37  newnode->bitfieldWidth = maybeClone( bitfieldWidth );
38  newnode->hasEllipsis = hasEllipsis;
39  newnode->initializer = initializer;
40  newnode->next = maybeClone( next );
41  newnode->linkage = linkage;
42  return newnode;
43}
44
45DeclarationNode::DeclarationNode( char *filename, int lineno )
46  : ParseNode( "", filename, lineno ), type( 0 ), bitfieldWidth( 0 ), initializer( 0 ), hasEllipsis( false ), linkage( ::linkage )
47{
48}
49
50DeclarationNode::~DeclarationNode()
51{
52  delete type;
53  delete bitfieldWidth;
54  delete initializer;
55}
56
57bool
58DeclarationNode::get_hasEllipsis() const
59{
60  return hasEllipsis;
61}
62
63const char *storageClassName[] =
64{
65  // order must correspond with DeclarationNode::StorageClass
66  "static",
67  "auto",
68  "extern",
69  "register",
70  "inline",
71  "fortran",
72};
73
74void
75DeclarationNode::print( std::ostream &os, int indent ) const
76{
77  os << string(indent,  ' ');
78  if( name == "" ) {
79///     os << "An unnamed ";
80  } else {
81    os << name << ": a ";
82  }
83  if( linkage != LinkageSpec::Cforall ) {
84    os << LinkageSpec::toString( linkage ) << " ";
85  }
86  printEnums( storageClasses.begin(), storageClasses.end(), storageClassName, os );
87  if( type ) {
88    type->print( os, indent );
89  } else {
90    os << "untyped entity ";
91  }
92  if( bitfieldWidth ) {
93    os << endl << string(indent+2,  ' ') << "with bitfield width ";
94    bitfieldWidth->printOneLine( os );
95  }
96
97  if( initializer != 0 ) {
98    os << endl << string(indent+2,  ' ') << "with initializer ";
99    initializer->printOneLine( os );
100  }
101
102  os << endl;
103}
104
105void
106DeclarationNode::printList( std::ostream &os, int indent ) const
107{
108  ParseNode::printList( os, indent );
109  if( hasEllipsis ) {
110    os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
111  }
112}
113
114/* static class method */
115DeclarationNode *
116DeclarationNode::newFunction( struct token &tok, DeclarationNode *ret, DeclarationNode *param, StatementNode *body )
117{
118  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
119  newnode->name = assign_strptr( tok.str );
120
121  newnode->type = new TypeData( TypeData::Function );
122  newnode->type->function->params = param;
123  newnode->type->function->body = body;
124  if( body ) {
125    newnode->type->function->hasBody = true;
126  }
127
128  if( ret ) {
129    newnode->type->base = ret->type;
130    ret->type = 0;
131    delete ret;
132  }
133
134  return newnode;
135}
136
137DeclarationNode *
138DeclarationNode::newFunction( char *filename, int lineno, DeclarationNode *ret, DeclarationNode *param, StatementNode *body )
139{
140  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
141
142  newnode->type = new TypeData( TypeData::Function );
143  newnode->type->function->params = param;
144  newnode->type->function->body = body;
145  if( body ) {
146    newnode->type->function->hasBody = true;
147  }
148
149  if( ret ) {
150    newnode->type->base = ret->type;
151    ret->type = 0;
152    delete ret;
153  }
154
155  return newnode;
156}
157
158/* static class method */
159DeclarationNode *
160DeclarationNode::newQualifier( Qualifier q, char *filename, int lineno )
161{
162  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
163  newnode->type = new TypeData();
164  newnode->type->qualifiers.push_back( q );
165  return newnode;
166}
167
168/* static class method */
169DeclarationNode *
170DeclarationNode::newStorageClass( StorageClass sc, char *filename, int lineno )
171{
172  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
173  newnode->storageClasses.push_back( sc );
174  return newnode;
175}
176
177/* static class method */
178DeclarationNode *
179DeclarationNode::newBasicType( BasicType bt, char *filename, int lineno )
180{
181  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
182  newnode->type = new TypeData( TypeData::Basic );
183  newnode->type->basic->typeSpec.push_back( bt );
184  return newnode;
185}
186
187/* static class method */
188DeclarationNode *
189DeclarationNode::newModifier( Modifier mod, char *filename, int lineno )
190{
191  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
192  newnode->type = new TypeData( TypeData::Basic );
193  newnode->type->basic->modifiers.push_back( mod );
194  return newnode;
195}
196
197/* static class method */
198DeclarationNode *
199DeclarationNode::newForall( DeclarationNode* forall, char *filename, int lineno )
200{
201  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
202  newnode->type = new TypeData( TypeData::Unknown );
203  newnode->type->forall = forall;
204  return newnode;
205}
206
207/* static class method */
208DeclarationNode *
209DeclarationNode::newFromTypedef( struct token &tok )
210{
211  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
212  newnode->type = new TypeData( TypeData::SymbolicInst );
213  newnode->type->symbolic->name = assign_strptr( tok.str );
214  newnode->type->symbolic->isTypedef = true;
215  newnode->type->symbolic->params = 0;
216  return newnode;
217}
218
219/* static class method */
220DeclarationNode *
221DeclarationNode::newAggregate( TyCon kind, struct token &tok, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields )
222{
223  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
224  newnode->type = new TypeData( TypeData::Aggregate );
225  newnode->type->aggregate->kind = kind;
226  newnode->type->aggregate->name = assign_strptr( tok.str );
227  if( newnode->type->aggregate->name == "" ) {
228    newnode->type->aggregate->name = DeclarationNode::anonymous.newName();
229  }
230  newnode->type->aggregate->params = formals;
231  newnode->type->aggregate->actuals = actuals;
232  newnode->type->aggregate->members = fields;
233  return newnode;
234}
235
236DeclarationNode *
237DeclarationNode::newAggregate( TyCon kind, char *filename, int lineno, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields )
238{
239  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
240  newnode->type = new TypeData( TypeData::Aggregate );
241  newnode->type->aggregate->kind = kind;
242  newnode->type->aggregate->name = DeclarationNode::anonymous.newName();
243  newnode->type->aggregate->params = formals;
244  newnode->type->aggregate->actuals = actuals;
245  newnode->type->aggregate->members = fields;
246  return newnode;
247}
248
249/* static class method */
250DeclarationNode *
251DeclarationNode::newEnum( struct token &tok, DeclarationNode *constants )
252{
253  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
254  newnode->name = assign_strptr( tok.str );
255  newnode->type = new TypeData( TypeData::Enum );
256  newnode->type->enumeration->name = newnode->name;
257  if( newnode->type->enumeration->name == "" ) {
258    newnode->type->enumeration->name = DeclarationNode::anonymous.newName();
259  }
260  newnode->type->enumeration->constants = constants;
261  return newnode;
262}
263
264/* static class method */
265DeclarationNode *
266DeclarationNode::newEnum( char *filename, int lineno, DeclarationNode *constants )
267{
268  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
269  newnode->type = new TypeData( TypeData::Enum );
270  newnode->type->enumeration->name = newnode->name;
271  newnode->type->enumeration->name = DeclarationNode::anonymous.newName();
272  newnode->type->enumeration->constants = constants;
273  return newnode;
274}
275
276/* static class method */
277DeclarationNode *
278DeclarationNode::newEnumConstant( struct token &tok, ExpressionNode *constant )
279{
280  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
281  newnode->name = assign_strptr( tok.str );
282  // do something with the constant
283  return newnode;
284}
285
286/* static class method */
287DeclarationNode *
288DeclarationNode::newName( struct token &tok )
289{
290  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
291  newnode->name = assign_strptr( tok.str );
292  return newnode;
293}
294
295/* static class method */
296DeclarationNode *
297DeclarationNode::newFromTypeGen( struct token &tok, ExpressionNode *params )
298{
299  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
300  newnode->type = new TypeData( TypeData::SymbolicInst );
301  newnode->type->symbolic->name = assign_strptr( tok.str );
302  newnode->type->symbolic->isTypedef = false;
303  newnode->type->symbolic->actuals = params;
304  return newnode;
305}
306
307/* static class method */
308DeclarationNode *
309DeclarationNode::newTypeParam( TypeClass tc, std::string* name, char *filename, int lineno )
310{
311  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
312  newnode->name = assign_strptr( name );
313  newnode->type = new TypeData( TypeData::Variable );
314  newnode->type->variable->tyClass = tc;
315  newnode->type->variable->name = newnode->name;
316  return newnode;
317}
318
319/* static class method */
320DeclarationNode *
321DeclarationNode::newContext( struct token &tok, DeclarationNode *params, DeclarationNode *asserts )
322{
323  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
324  newnode->type = new TypeData( TypeData::Aggregate );
325  newnode->type->aggregate->kind = Context;
326  newnode->type->aggregate->params = params;
327  newnode->type->aggregate->members = asserts;
328  newnode->type->aggregate->name = assign_strptr( tok.str );
329  return newnode;
330}
331
332/* static class method */
333DeclarationNode *
334DeclarationNode::newContextUse( struct token &tok, ExpressionNode *params )
335{
336  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
337  newnode->type = new TypeData( TypeData::AggregateInst );
338  newnode->type->aggInst->aggregate = new TypeData( TypeData::Aggregate );
339  newnode->type->aggInst->aggregate->aggregate->kind = Context;
340  newnode->type->aggInst->aggregate->aggregate->name = assign_strptr( tok.str );
341  newnode->type->aggInst->params = params;
342  return newnode;
343}
344
345/* static class method */
346DeclarationNode *
347DeclarationNode::newTypeDecl( struct token &tok, DeclarationNode *typeParams )
348{
349  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
350  newnode->name = assign_strptr( tok.str );
351  newnode->type = new TypeData( TypeData::Symbolic );
352  newnode->type->symbolic->isTypedef = false;
353  newnode->type->symbolic->params = typeParams;
354  newnode->type->symbolic->name = newnode->name;
355  return newnode;
356}
357
358/* static class method */
359DeclarationNode *
360DeclarationNode::newPointer( DeclarationNode *qualifiers, char *filename, int lineno )
361{
362  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
363  newnode->type = new TypeData( TypeData::Pointer );
364  return newnode->addQualifiers( qualifiers );
365}
366
367/* static class method */
368DeclarationNode *
369DeclarationNode::newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic, char *filename, int lineno )
370{
371  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
372  newnode->type = new TypeData( TypeData::Array );
373  newnode->type->array->dimension = size;
374  newnode->type->array->isStatic = isStatic;
375  newnode->type->array->isVarLen = false;
376  return newnode->addQualifiers( qualifiers );
377}
378
379/* static class method */
380DeclarationNode *
381DeclarationNode::newVarArray( DeclarationNode *qualifiers, char *filename, int lineno )
382{
383  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
384  newnode->type = new TypeData( TypeData::Array );
385  newnode->type->array->dimension = 0;
386  newnode->type->array->isStatic = false;
387  newnode->type->array->isVarLen = true;
388  return newnode->addQualifiers( qualifiers );
389}
390
391/* static class method */
392DeclarationNode *
393DeclarationNode::newBitfield( ExpressionNode *size )
394{
395  DeclarationNode *newnode = new DeclarationNode( size->get_filename(), size->get_lineno() );
396  newnode->bitfieldWidth = size;
397  return newnode;
398}
399
400/* static class method */
401DeclarationNode *
402DeclarationNode::newTuple( DeclarationNode *members, char *filename, int lineno )
403{
404  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
405  newnode->type = new TypeData( TypeData::Tuple );
406  newnode->type->tuple->members = members;
407  return newnode;
408}
409
410/* static class method */
411DeclarationNode *
412DeclarationNode::newTypeof( ExpressionNode *expr, char *filename, int lineno )
413{
414  DeclarationNode *newnode = new DeclarationNode( filename, lineno );
415  newnode->type = new TypeData( TypeData::Typeof );
416  newnode->type->typeexpr->expr = expr;
417  return newnode;
418}
419
420static void
421addQualifiersToType( TypeData *&src, TypeData *dst )
422{
423  if( src && dst ) {
424    if( src->forall && dst->kind == TypeData::Function ) {
425      if( dst->forall ) {
426        dst->forall->appendList( src->forall );
427      } else {
428        dst->forall = src->forall;
429      }
430      src->forall = 0;
431    }
432    if( dst->base ) {
433      addQualifiersToType( src, dst->base );
434    } else if( dst->kind == TypeData::Function ) {
435      dst->base = src;
436      src = 0;
437    } else {
438      dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
439    }
440  }
441}
442     
443DeclarationNode *
444DeclarationNode::addQualifiers( DeclarationNode *q )
445{
446  if( q ) {
447    storageClasses.splice( storageClasses.end(), q->storageClasses );
448    if( q->type ) {
449      if( !type ) {
450        type = new TypeData;
451      }
452      addQualifiersToType( q->type, type );
453      if( q->type && q->type->forall ) {
454        if( type->forall ) {
455          type->forall->appendList( q->type->forall );
456        } else {
457          type->forall = q->type->forall;
458        }
459        q->type->forall = 0;
460      }
461    }
462  }
463  lineno = min( lineno, q->lineno );
464  delete q;
465  return this;
466}
467
468DeclarationNode *
469DeclarationNode::copyStorageClasses( DeclarationNode *q )
470{
471  storageClasses = q->storageClasses;
472  return this;
473}
474
475static void
476addTypeToType( TypeData *&src, TypeData *&dst )
477{
478  if( src && dst ) {
479    if( src->forall && dst->kind == TypeData::Function ) {
480      if( dst->forall ) {
481        dst->forall->appendList( src->forall );
482      } else {
483        dst->forall = src->forall;
484      }
485      src->forall = 0;
486    }
487    if( dst->base ) {
488      addTypeToType( src, dst->base );
489    } else {
490      switch( dst->kind ) {
491      case TypeData::Unknown:
492        src->qualifiers.splice( src->qualifiers.end(), dst->qualifiers );
493        dst = src;
494        src = 0;
495        break;
496
497      case TypeData::Basic:
498        dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
499        if( src->kind != TypeData::Unknown ) {
500          assert( src->kind == TypeData::Basic );
501          dst->basic->modifiers.splice( dst->basic->modifiers.end(), src->basic->modifiers );
502          dst->basic->typeSpec.splice( dst->basic->typeSpec.end(), src->basic->typeSpec );
503        }
504        break;
505
506      default:
507        switch( src->kind ) {
508        case TypeData::Aggregate:
509        case TypeData::Enum:
510          dst->base = new TypeData( TypeData::AggregateInst );
511          dst->base->aggInst->aggregate = src;
512          if( src->kind == TypeData::Aggregate ) {
513            dst->base->aggInst->params = maybeClone( src->aggregate->actuals );
514          }
515          dst->base->qualifiers.splice( dst->base->qualifiers.end(), src->qualifiers );
516          src = 0;
517          break;
518         
519        default:
520          if( dst->forall ) {
521            dst->forall->appendList( src->forall );
522          } else {
523            dst->forall = src->forall;
524          }
525          src->forall = 0;
526          dst->base = src;
527          src = 0;
528        }
529      }
530    }
531  }
532}
533
534DeclarationNode *
535DeclarationNode::addType( DeclarationNode *o )
536{
537  if( o ) {
538    storageClasses.splice( storageClasses.end(), o->storageClasses );
539    if ( o->type ) {
540      if( !type ) {
541        if( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
542          type = new TypeData( TypeData::AggregateInst );
543          type->aggInst->aggregate = o->type;
544          if( o->type->kind == TypeData::Aggregate ) {
545            type->aggInst->params = maybeClone( o->type->aggregate->actuals );
546          }
547          type->qualifiers.splice( type->qualifiers.end(), o->type->qualifiers );
548        } else {
549          type = o->type;
550        }
551        o->type = 0;
552      } else {
553        addTypeToType( o->type, type );
554      }
555    }
556    if( o->bitfieldWidth ) {
557      bitfieldWidth = o->bitfieldWidth;
558    }
559  }
560  lineno = min( lineno, o->lineno );
561  delete o;
562  return this;
563}
564
565DeclarationNode *
566DeclarationNode::addTypedef()
567{
568  TypeData *newtype = new TypeData( TypeData::Symbolic );
569  newtype->symbolic->params = 0;
570  newtype->symbolic->isTypedef = true;
571  newtype->symbolic->name = name;
572  newtype->base = type;
573  type = newtype;
574  return this;
575}
576
577DeclarationNode *
578DeclarationNode::addAssertions( DeclarationNode* assertions )
579{
580  assert( type );
581  switch( type->kind ) {
582  case TypeData::Symbolic:
583    if( type->symbolic->assertions ) {
584      type->symbolic->assertions->appendList( assertions );
585    } else {
586      type->symbolic->assertions = assertions;
587    }
588    break;
589   
590  case TypeData::Variable:
591    if( type->variable->assertions ) {
592      type->variable->assertions->appendList( assertions );
593    } else {
594      type->variable->assertions = assertions;
595    }
596    break;
597   
598  default:
599    assert( false );
600  }
601   
602  return this;
603}
604
605DeclarationNode *
606DeclarationNode::addName( struct token &tok )
607{
608  name = assign_strptr( tok.str );
609  lineno = min( lineno, tok.lineno );
610  return this;
611}
612
613DeclarationNode *
614DeclarationNode::addBitfield( ExpressionNode *size )
615{
616  bitfieldWidth = size;
617  return this;
618}
619
620DeclarationNode *
621DeclarationNode::addVarArgs()
622{
623  assert( type );
624  hasEllipsis = true;
625  return this;
626}
627
628DeclarationNode *
629DeclarationNode::addFunctionBody( StatementNode *body )
630{
631  assert( type );
632  assert( type->kind == TypeData::Function );
633  assert( type->function->body == 0 );
634  type->function->body = body;
635  type->function->hasBody = true;
636  return this;
637}
638
639DeclarationNode *
640DeclarationNode::addOldDeclList( DeclarationNode *list )
641{
642  assert( type );
643  assert( type->kind == TypeData::Function );
644  assert( type->function->oldDeclList == 0 );
645  type->function->oldDeclList = list;
646  return this;
647}
648
649static void
650setBase( TypeData *&type, TypeData *newType )
651{
652  if( type ) {
653    TypeData *prevBase = type;
654    TypeData *curBase = type->base;
655    while( curBase != 0 ) {
656      prevBase = curBase;
657      curBase = curBase->base;
658    }
659    prevBase->base = newType;
660  } else {
661    type = newType;
662  }
663}
664
665DeclarationNode *
666DeclarationNode::addPointer( DeclarationNode *p )
667{
668  if( p ) {
669    assert( p->type->kind == TypeData::Pointer );
670    setBase( type, p->type );
671    p->type = 0;
672    delete p;
673  }
674  return this;
675}
676
677DeclarationNode *
678DeclarationNode::addArray( DeclarationNode *a )
679{
680  if( a ) {
681    assert( a->type->kind == TypeData::Array );
682    setBase( type, a->type );
683    a->type = 0;
684    delete a;
685  }
686  return this;
687}
688
689DeclarationNode *
690DeclarationNode::addNewPointer( DeclarationNode *p )
691{
692  if( p ) {
693    assert( p->type->kind == TypeData::Pointer );
694    if( type ) {
695      switch( type->kind ) {
696      case TypeData::Aggregate:
697      case TypeData::Enum:
698        p->type->base = new TypeData( TypeData::AggregateInst );
699        p->type->base->aggInst->aggregate = type;
700        if( type->kind == TypeData::Aggregate ) {
701          p->type->base->aggInst->params = maybeClone( type->aggregate->actuals );
702        }
703        p->type->base->qualifiers.splice( p->type->base->qualifiers.end(), type->qualifiers );
704        break;
705       
706      default:
707        p->type->base = type;
708      }
709      type = 0;
710    }
711    delete this;
712    return p;
713  } else {
714    return this;
715  }
716}
717
718static TypeData *
719findLast( TypeData *a )
720{
721  assert( a );
722  TypeData *cur = a;
723  while( cur->base ) {
724    cur = cur->base;
725  }
726  return cur;
727}
728
729DeclarationNode *
730DeclarationNode::addNewArray( DeclarationNode *a )
731{
732  if( a ) {
733    assert( a->type->kind == TypeData::Array );
734    TypeData *lastArray = findLast( a->type );
735    if( type ) { 
736      switch( type->kind ) {
737      case TypeData::Aggregate:
738      case TypeData::Enum:
739        lastArray->base = new TypeData( TypeData::AggregateInst );
740        lastArray->base->aggInst->aggregate = type;
741        if( type->kind == TypeData::Aggregate ) {
742          lastArray->base->aggInst->params = maybeClone( type->aggregate->actuals );
743        }
744        lastArray->base->qualifiers.splice( lastArray->base->qualifiers.end(), type->qualifiers );
745        break;
746       
747      default:
748        lastArray->base = type;
749      }
750      type = 0;
751    }
752    delete this;
753    return a;
754  } else {
755    return this;
756  }
757}
758
759DeclarationNode *
760DeclarationNode::addParamList( DeclarationNode *params )
761{
762  TypeData *ftype = new TypeData( TypeData::Function );
763  ftype->function->params = params;
764  setBase( type, ftype );
765  return this;
766}
767
768static TypeData*
769addIdListToType( TypeData *type, DeclarationNode *ids )
770{
771  if( type ) {
772    if( type->kind != TypeData::Function ) {
773      type->base = addIdListToType( type->base, ids );
774    } else {
775      type->function->idList = ids;
776    }
777    return type;
778  } else {
779    TypeData *newtype = new TypeData( TypeData::Function );
780    newtype->function->idList = ids;
781    return newtype;
782  }
783}
784   
785DeclarationNode *
786DeclarationNode::addIdList( DeclarationNode *ids )
787{
788  type = addIdListToType( type, ids );
789  return this;
790}
791
792DeclarationNode *
793DeclarationNode::addInitializer( InitializerNode *init )
794{
795  //assert
796  initializer = init;
797  return this;
798}
799
800DeclarationNode *
801DeclarationNode::cloneBaseType( struct token &tok )
802{
803  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
804  TypeData *srcType = type;
805  while( srcType->base ) {
806    srcType = srcType->base;
807  }
808  newnode->type = maybeClone( srcType );
809  if( newnode->type->kind == TypeData::AggregateInst ) {
810    // don't duplicate members
811    if( newnode->type->aggInst->aggregate->kind == TypeData::Enum ) {
812      delete newnode->type->aggInst->aggregate->enumeration->constants;
813      newnode->type->aggInst->aggregate->enumeration->constants = 0;
814    } else {
815      assert( newnode->type->aggInst->aggregate->kind == TypeData::Aggregate );
816      delete newnode->type->aggInst->aggregate->aggregate->members;
817      newnode->type->aggInst->aggregate->aggregate->members = 0;
818    }
819  }
820  newnode->type->forall = maybeClone( type->forall );
821  newnode->storageClasses = storageClasses;
822  newnode->name = assign_strptr( tok.str );
823  return newnode;
824}
825
826DeclarationNode *
827DeclarationNode::cloneBaseType( DeclarationNode *o )
828{
829  if( o ) {
830    o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
831    if ( type ) {
832      TypeData *srcType = type;
833      while( srcType->base ) {
834        srcType = srcType->base;
835      }
836      TypeData *newType = srcType->clone();
837      if( newType->kind == TypeData::AggregateInst ) {
838        // don't duplicate members
839        if( newType->aggInst->aggregate->kind == TypeData::Enum ) {
840          delete newType->aggInst->aggregate->enumeration->constants;
841          newType->aggInst->aggregate->enumeration->constants = 0;
842        } else {
843          assert( newType->aggInst->aggregate->kind == TypeData::Aggregate );
844          delete newType->aggInst->aggregate->aggregate->members;
845          newType->aggInst->aggregate->aggregate->members = 0;
846        }
847      }
848      newType->forall = maybeClone( type->forall );
849      if( !o->type ) {
850        o->type = newType;
851      } else {
852        addTypeToType( newType, o->type );
853        delete newType;
854      }
855    }
856  }
857  return o;
858}
859
860DeclarationNode *
861DeclarationNode::cloneType( struct token &tok )
862{
863  DeclarationNode *newnode = new DeclarationNode( tok.filename, tok.lineno );
864  newnode->type = maybeClone( type );
865  newnode->storageClasses = storageClasses;
866  newnode->name = assign_strptr( tok.str );
867  return newnode;
868}
869
870DeclarationNode *
871DeclarationNode::cloneType( DeclarationNode *o )
872{
873  if( o ) {
874    o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
875    if ( type ) {
876      TypeData *newType = type->clone();
877      if( !o->type ) {
878        o->type = newType;
879      } else {
880        addTypeToType( newType, o->type );
881        delete newType;
882      }
883    }
884  }
885  return o;
886}
887
888DeclarationNode *
889DeclarationNode::appendList( DeclarationNode *node )
890{
891  if( node != 0 ) {
892    set_link( node );
893  }
894  return this;
895}
896
897DeclarationNode*
898DeclarationNode::extractAggregate() const
899{
900  if( type ) {
901    TypeData *ret = type->extractAggregate();
902    if( ret ) {
903      DeclarationNode *newnode = new DeclarationNode( filename, lineno );
904      newnode->type = ret;
905      return newnode;
906    } else {
907      return 0;
908    }
909  } else {
910    return 0;
911  }
912}
913
914void buildList( const DeclarationNode *firstNode, std::list< Declaration* > &outputList )
915{
916  SemanticError errors;
917  std::back_insert_iterator< std::list< Declaration* > > out( outputList );
918  const DeclarationNode *cur = firstNode;
919  while( cur ) {
920    try {
921      if( DeclarationNode *extr = cur->extractAggregate() ) {
922        // handle the case where a structure declaration is contained within an object or type
923        // declaration
924        Declaration *decl = extr->build();
925        if( decl ) {
926          *out++ = decl;
927        }
928      }
929      Declaration *decl = cur->build();
930      if( decl ) {
931        *out++ = decl;
932      }
933    } catch( SemanticError &e ) {
934      errors.append( e );
935    }
936    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
937  }
938  if( !errors.isEmpty() ) {
939    throw errors;
940  }
941}
942
943void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType* > &outputList )
944{
945  SemanticError errors;
946  std::back_insert_iterator< std::list< DeclarationWithType* > > out( outputList );
947  const DeclarationNode *cur = firstNode;
948  while( cur ) {
949    try {
950///       if( DeclarationNode *extr = cur->extractAggregate() ) {
951///     // handle the case where a structure declaration is contained within an object or type
952///     // declaration
953///     Declaration *decl = extr->build();
954///     if( decl ) {
955///           *out++ = decl;
956///     }
957///       }
958      Declaration *decl = cur->build();
959      if( decl ) {
960        if( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
961          *out++ = dwt;
962        } else if( StructDecl *agg = dynamic_cast< StructDecl* >( decl ) ) {
963          StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
964          *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
965          delete agg;
966        } else if( UnionDecl *agg = dynamic_cast< UnionDecl* >( decl ) ) {
967          UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
968          *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
969        }
970      }
971    } catch( SemanticError &e ) {
972      errors.append( e );
973    }
974    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
975  }
976  if( !errors.isEmpty() ) {
977    throw errors;
978  }
979}
980
981void buildTypeList( const DeclarationNode *firstNode, std::list< Type* > &outputList )
982{
983  SemanticError errors;
984  std::back_insert_iterator< std::list< Type* > > out( outputList );
985  const DeclarationNode *cur = firstNode;
986  while( cur ) {
987    try {
988      *out++ = cur->buildType();
989    } catch( SemanticError &e ) {
990      errors.append( e );
991    }
992    cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
993  }
994  if( !errors.isEmpty() ) {
995    throw errors;
996  }
997}
998
999Declaration *
1000DeclarationNode::build() const
1001{
1002
1003  if( !type ) {
1004    if( buildInline() ) {
1005      throw SemanticError( "invalid inline specification in declaration of ", this );
1006    } else {
1007      return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) );
1008    }
1009  } else {
1010    Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildInline(), linkage, maybeBuild< Initializer >(initializer) );
1011    return newDecl;
1012  }
1013  // we should never get here
1014  assert( false );
1015  return 0;
1016}
1017
1018Type *
1019DeclarationNode::buildType() const
1020{
1021
1022  assert( type );
1023 
1024  switch( type->kind ) {
1025  case TypeData::Enum:
1026    return new EnumInstType( type->buildQualifiers(), type->enumeration->name );
1027   
1028  case TypeData::Aggregate: {
1029    ReferenceToType *ret;
1030    switch( type->aggregate->kind ) {
1031    case DeclarationNode::Struct:
1032      ret = new StructInstType( type->buildQualifiers(), type->aggregate->name );
1033      break;
1034
1035    case DeclarationNode::Union:
1036      ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name );
1037      break;
1038
1039    case DeclarationNode::Context:
1040      ret = new ContextInstType( type->buildQualifiers(), type->aggregate->name );
1041      break;
1042
1043    default:
1044      assert( false );
1045    }
1046    buildList( type->aggregate->actuals, ret->get_parameters() );
1047    return ret;
1048  }
1049 
1050  case TypeData::Symbolic: {
1051    TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name );
1052    buildList( type->symbolic->actuals, ret->get_parameters() );
1053    return ret;
1054  }
1055 
1056  default:
1057    return type->build();
1058  }
1059}
1060
1061Declaration::StorageClass
1062DeclarationNode::buildStorageClass() const
1063{
1064  static const Declaration::StorageClass scMap[] = { 
1065    Declaration::Static,
1066    Declaration::Auto,
1067    Declaration::Extern,
1068    Declaration::Register,
1069    Declaration::NoStorageClass, // inline
1070    Declaration::Fortran
1071  }; 
1072 
1073  Declaration::StorageClass ret = Declaration::NoStorageClass;
1074  for( std::list< StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) {
1075    assert( unsigned( *i ) < sizeof( scMap ) / sizeof( scMap[0] ) );
1076    if( *i == Inline ) continue;
1077    if( ret == Declaration::NoStorageClass ) {
1078      ret = scMap[ *i ];
1079    } else {
1080      throw SemanticError( "invalid combination of storage classes in declaration of ", this );
1081    }
1082  }
1083  return ret;
1084}
1085
1086bool 
1087DeclarationNode::buildInline() const
1088{
1089  std::list< StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), Inline );
1090  if( first == storageClasses.end() ) {
1091    return false;
1092  } else {
1093    std::list< StorageClass >::const_iterator next = std::find( ++first, storageClasses.end(), Inline );
1094    if( next == storageClasses.end() ) {
1095      return true;
1096    } else {
1097      throw SemanticError( "duplicate inline specification in declaration of ", this );
1098    }
1099  }
1100  // we should never get here
1101  return false;
1102}
Note: See TracBrowser for help on using the repository browser.