source: src/Parser/TypeData.cc @ 057608a

Last change on this file since 057608a was 057608a, checked in by Andrew Beach <ajbeach@…>, 4 months ago

Parser clean-up: Removed an unused field, added a comment, fixed a memory leak and reformated a function.

  • Property mode set to 100644
File size: 51.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// TypeData.cc --
8//
9// Author           : Rodolfo G. Esteves
10// Created On       : Sat May 16 15:12:51 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Feb 23 08:58:30 2024
13// Update Count     : 734
14//
15
16#include "TypeData.h"
17
18#include <cassert>                 // for assert
19#include <ostream>                 // for operator<<, ostream, basic_ostream
20
21#include "AST/Decl.hpp"            // for AggregateDecl, ObjectDecl, TypeDe...
22#include "AST/Attribute.hpp"       // for Attribute
23#include "AST/Init.hpp"            // for SingleInit, ListInit
24#include "AST/Print.hpp"           // for print
25#include "Common/SemanticError.h"  // for SemanticError
26#include "Common/utility.h"        // for splice, spliceBegin
27#include "Common/Iterate.hpp"      // for reverseIterate
28#include "Parser/ExpressionNode.h" // for ExpressionNode
29#include "Parser/StatementNode.h"  // for StatementNode
30
31class Attribute;
32
33using namespace std;
34
35// These must harmonize with the corresponding enumerations in the header.
36const char * TypeData::basicTypeNames[] = {
37        "void", "_Bool", "char", "int", "int128",
38        "float", "double", "long double", "float80", "float128",
39        "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x",
40        "NoBasicTypeNames"
41};
42const char * TypeData::complexTypeNames[] = {
43        "_Complex", "NoComplexTypeNames", "_Imaginary"
44}; // Imaginary unsupported => parse, but make invisible and print error message
45const char * TypeData::signednessNames[] = {
46        "signed", "unsigned", "NoSignednessNames"
47};
48const char * TypeData::lengthNames[] = {
49        "short", "long", "long long", "NoLengthNames"
50};
51const char * TypeData::builtinTypeNames[] = {
52        "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames"
53};
54
55TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
56        switch ( kind ) {
57        case Unknown:
58        case Pointer:
59        case Reference:
60        case EnumConstant:
61        case GlobalScope:
62        case Basic:
63                // No unique data to initialize.
64                break;
65        case Array:
66                array.dimension = nullptr;
67                array.isVarLen = false;
68                array.isStatic = false;
69                break;
70        case Function:
71                function.params = nullptr;
72                function.idList = nullptr;
73                function.oldDeclList = nullptr;
74                function.body = nullptr;
75                function.withExprs = nullptr;
76                break;
77        case Enum:
78                enumeration.name = nullptr;
79                enumeration.constants = nullptr;
80                enumeration.body = false;
81                enumeration.anon = false;
82                break;
83        case Aggregate:
84                aggregate.kind = ast::AggregateDecl::NoAggregate;
85                aggregate.name = nullptr;
86                aggregate.params = nullptr;
87                aggregate.actuals = nullptr;
88                aggregate.fields = nullptr;
89                aggregate.body = false;
90                aggregate.parent = nullptr;
91                aggregate.anon = false;
92                break;
93        case AggregateInst:
94                aggInst.aggregate = nullptr;
95                aggInst.params = nullptr;
96                aggInst.hoistType = false;
97                break;
98        case Symbolic:
99        case SymbolicInst:
100                symbolic.name = nullptr;
101                symbolic.params = nullptr;
102                symbolic.actuals = nullptr;
103                symbolic.assertions = nullptr;
104                break;
105        case Tuple:
106                tuple = nullptr;
107                break;
108        case Typeof:
109        case Basetypeof:
110                typeexpr = nullptr;
111                break;
112        case Vtable:
113        case Builtin:
114                // No unique data to initialize.
115                break;
116        case Qualified:
117                qualified.parent = nullptr;
118                qualified.child = nullptr;
119                break;
120        } // switch
121} // TypeData::TypeData
122
123
124TypeData::~TypeData() {
125        delete base;
126        delete forall;
127
128        switch ( kind ) {
129        case Unknown:
130        case Pointer:
131        case Reference:
132        case EnumConstant:
133        case GlobalScope:
134        case Basic:
135                // No unique data to deconstruct.
136                break;
137        case Array:
138                delete array.dimension;
139                break;
140        case Function:
141                delete function.params;
142                delete function.idList;
143                delete function.oldDeclList;
144                delete function.body;
145                delete function.withExprs;
146                break;
147        case Aggregate:
148                delete aggregate.name;
149                delete aggregate.params;
150                delete aggregate.actuals;
151                delete aggregate.fields;
152                break;
153        case AggregateInst:
154                delete aggInst.aggregate;
155                delete aggInst.params;
156                break;
157        case Enum:
158                delete enumeration.name;
159                delete enumeration.constants;
160                break;
161        case Symbolic:
162        case SymbolicInst:
163                delete symbolic.name;
164                delete symbolic.params;
165                delete symbolic.actuals;
166                delete symbolic.assertions;
167                break;
168        case Tuple:
169                delete tuple;
170                break;
171        case Typeof:
172        case Basetypeof:
173                delete typeexpr;
174                break;
175        case Vtable:
176        case Builtin:
177                // No unique data to deconstruct.
178                break;
179        case Qualified:
180                delete qualified.parent;
181                delete qualified.child;
182                break;
183        } // switch
184} // TypeData::~TypeData
185
186
187TypeData * TypeData::clone() const {
188        TypeData * newtype = new TypeData( kind );
189        newtype->qualifiers = qualifiers;
190        newtype->base = maybeCopy( base );
191        newtype->forall = maybeCopy( forall );
192
193        switch ( kind ) {
194        case Unknown:
195        case EnumConstant:
196        case Pointer:
197        case Reference:
198        case GlobalScope:
199                // nothing else to copy
200                break;
201        case Basic:
202                newtype->basictype = basictype;
203                newtype->complextype = complextype;
204                newtype->signedness = signedness;
205                newtype->length = length;
206                break;
207        case Array:
208                newtype->array.dimension = maybeCopy( array.dimension );
209                newtype->array.isVarLen = array.isVarLen;
210                newtype->array.isStatic = array.isStatic;
211                break;
212        case Function:
213                newtype->function.params = maybeCopy( function.params );
214                newtype->function.idList = maybeCopy( function.idList );
215                newtype->function.oldDeclList = maybeCopy( function.oldDeclList );
216                newtype->function.body = maybeCopy( function.body );
217                newtype->function.withExprs = maybeCopy( function.withExprs );
218                break;
219        case Aggregate:
220                newtype->aggregate.kind = aggregate.kind;
221                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
222                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
223                newtype->aggregate.params = maybeCopy( aggregate.params );
224                newtype->aggregate.actuals = maybeCopy( aggregate.actuals );
225                newtype->aggregate.fields = maybeCopy( aggregate.fields );
226                newtype->aggregate.attributes = aggregate.attributes;
227                newtype->aggregate.body = aggregate.body;
228                newtype->aggregate.anon = aggregate.anon;
229                break;
230        case AggregateInst:
231                newtype->aggInst.aggregate = maybeCopy( aggInst.aggregate );
232                newtype->aggInst.params = maybeCopy( aggInst.params );
233                newtype->aggInst.hoistType = aggInst.hoistType;
234                break;
235        case Enum:
236                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
237                newtype->enumeration.constants = maybeCopy( enumeration.constants );
238                newtype->enumeration.body = enumeration.body;
239                newtype->enumeration.anon = enumeration.anon;
240                break;
241        case Symbolic:
242        case SymbolicInst:
243                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
244                newtype->symbolic.params = maybeCopy( symbolic.params );
245                newtype->symbolic.actuals = maybeCopy( symbolic.actuals );
246                newtype->symbolic.assertions = maybeCopy( symbolic.assertions );
247                newtype->symbolic.isTypedef = symbolic.isTypedef;
248                break;
249        case Tuple:
250                newtype->tuple = maybeCopy( tuple );
251                break;
252        case Typeof:
253        case Basetypeof:
254                newtype->typeexpr = maybeCopy( typeexpr );
255                break;
256        case Vtable:
257                break;
258        case Builtin:
259                assert( builtintype == Zero || builtintype == One );
260                newtype->builtintype = builtintype;
261                break;
262        case Qualified:
263                newtype->qualified.parent = maybeCopy( qualified.parent );
264                newtype->qualified.child = maybeCopy( qualified.child );
265                break;
266        } // switch
267        return newtype;
268} // TypeData::clone
269
270
271void TypeData::print( ostream &os, int indent ) const {
272        ast::print( os, qualifiers );
273
274        if ( forall ) {
275                os << "forall " << endl;
276                forall->printList( os, indent + 4 );
277        } // if
278
279        switch ( kind ) {
280        case Basic:
281                if ( signedness != NoSignedness ) os << signednessNames[ signedness ] << " ";
282                if ( length != NoLength ) os << lengthNames[ length ] << " ";
283                if ( complextype != NoComplexType ) os << complexTypeNames[ complextype ] << " ";
284                if ( basictype != NoBasicType ) os << basicTypeNames[ basictype ] << " ";
285                break;
286        case Pointer:
287                os << "pointer ";
288                if ( base ) {
289                        os << "to ";
290                        base->print( os, indent );
291                } // if
292                break;
293        case Reference:
294                os << "reference ";
295                if ( base ) {
296                        os << "to ";
297                        base->print( os, indent );
298                } // if
299                break;
300        case Array:
301                if ( array.isStatic ) {
302                        os << "static ";
303                } // if
304                if ( array.dimension ) {
305                        os << "array of ";
306                        array.dimension->printOneLine( os, indent );
307                } else if ( array.isVarLen ) {
308                        os << "variable-length array of ";
309                } else {
310                        os << "open array of ";
311                } // if
312                if ( base ) {
313                        base->print( os, indent );
314                } // if
315                break;
316        case Function:
317                os << "function" << endl;
318                if ( function.params ) {
319                        os << string( indent + 2, ' ' ) << "with parameters " << endl;
320                        function.params->printList( os, indent + 4 );
321                } else {
322                        os << string( indent + 2, ' ' ) << "with no parameters" << endl;
323                } // if
324                if ( function.idList ) {
325                        os << string( indent + 2, ' ' ) << "with old-style identifier list " << endl;
326                        function.idList->printList( os, indent + 4 );
327                } // if
328                if ( function.oldDeclList ) {
329                        os << string( indent + 2, ' ' ) << "with old-style declaration list " << endl;
330                        function.oldDeclList->printList( os, indent + 4 );
331                } // if
332                os << string( indent + 2, ' ' ) << "returning ";
333                if ( base ) {
334                        base->print( os, indent + 4 );
335                } else {
336                        os << "nothing ";
337                } // if
338                os << endl;
339                if ( function.body ) {
340                        os << string( indent + 2, ' ' ) << "with body " << endl;
341                        function.body->printList( os, indent + 2 );
342                } // if
343                break;
344        case Aggregate:
345                os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
346                if ( aggregate.params ) {
347                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
348                        aggregate.params->printList( os, indent + 4 );
349                } // if
350                if ( aggregate.actuals ) {
351                        os << string( indent + 2, ' ' ) << "instantiated with actual parameters" << endl;
352                        aggregate.actuals->printList( os, indent + 4 );
353                } // if
354                if ( aggregate.fields ) {
355                        os << string( indent + 2, ' ' ) << "with members" << endl;
356                        aggregate.fields->printList( os, indent + 4 );
357                } // if
358                if ( aggregate.body ) {
359                        os << string( indent + 2, ' ' ) << "with body" << endl;
360                } // if
361                if ( ! aggregate.attributes.empty() ) {
362                        os << string( indent + 2, ' ' ) << "with attributes" << endl;
363                        for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( aggregate.attributes ) ) {
364                                os << string( indent + 4, ' ' );
365                                ast::print( os, attr, indent + 2 );
366                        } // for
367                } // if
368                break;
369        case AggregateInst:
370                if ( aggInst.aggregate ) {
371                        os << "instance of " ;
372                        aggInst.aggregate->print( os, indent );
373                } else {
374                        os << "instance of an unspecified aggregate ";
375                } // if
376                if ( aggInst.params ) {
377                        os << string( indent + 2, ' ' ) << "with parameters" << endl;
378                        aggInst.params->printList( os, indent + 2 );
379                } // if
380                break;
381        case Enum:
382                os << "enumeration " << *enumeration.name << endl;;
383                if ( enumeration.constants ) {
384                        os << "with constants" << endl;
385                        enumeration.constants->printList( os, indent + 2 );
386                } // if
387                if ( enumeration.body ) {
388                        os << string( indent + 2, ' ' ) << "with body" << endl;
389                } // if
390                if ( base ) {
391                        os << "for ";
392                        base->print( os, indent + 2 );
393                } // if
394                break;
395        case EnumConstant:
396                os << "enumeration constant ";
397                break;
398        case Symbolic:
399                if ( symbolic.isTypedef ) {
400                        os << "typedef definition ";
401                } else {
402                        os << "type definition ";
403                } // if
404                if ( symbolic.params ) {
405                        os << endl << string( indent + 2, ' ' ) << "with parameters" << endl;
406                        symbolic.params->printList( os, indent + 2 );
407                } // if
408                if ( symbolic.assertions ) {
409                        os << endl << string( indent + 2, ' ' ) << "with assertions" << endl;
410                        symbolic.assertions->printList( os, indent + 4 );
411                        os << string( indent + 2, ' ' );
412                } // if
413                if ( base ) {
414                        os << "for ";
415                        base->print( os, indent + 2 );
416                } // if
417                break;
418        case SymbolicInst:
419                os << *symbolic.name;
420                if ( symbolic.actuals ) {
421                        os << "(";
422                        symbolic.actuals->printList( os, indent + 2 );
423                        os << ")";
424                } // if
425                break;
426        case Tuple:
427                os << "tuple ";
428                if ( tuple ) {
429                        os << "with members" << endl;
430                        tuple->printList( os, indent + 2 );
431                } // if
432                break;
433        case Basetypeof:
434                os << "base-";
435                #if defined(__GNUC__) && __GNUC__ >= 7
436                        __attribute__((fallthrough));
437                #endif
438                // FALL THROUGH
439        case Typeof:
440                os << "type-of expression ";
441                if ( typeexpr ) {
442                        typeexpr->print( os, indent + 2 );
443                } // if
444                break;
445        case Vtable:
446                os << "vtable";
447                break;
448        case Builtin:
449                os << builtinTypeNames[builtintype];
450                break;
451        case GlobalScope:
452                break;
453        case Qualified:
454                qualified.parent->print( os );
455                os << ".";
456                qualified.child->print( os );
457                break;
458        case Unknown:
459                os << "entity of unknown type ";
460                break;
461        default:
462                os << "internal error: TypeData::print " << kind << endl;
463                assert( false );
464        } // switch
465} // TypeData::print
466
467const std::string * TypeData::leafName() const {
468        switch ( kind ) {
469        case Unknown:
470        case Pointer:
471        case Reference:
472        case EnumConstant:
473        case GlobalScope:
474        case Array:
475        case Basic:
476        case Function:
477        case AggregateInst:
478        case Tuple:
479        case Typeof:
480        case Basetypeof:
481        case Builtin:
482        case Vtable:
483                assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
484                break;
485        case Aggregate:
486                return aggregate.name;
487        case Enum:
488                return enumeration.name;
489        case Symbolic:
490        case SymbolicInst:
491                return symbolic.name;
492        case Qualified:
493                return qualified.child->leafName();
494        } // switch
495        assert(false);
496}
497
498TypeData * TypeData::getLastBase() {
499        TypeData * cur = this;
500        while ( cur->base ) cur = cur->base;
501        return cur;
502}
503
504void TypeData::setLastBase( TypeData * newBase ) {
505        getLastBase()->base = newBase;
506}
507
508
509TypeData * build_type_qualifier( ast::CV::Qualifiers tq ) {
510        TypeData * type = new TypeData;
511        type->qualifiers = tq;
512        return type;
513}
514
515TypeData * build_basic_type( TypeData::BasicType basic ) {
516        TypeData * type = new TypeData( TypeData::Basic );
517        type->basictype = basic;
518        return type;
519}
520
521TypeData * build_complex_type( TypeData::ComplexType complex ) {
522        TypeData * type = new TypeData( TypeData::Basic );
523        type->complextype = complex;
524        return type;
525}
526
527TypeData * build_signedness( TypeData::Signedness signedness ) {
528        TypeData * type = new TypeData( TypeData::Basic );
529        type->signedness = signedness;
530        return type;
531}
532
533TypeData * build_builtin_type( TypeData::BuiltinType bit ) {
534        TypeData * type = new TypeData( TypeData::Builtin );
535        type->builtintype = bit;
536        return type;
537}
538
539TypeData * build_length( TypeData::Length length ) {
540        TypeData * type = new TypeData( TypeData::Basic );
541        type->length = length;
542        return type;
543}
544
545TypeData * build_forall( DeclarationNode * forall ) {
546        TypeData * type = new TypeData( TypeData::Unknown );
547        type->forall = forall;
548        return type;
549}
550
551TypeData * build_global_scope() {
552        return new TypeData( TypeData::GlobalScope );
553}
554
555TypeData * build_qualified_type( TypeData * parent, TypeData * child ) {
556        TypeData * type = new TypeData( TypeData::Qualified );
557        type->qualified.parent = parent;
558        type->qualified.child = child;
559        return type;
560}
561
562TypeData * build_typedef( const std::string * name ) {
563        TypeData * type = new TypeData( TypeData::SymbolicInst );
564        type->symbolic.name = name;
565        type->symbolic.isTypedef = true;
566        type->symbolic.actuals = nullptr;
567        return type;
568}
569
570TypeData * build_type_gen( const std::string * name, ExpressionNode * params ) {
571        TypeData * type = new TypeData( TypeData::SymbolicInst );
572        type->symbolic.name = name;
573        type->symbolic.isTypedef = false;
574        type->symbolic.actuals = params;
575        return type;
576}
577
578TypeData * build_vtable_type( TypeData * base ) {
579        TypeData * type = new TypeData( TypeData::Vtable );
580        type->base = base;
581        return type;
582}
583
584// Takes ownership of src.
585static void addQualifiersToType( TypeData * dst, TypeData * src ) {
586        if ( dst->base ) {
587                addQualifiersToType( dst->base, src );
588        } else if ( dst->kind == TypeData::Function ) {
589                dst->base = src;
590                src = nullptr;
591    } else {
592                dst->qualifiers |= src->qualifiers;
593                delete src;
594        } // if
595}
596
597// Takes ownership of all arguments, gives ownership of return value.
598TypeData * addQualifiers( TypeData * ltype, TypeData * rtype ) {
599        if ( ltype->forall ) {
600                if ( rtype->forall ) {
601                        rtype->forall->set_last( ltype->forall );
602                } else if ( TypeData::Aggregate != rtype->kind ) {
603                        rtype->forall = ltype->forall;
604                } else if ( rtype->aggregate.params ) {
605                        rtype->aggregate.params->set_last( ltype->forall );
606                } else {
607                        rtype->aggregate.params = ltype->forall;
608                }
609                ltype->forall = nullptr;
610        }
611
612        addQualifiersToType( rtype, ltype );
613        return rtype;
614}
615
616// Helper for addType and cloneBaseType.
617static void addTypeToType( TypeData *& dst, TypeData *& src ) {
618        if ( src->forall && dst->kind == TypeData::Function ) {
619                if ( dst->forall ) {
620                        dst->forall->set_last( src->forall );
621                } else {
622                        dst->forall = src->forall;
623                } // if
624                src->forall = nullptr;
625        } // if
626        if ( dst->base ) {
627                addTypeToType( dst->base, src );
628                return;
629        }
630        switch ( dst->kind ) {
631        case TypeData::Unknown:
632                src->qualifiers |= dst->qualifiers;
633                // LEAKS dst?
634                dst = src;
635                src = nullptr;
636                break;
637        case TypeData::Basic:
638                dst->qualifiers |= src->qualifiers;
639                if ( src->kind != TypeData::Unknown ) {
640                        assert( src->kind == TypeData::Basic );
641
642                        if ( dst->basictype == TypeData::NoBasicType ) {
643                                dst->basictype = src->basictype;
644                        } else if ( src->basictype != TypeData::NoBasicType ) {
645                                SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
646                                        TypeData::basicTypeNames[ dst->basictype ],
647                                        TypeData::basicTypeNames[ src->basictype ] );
648                        }
649                        if ( dst->complextype == TypeData::NoComplexType ) {
650                                dst->complextype = src->complextype;
651                        } else if ( src->complextype != TypeData::NoComplexType ) {
652                                SemanticError( yylloc, "multiple declaration types \"%s\" and \"%s\".",
653                                        TypeData::complexTypeNames[ src->complextype ],
654                                        TypeData::complexTypeNames[ src->complextype ] );
655                        }
656                        if ( dst->signedness == TypeData::NoSignedness ) {
657                                dst->signedness = src->signedness;
658                        } else if ( src->signedness != TypeData::NoSignedness ) {
659                                SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
660                                        TypeData::signednessNames[ dst->signedness ],
661                                        TypeData::signednessNames[ src->signedness ] );
662                        }
663                        if ( dst->length == TypeData::NoLength ) {
664                                dst->length = src->length;
665                        } else if ( dst->length == TypeData::Long && src->length == TypeData::Long ) {
666                                dst->length = TypeData::LongLong;
667                        } else if ( src->length != TypeData::NoLength ) {
668                                SemanticError( yylloc, "conflicting type specifier \"%s\" and \"%s\".",
669                                        TypeData::lengthNames[ dst->length ],
670                                        TypeData::lengthNames[ src->length ] );
671                        }
672                } // if
673                break;
674        default:
675                switch ( src->kind ) {
676                case TypeData::Aggregate:
677                case TypeData::Enum:
678                        dst->base = new TypeData( TypeData::AggregateInst );
679                        dst->base->aggInst.aggregate = src;
680                        if ( src->kind == TypeData::Aggregate ) {
681                                dst->base->aggInst.params = maybeCopy( src->aggregate.actuals );
682                        } // if
683                        dst->base->qualifiers |= src->qualifiers;
684                        src = nullptr;
685                        break;
686                default:
687                        if ( dst->forall ) {
688                                dst->forall->set_last( src->forall );
689                        } else {
690                                dst->forall = src->forall;
691                        } // if
692                        src->forall = nullptr;
693                        dst->base = src;
694                        src = nullptr;
695                } // switch
696        } // switch
697}
698
699// Takes ownership of all arguments, gives ownership of return value.
700TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & attributes ) {
701        if ( rtype ) {
702                addTypeToType( rtype, ltype );
703                return rtype;
704        } else {
705                if ( ltype->kind == TypeData::Aggregate || ltype->kind == TypeData::Enum ) {
706                        // Hide type information aggregate instances.
707                        rtype = new TypeData( TypeData::AggregateInst );
708                        rtype->aggInst.aggregate = ltype;
709                        rtype->aggInst.aggregate->aggregate.attributes.swap( attributes ); // change ownership
710                        if ( ltype->kind == TypeData::Aggregate ) {
711                                rtype->aggInst.hoistType = ltype->aggregate.body;
712                                rtype->aggInst.params = maybeCopy( ltype->aggregate.actuals );
713                        } else {
714                                rtype->aggInst.hoistType = ltype->enumeration.body;
715                        } // if
716                        rtype->qualifiers |= ltype->qualifiers;
717                } else {
718                        rtype = ltype;
719                } // if
720                return rtype;
721        } // if
722}
723
724TypeData * addType( TypeData * ltype, TypeData * rtype ) {
725        std::vector<ast::ptr<ast::Attribute>> attributes;
726        return addType( ltype, rtype, attributes );
727}
728
729// Takes ownership of both arguments, gives ownership of return value.
730TypeData * cloneBaseType( TypeData * type, TypeData * other ) {
731        TypeData * newType = type->getLastBase()->clone();
732        if ( newType->kind == TypeData::AggregateInst ) {
733                // don't duplicate members
734                if ( newType->aggInst.aggregate->kind == TypeData::Enum ) {
735                        delete newType->aggInst.aggregate->enumeration.constants;
736                        newType->aggInst.aggregate->enumeration.constants = nullptr;
737                        newType->aggInst.aggregate->enumeration.body = false;
738                } else {
739                        assert( newType->aggInst.aggregate->kind == TypeData::Aggregate );
740                        delete newType->aggInst.aggregate->aggregate.fields;
741                        newType->aggInst.aggregate->aggregate.fields = nullptr;
742                        newType->aggInst.aggregate->aggregate.body = false;
743                } // if
744                // don't hoist twice
745                newType->aggInst.hoistType = false;
746        } // if
747        newType->forall = maybeCopy( type->forall );
748
749        if ( other ) {
750                addTypeToType( other, newType );
751                delete newType;
752                return other;
753        } // if
754        return newType;
755}
756
757TypeData * makeNewBase( TypeData * type ) {
758        switch ( type->kind ) {
759        case TypeData::Aggregate:
760        case TypeData::Enum: {
761                TypeData * out = new TypeData( TypeData::AggregateInst );
762                out->aggInst.aggregate = type;
763                if ( TypeData::Aggregate == type->kind ) {
764                        out->aggInst.params = maybeCopy( type->aggregate.actuals );
765                }
766                out->qualifiers |= type->qualifiers;
767                return out;
768        }
769        default:
770                return type;
771        } // switch
772}
773
774
775void buildForall(
776                const DeclarationNode * firstNode,
777                std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
778        {
779                std::vector<ast::ptr<ast::Type>> tmpList;
780                buildTypeList( firstNode, tmpList );
781                for ( auto tmp : tmpList ) {
782                        outputList.emplace_back(
783                                strict_dynamic_cast<const ast::TypeInstType *>(
784                                        tmp.release() ) );
785                }
786        }
787        auto n = firstNode;
788        for ( auto i = outputList.begin() ;
789                        i != outputList.end() ;
790                        ++i, n = n->next ) {
791                // Only the object type class adds additional assertions.
792                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
793                        continue;
794                }
795
796                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
797                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
798                auto mutTypeDecl = ast::mutate( td );
799                const CodeLocation & location = mutTypeDecl->location;
800                *i = mutTypeDecl;
801
802                // add assertion parameters to `type' tyvars in reverse order
803                // add assignment operator:  T * ?=?(T *, T)
804                newAssertions.push_back( new ast::FunctionDecl(
805                        location,
806                        "?=?",
807                        {}, // forall
808                        {}, // assertions
809                        {
810                                new ast::ObjectDecl(
811                                        location,
812                                        "",
813                                        new ast::ReferenceType( i->get() ),
814                                        (ast::Init *)nullptr,
815                                        ast::Storage::Classes(),
816                                        ast::Linkage::Cforall,
817                                        (ast::Expr *)nullptr
818                                ),
819                                new ast::ObjectDecl(
820                                        location,
821                                        "",
822                                        i->get(),
823                                        (ast::Init *)nullptr,
824                                        ast::Storage::Classes(),
825                                        ast::Linkage::Cforall,
826                                        (ast::Expr *)nullptr
827                                ),
828                        }, // params
829                        {
830                                new ast::ObjectDecl(
831                                        location,
832                                        "",
833                                        i->get(),
834                                        (ast::Init *)nullptr,
835                                        ast::Storage::Classes(),
836                                        ast::Linkage::Cforall,
837                                        (ast::Expr *)nullptr
838                                ),
839                        }, // returns
840                        (ast::CompoundStmt *)nullptr,
841                        ast::Storage::Classes(),
842                        ast::Linkage::Cforall
843                ) );
844
845                // add default ctor:  void ?{}(T *)
846                newAssertions.push_back( new ast::FunctionDecl(
847                        location,
848                        "?{}",
849                        {}, // forall
850                        {}, // assertions
851                        {
852                                new ast::ObjectDecl(
853                                        location,
854                                        "",
855                                        new ast::ReferenceType( i->get() ),
856                                        (ast::Init *)nullptr,
857                                        ast::Storage::Classes(),
858                                        ast::Linkage::Cforall,
859                                        (ast::Expr *)nullptr
860                                ),
861                        }, // params
862                        {}, // returns
863                        (ast::CompoundStmt *)nullptr,
864                        ast::Storage::Classes(),
865                        ast::Linkage::Cforall
866                ) );
867
868                // add copy ctor:  void ?{}(T *, T)
869                newAssertions.push_back( new ast::FunctionDecl(
870                        location,
871                        "?{}",
872                        {}, // forall
873                        {}, // assertions
874                        {
875                                new ast::ObjectDecl(
876                                        location,
877                                        "",
878                                        new ast::ReferenceType( i->get() ),
879                                        (ast::Init *)nullptr,
880                                        ast::Storage::Classes(),
881                                        ast::Linkage::Cforall,
882                                        (ast::Expr *)nullptr
883                                ),
884                                new ast::ObjectDecl(
885                                        location,
886                                        "",
887                                        i->get(),
888                                        (ast::Init *)nullptr,
889                                        ast::Storage::Classes(),
890                                        ast::Linkage::Cforall,
891                                        (ast::Expr *)nullptr
892                                ),
893                        }, // params
894                        {}, // returns
895                        (ast::CompoundStmt *)nullptr,
896                        ast::Storage::Classes(),
897                        ast::Linkage::Cforall
898                ) );
899
900                // add dtor:  void ^?{}(T *)
901                newAssertions.push_back( new ast::FunctionDecl(
902                        location,
903                        "^?{}",
904                        {}, // forall
905                        {}, // assertions
906                        {
907                                new ast::ObjectDecl(
908                                        location,
909                                        "",
910                                        new ast::ReferenceType( i->get() ),
911                                        (ast::Init *)nullptr,
912                                        ast::Storage::Classes(),
913                                        ast::Linkage::Cforall,
914                                        (ast::Expr *)nullptr
915                                ),
916                        }, // params
917                        {}, // returns
918                        (ast::CompoundStmt *)nullptr,
919                        ast::Storage::Classes(),
920                        ast::Linkage::Cforall
921                ) );
922
923                spliceBegin( mutTypeDecl->assertions, newAssertions );
924        } // for
925}
926
927
928void buildForall(
929                const DeclarationNode * firstNode,
930                std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
931        buildList( firstNode, outputForall );
932        auto n = firstNode;
933        for ( auto i = outputForall.begin() ;
934                        i != outputForall.end() ;
935                        ++i, n = n->next ) {
936                // Only the object type class adds additional assertions.
937                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
938                        continue;
939                }
940
941                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
942                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
943                auto mutTypeDecl = ast::mutate( td );
944                const CodeLocation & location = mutTypeDecl->location;
945                *i = mutTypeDecl;
946
947                // add assertion parameters to `type' tyvars in reverse order
948                // add assignment operator:  T * ?=?(T *, T)
949                newAssertions.push_back( new ast::FunctionDecl(
950                        location,
951                        "?=?",
952                        {}, // forall
953                        {}, // assertions
954                        {
955                                new ast::ObjectDecl(
956                                        location,
957                                        "",
958                                        new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
959                                        (ast::Init *)nullptr,
960                                        ast::Storage::Classes(),
961                                        ast::Linkage::Cforall,
962                                        (ast::Expr *)nullptr
963                                ),
964                                new ast::ObjectDecl(
965                                        location,
966                                        "",
967                                        new ast::TypeInstType( td->name, *i ),
968                                        (ast::Init *)nullptr,
969                                        ast::Storage::Classes(),
970                                        ast::Linkage::Cforall,
971                                        (ast::Expr *)nullptr
972                                ),
973                        }, // params
974                        {
975                                new ast::ObjectDecl(
976                                        location,
977                                        "",
978                                        new ast::TypeInstType( td->name, *i ),
979                                        (ast::Init *)nullptr,
980                                        ast::Storage::Classes(),
981                                        ast::Linkage::Cforall,
982                                        (ast::Expr *)nullptr
983                                ),
984                        }, // returns
985                        (ast::CompoundStmt *)nullptr,
986                        ast::Storage::Classes(),
987                        ast::Linkage::Cforall
988                ) );
989
990                // add default ctor:  void ?{}(T *)
991                newAssertions.push_back( new ast::FunctionDecl(
992                        location,
993                        "?{}",
994                        {}, // forall
995                        {}, // assertions
996                        {
997                                new ast::ObjectDecl(
998                                        location,
999                                        "",
1000                                        new ast::ReferenceType(
1001                                                new ast::TypeInstType( td->name, i->get() ) ),
1002                                        (ast::Init *)nullptr,
1003                                        ast::Storage::Classes(),
1004                                        ast::Linkage::Cforall,
1005                                        (ast::Expr *)nullptr
1006                                ),
1007                        }, // params
1008                        {}, // returns
1009                        (ast::CompoundStmt *)nullptr,
1010                        ast::Storage::Classes(),
1011                        ast::Linkage::Cforall
1012                ) );
1013
1014                // add copy ctor:  void ?{}(T *, T)
1015                newAssertions.push_back( new ast::FunctionDecl(
1016                        location,
1017                        "?{}",
1018                        {}, // forall
1019                        {}, // assertions
1020                        {
1021                                new ast::ObjectDecl(
1022                                        location,
1023                                        "",
1024                                        new ast::ReferenceType(
1025                                                new ast::TypeInstType( td->name, *i ) ),
1026                                        (ast::Init *)nullptr,
1027                                        ast::Storage::Classes(),
1028                                        ast::Linkage::Cforall,
1029                                        (ast::Expr *)nullptr
1030                                ),
1031                                new ast::ObjectDecl(
1032                                        location,
1033                                        "",
1034                                        new ast::TypeInstType( td->name, *i ),
1035                                        (ast::Init *)nullptr,
1036                                        ast::Storage::Classes(),
1037                                        ast::Linkage::Cforall,
1038                                        (ast::Expr *)nullptr
1039                                ),
1040                        }, // params
1041                        {}, // returns
1042                        (ast::CompoundStmt *)nullptr,
1043                        ast::Storage::Classes(),
1044                        ast::Linkage::Cforall
1045                ) );
1046
1047                // add dtor:  void ^?{}(T *)
1048                newAssertions.push_back( new ast::FunctionDecl(
1049                        location,
1050                        "^?{}",
1051                        {}, // forall
1052                        {}, // assertions
1053                        {
1054                                new ast::ObjectDecl(
1055                                        location,
1056                                        "",
1057                                        new ast::ReferenceType(
1058                                                new ast::TypeInstType( i->get() )
1059                                        ),
1060                                        (ast::Init *)nullptr,
1061                                        ast::Storage::Classes(),
1062                                        ast::Linkage::Cforall,
1063                                        (ast::Expr *)nullptr
1064                                ),
1065                        }, // params
1066                        {}, // returns
1067                        (ast::CompoundStmt *)nullptr,
1068                        ast::Storage::Classes(),
1069                        ast::Linkage::Cforall
1070                ) );
1071
1072                spliceBegin( mutTypeDecl->assertions, newAssertions );
1073        } // for
1074} // buildForall
1075
1076
1077ast::Type * typebuild( const TypeData * td ) {
1078        assert( td );
1079        switch ( td->kind ) {
1080        case TypeData::Unknown:
1081                // fill in implicit int
1082                return new ast::BasicType(
1083                        ast::BasicType::SignedInt,
1084                        buildQualifiers( td )
1085                );
1086        case TypeData::Basic:
1087                return buildBasicType( td );
1088        case TypeData::Pointer:
1089                return buildPointer( td );
1090        case TypeData::Array:
1091                return buildArray( td );
1092        case TypeData::Reference:
1093                return buildReference( td );
1094        case TypeData::Function:
1095                return buildFunctionType( td );
1096        case TypeData::AggregateInst:
1097                return buildAggInst( td );
1098        case TypeData::EnumConstant:
1099                return new ast::EnumInstType( "", buildQualifiers( td ) );
1100        case TypeData::SymbolicInst:
1101                return buildSymbolicInst( td );
1102        case TypeData::Tuple:
1103                return buildTuple( td );
1104        case TypeData::Typeof:
1105        case TypeData::Basetypeof:
1106                return buildTypeof( td );
1107        case TypeData::Vtable:
1108                return buildVtable( td );
1109        case TypeData::Builtin:
1110                switch ( td->builtintype ) {
1111                case TypeData::Zero:
1112                        return new ast::ZeroType();
1113                case TypeData::One:
1114                        return new ast::OneType();
1115                default:
1116                        return new ast::VarArgsType( buildQualifiers( td ) );
1117                } // switch
1118        case TypeData::GlobalScope:
1119                return new ast::GlobalScopeType();
1120        case TypeData::Qualified:
1121                return new ast::QualifiedType(
1122                        typebuild( td->qualified.parent ),
1123                        typebuild( td->qualified.child ),
1124                        buildQualifiers( td )
1125                );
1126        case TypeData::Symbolic:
1127        case TypeData::Enum:
1128        case TypeData::Aggregate:
1129                assert( false );
1130        } // switch
1131
1132        return nullptr;
1133} // typebuild
1134
1135
1136TypeData * typeextractAggregate( const TypeData * td, bool toplevel ) {
1137        TypeData * ret = nullptr;
1138
1139        switch ( td->kind ) {
1140        case TypeData::Aggregate:
1141                if ( ! toplevel && td->aggregate.body ) {
1142                        ret = td->clone();
1143                } // if
1144                break;
1145        case TypeData::Enum:
1146                if ( ! toplevel && td->enumeration.body ) {
1147                        ret = td->clone();
1148                } // if
1149                break;
1150        case TypeData::AggregateInst:
1151                if ( td->aggInst.aggregate ) {
1152                        ret = typeextractAggregate( td->aggInst.aggregate, false );
1153                } // if
1154                break;
1155        default:
1156                if ( td->base ) {
1157                        ret = typeextractAggregate( td->base, false );
1158                } // if
1159        } // switch
1160        return ret;
1161} // typeextractAggregate
1162
1163
1164ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
1165        return td->qualifiers;
1166} // buildQualifiers
1167
1168
1169static string genTSError( string msg, TypeData::BasicType basictype ) {
1170        SemanticError( yylloc, "invalid type specifier \"%s\" for type \"%s\".", msg.c_str(), TypeData::basicTypeNames[basictype] );
1171} // genTSError
1172
1173ast::Type * buildBasicType( const TypeData * td ) {
1174        ast::BasicType::Kind ret;
1175
1176        switch ( td->basictype ) {
1177        case TypeData::Void:
1178                if ( td->signedness != TypeData::NoSignedness ) {
1179                        genTSError( TypeData::signednessNames[ td->signedness ], td->basictype );
1180                } // if
1181                if ( td->length != TypeData::NoLength ) {
1182                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1183                } // if
1184                return new ast::VoidType( buildQualifiers( td ) );
1185                break;
1186
1187        case TypeData::Bool:
1188                if ( td->signedness != TypeData::NoSignedness ) {
1189                        genTSError( TypeData::signednessNames[ td->signedness ], td->basictype );
1190                } // if
1191                if ( td->length != TypeData::NoLength ) {
1192                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1193                } // if
1194
1195                ret = ast::BasicType::Bool;
1196                break;
1197
1198        case TypeData::Char:
1199                // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the
1200                // character types. The implementation shall define char to have the same range, representation, and behavior as
1201                // either signed char or unsigned char.
1202                static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
1203
1204                if ( td->length != TypeData::NoLength ) {
1205                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1206                } // if
1207
1208                ret = chartype[ td->signedness ];
1209                break;
1210
1211        case TypeData::Int:
1212                static ast::BasicType::Kind inttype[2][4] = {
1213                        { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
1214                        { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
1215                };
1216
1217        Integral: ;
1218                if ( td->signedness == TypeData::NoSignedness ) {
1219                        const_cast<TypeData *>(td)->signedness = TypeData::Signed;
1220                } // if
1221                ret = inttype[ td->signedness ][ td->length ];
1222                break;
1223
1224        case TypeData::Int128:
1225                ret = td->signedness == TypeData::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
1226                if ( td->length != TypeData::NoLength ) {
1227                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1228                } // if
1229                break;
1230
1231        case TypeData::Float:
1232        case TypeData::Double:
1233        case TypeData::LongDouble:                                      // not set until below
1234        case TypeData::uuFloat80:
1235        case TypeData::uuFloat128:
1236        case TypeData::uFloat16:
1237        case TypeData::uFloat32:
1238        case TypeData::uFloat32x:
1239        case TypeData::uFloat64:
1240        case TypeData::uFloat64x:
1241        case TypeData::uFloat128:
1242        case TypeData::uFloat128x:
1243                static ast::BasicType::Kind floattype[2][12] = {
1244                        { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, },
1245                        { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, },
1246                };
1247
1248        FloatingPoint: ;
1249                if ( td->signedness != TypeData::NoSignedness ) {
1250                        genTSError( TypeData::signednessNames[ td->signedness ], td->basictype );
1251                } // if
1252                if ( td->length == TypeData::Short || td->length == TypeData::LongLong ) {
1253                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1254                } // if
1255                if ( td->basictype != TypeData::Double && td->length == TypeData::Long ) {
1256                        genTSError( TypeData::lengthNames[ td->length ], td->basictype );
1257                } // if
1258                if ( td->complextype == TypeData::Imaginary ) {
1259                        genTSError( TypeData::complexTypeNames[ td->complextype ], td->basictype );
1260                } // if
1261                if ( (td->basictype == TypeData::uuFloat80 || td->basictype == TypeData::uuFloat128) && td->complextype == TypeData::Complex ) { // gcc unsupported
1262                        genTSError( TypeData::complexTypeNames[ td->complextype ], td->basictype );
1263                } // if
1264                if ( td->length == TypeData::Long ) {
1265                        const_cast<TypeData *>(td)->basictype = TypeData::LongDouble;
1266                } // if
1267
1268                ret = floattype[ td->complextype ][ td->basictype - TypeData::Float ];
1269                //printf( "XXXX %d %d %d %d\n", td->complextype, td->basictype, TypeData::Float, ret );
1270                break;
1271
1272        case TypeData::NoBasicType:
1273                // No basic type in declaration => default double for Complex/Imaginary and int type for integral types
1274                if ( td->complextype == TypeData::Complex || td->complextype == TypeData::Imaginary ) {
1275                        const_cast<TypeData *>(td)->basictype = TypeData::Double;
1276                        goto FloatingPoint;
1277                } // if
1278
1279                const_cast<TypeData *>(td)->basictype = TypeData::Int;
1280                goto Integral;
1281        default:
1282                assertf( false, "unknown basic type" );
1283                return nullptr;
1284        } // switch
1285
1286        ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
1287        return bt;
1288} // buildBasicType
1289
1290
1291static ast::Type * buildDefaultType( const TypeData * td ) {
1292        return ( td ) ? typebuild( td ) : new ast::BasicType( ast::BasicType::SignedInt );
1293} // buildDefaultType
1294
1295
1296ast::PointerType * buildPointer( const TypeData * td ) {
1297        return new ast::PointerType(
1298                buildDefaultType( td->base ),
1299                buildQualifiers( td )
1300        );
1301} // buildPointer
1302
1303
1304ast::ArrayType * buildArray( const TypeData * td ) {
1305        return new ast::ArrayType(
1306                buildDefaultType( td->base ),
1307                maybeBuild( td->array.dimension ),
1308                td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
1309                td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
1310                buildQualifiers( td )
1311        );
1312} // buildArray
1313
1314
1315ast::ReferenceType * buildReference( const TypeData * td ) {
1316        return new ast::ReferenceType(
1317                buildDefaultType( td->base ),
1318                buildQualifiers( td )
1319        );
1320} // buildReference
1321
1322
1323ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
1324        assert( td->kind == TypeData::Aggregate );
1325        ast::AggregateDecl * at;
1326        switch ( td->aggregate.kind ) {
1327        case ast::AggregateDecl::Struct:
1328        case ast::AggregateDecl::Coroutine:
1329        case ast::AggregateDecl::Exception:
1330        case ast::AggregateDecl::Generator:
1331        case ast::AggregateDecl::Monitor:
1332        case ast::AggregateDecl::Thread:
1333                at = new ast::StructDecl( td->location,
1334                        *td->aggregate.name,
1335                        td->aggregate.kind,
1336                        std::move( attributes ),
1337                        linkage
1338                );
1339                buildForall( td->aggregate.params, at->params );
1340                break;
1341        case ast::AggregateDecl::Union:
1342                at = new ast::UnionDecl( td->location,
1343                        *td->aggregate.name,
1344                        std::move( attributes ),
1345                        linkage
1346                );
1347                buildForall( td->aggregate.params, at->params );
1348                break;
1349        case ast::AggregateDecl::Trait:
1350                at = new ast::TraitDecl( td->location,
1351                        *td->aggregate.name,
1352                        std::move( attributes ),
1353                        linkage
1354                );
1355                buildList( td->aggregate.params, at->params );
1356                break;
1357        default:
1358                assert( false );
1359        } // switch
1360
1361        buildList( td->aggregate.fields, at->members );
1362        at->set_body( td->aggregate.body );
1363
1364        return at;
1365} // buildAggregate
1366
1367
1368ast::BaseInstType * buildComAggInst(
1369                const TypeData * td,
1370                std::vector<ast::ptr<ast::Attribute>> && attributes,
1371                ast::Linkage::Spec linkage ) {
1372        switch ( td->kind ) {
1373        case TypeData::Enum:
1374                if ( td->enumeration.body ) {
1375                        ast::EnumDecl * typedecl =
1376                                buildEnum( td, std::move( attributes ), linkage );
1377                        return new ast::EnumInstType(
1378                                typedecl,
1379                                buildQualifiers( td )
1380                        );
1381                } else {
1382                        return new ast::EnumInstType(
1383                                *td->enumeration.name,
1384                                buildQualifiers( td )
1385                        );
1386                } // if
1387                break;
1388        case TypeData::Aggregate:
1389                if ( td->aggregate.body ) {
1390                        ast::AggregateDecl * typedecl =
1391                                buildAggregate( td, std::move( attributes ), linkage );
1392                        switch ( td->aggregate.kind ) {
1393                        case ast::AggregateDecl::Struct:
1394                        case ast::AggregateDecl::Coroutine:
1395                        case ast::AggregateDecl::Monitor:
1396                        case ast::AggregateDecl::Thread:
1397                                return new ast::StructInstType(
1398                                        strict_dynamic_cast<ast::StructDecl *>( typedecl ),
1399                                        buildQualifiers( td )
1400                                );
1401                        case ast::AggregateDecl::Union:
1402                                return new ast::UnionInstType(
1403                                        strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
1404                                        buildQualifiers( td )
1405                                );
1406                        case ast::AggregateDecl::Trait:
1407                                assert( false );
1408                                break;
1409                        default:
1410                                assert( false );
1411                        } // switch
1412                } else {
1413                        switch ( td->aggregate.kind ) {
1414                        case ast::AggregateDecl::Struct:
1415                        case ast::AggregateDecl::Coroutine:
1416                        case ast::AggregateDecl::Monitor:
1417                        case ast::AggregateDecl::Thread:
1418                                return new ast::StructInstType(
1419                                        *td->aggregate.name,
1420                                        buildQualifiers( td )
1421                                );
1422                        case ast::AggregateDecl::Union:
1423                                return new ast::UnionInstType(
1424                                        *td->aggregate.name,
1425                                        buildQualifiers( td )
1426                                );
1427                        case ast::AggregateDecl::Trait:
1428                                return new ast::TraitInstType(
1429                                        *td->aggregate.name,
1430                                        buildQualifiers( td )
1431                                );
1432                        default:
1433                                assert( false );
1434                        } // switch
1435                        break;
1436                } // if
1437                break;
1438        default:
1439                assert( false );
1440        } // switch
1441        assert( false );
1442} // buildAggInst
1443
1444
1445ast::BaseInstType * buildAggInst( const TypeData * td ) {
1446        assert( td->kind == TypeData::AggregateInst );
1447
1448        ast::BaseInstType * ret = nullptr;
1449        TypeData * type = td->aggInst.aggregate;
1450        switch ( type->kind ) {
1451        case TypeData::Enum:
1452                return new ast::EnumInstType(
1453                        *type->enumeration.name,
1454                        buildQualifiers( type )
1455                );
1456        case TypeData::Aggregate:
1457                switch ( type->aggregate.kind ) {
1458                case ast::AggregateDecl::Struct:
1459                case ast::AggregateDecl::Coroutine:
1460                case ast::AggregateDecl::Monitor:
1461                case ast::AggregateDecl::Thread:
1462                        ret = new ast::StructInstType(
1463                                *type->aggregate.name,
1464                                buildQualifiers( type )
1465                        );
1466                        break;
1467                case ast::AggregateDecl::Union:
1468                        ret = new ast::UnionInstType(
1469                                *type->aggregate.name,
1470                                buildQualifiers( type )
1471                        );
1472                        break;
1473                case ast::AggregateDecl::Trait:
1474                        ret = new ast::TraitInstType(
1475                                *type->aggregate.name,
1476                                buildQualifiers( type )
1477                        );
1478                        break;
1479                default:
1480                        assert( false );
1481                } // switch
1482                break;
1483        default:
1484                assert( false );
1485        } // switch
1486
1487        ret->hoistType = td->aggInst.hoistType;
1488        buildList( td->aggInst.params, ret->params );
1489        return ret;
1490} // buildAggInst
1491
1492
1493ast::NamedTypeDecl * buildSymbolic(
1494                const TypeData * td,
1495                std::vector<ast::ptr<ast::Attribute>> attributes,
1496                const std::string & name,
1497                ast::Storage::Classes scs,
1498                ast::Linkage::Spec linkage ) {
1499        assert( td->kind == TypeData::Symbolic );
1500        ast::NamedTypeDecl * ret;
1501        assert( td->base );
1502        if ( td->symbolic.isTypedef ) {
1503                ret = new ast::TypedefDecl(
1504                        td->location,
1505                        name,
1506                        scs,
1507                        typebuild( td->base ),
1508                        linkage
1509                );
1510        } else {
1511                ret = new ast::TypeDecl(
1512                        td->location,
1513                        name,
1514                        scs,
1515                        typebuild( td->base ),
1516                        ast::TypeDecl::Dtype,
1517                        true
1518                );
1519        } // if
1520        buildList( td->symbolic.assertions, ret->assertions );
1521        splice( ret->base.get_and_mutate()->attributes, attributes );
1522        return ret;
1523} // buildSymbolic
1524
1525
1526ast::EnumDecl * buildEnum(
1527                const TypeData * td,
1528                std::vector<ast::ptr<ast::Attribute>> && attributes,
1529                ast::Linkage::Spec linkage ) {
1530        assert( td->kind == TypeData::Enum );
1531        ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
1532        ast::EnumDecl * ret = new ast::EnumDecl(
1533                td->location,
1534                *td->enumeration.name,
1535                td->enumeration.typed,
1536                std::move( attributes ),
1537                linkage,
1538                baseType
1539        );
1540        buildList( td->enumeration.constants, ret->members );
1541        auto members = ret->members.begin();
1542        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
1543        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = cur->next, ++members ) {
1544                if ( cur->enumInLine ) {
1545                        // Do Nothing
1546                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
1547                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
1548                } else if ( cur->has_enumeratorValue() ) {
1549                        ast::Decl * member = members->get_and_mutate();
1550                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
1551                        object->init = new ast::SingleInit(
1552                                td->location,
1553                                maybeMoveBuild( cur->consume_enumeratorValue() ),
1554                                ast::NoConstruct
1555                        );
1556                } else if ( !cur->initializer ) {
1557                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
1558                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
1559                        }
1560                }
1561                // else cur is a List Initializer and has been set as init in buildList()
1562                // if
1563        } // for
1564        ret->body = td->enumeration.body;
1565        return ret;
1566} // buildEnum
1567
1568
1569ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
1570        assert( td->kind == TypeData::SymbolicInst );
1571        ast::TypeInstType * ret = new ast::TypeInstType(
1572                *td->symbolic.name,
1573                ast::TypeDecl::Dtype,
1574                buildQualifiers( td )
1575        );
1576        buildList( td->symbolic.actuals, ret->params );
1577        return ret;
1578} // buildSymbolicInst
1579
1580
1581ast::TupleType * buildTuple( const TypeData * td ) {
1582        assert( td->kind == TypeData::Tuple );
1583        std::vector<ast::ptr<ast::Type>> types;
1584        buildTypeList( td->tuple, types );
1585        ast::TupleType * ret = new ast::TupleType(
1586                std::move( types ),
1587                buildQualifiers( td )
1588        );
1589        return ret;
1590} // buildTuple
1591
1592
1593ast::TypeofType * buildTypeof( const TypeData * td ) {
1594        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
1595        assert( td->typeexpr );
1596        return new ast::TypeofType(
1597                td->typeexpr->build(),
1598                td->kind == TypeData::Typeof
1599                        ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
1600                buildQualifiers( td )
1601        );
1602} // buildTypeof
1603
1604
1605ast::VTableType * buildVtable( const TypeData * td ) {
1606        assert( td->base );
1607        return new ast::VTableType(
1608                typebuild( td->base ),
1609                buildQualifiers( td )
1610        );
1611} // buildVtable
1612
1613
1614ast::FunctionDecl * buildFunctionDecl(
1615                const TypeData * td,
1616                const string &name,
1617                ast::Storage::Classes scs,
1618                ast::Function::Specs funcSpec,
1619                ast::Linkage::Spec linkage,
1620                ast::Expr * asmName,
1621                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1622        assert( td->kind == TypeData::Function );
1623        // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
1624        bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
1625        ast::CV::Qualifiers cvq = buildQualifiers( td );
1626        std::vector<ast::ptr<ast::TypeDecl>> forall;
1627        std::vector<ast::ptr<ast::DeclWithType>> assertions;
1628        std::vector<ast::ptr<ast::DeclWithType>> params;
1629        std::vector<ast::ptr<ast::DeclWithType>> returns;
1630        buildList( td->function.params, params );
1631        buildForall( td->forall, forall );
1632        // Functions do not store their assertions there anymore.
1633        for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
1634                auto mut = type_param.get_and_mutate();
1635                splice( assertions, mut->assertions );
1636        }
1637        if ( td->base ) {
1638                switch ( td->base->kind ) {
1639                case TypeData::Tuple:
1640                        buildList( td->base->tuple, returns );
1641                        break;
1642                default:
1643                        returns.push_back( dynamic_cast<ast::DeclWithType *>(
1644                                buildDecl(
1645                                        td->base,
1646                                        "",
1647                                        ast::Storage::Classes(),
1648                                        (ast::Expr *)nullptr, // bitfieldWidth
1649                                        ast::Function::Specs(),
1650                                        ast::Linkage::Cforall,
1651                                        (ast::Expr *)nullptr // asmName
1652                                )
1653                        ) );
1654                } // switch
1655        } else {
1656                returns.push_back( new ast::ObjectDecl(
1657                        td->location,
1658                        "",
1659                        new ast::BasicType( ast::BasicType::SignedInt ),
1660                        (ast::Init *)nullptr,
1661                        ast::Storage::Classes(),
1662                        ast::Linkage::Cforall
1663                ) );
1664        } // if
1665        ast::Stmt * stmt = maybeBuild( td->function.body );
1666        ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
1667        ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
1668                name,
1669                std::move( forall ),
1670                std::move( assertions ),
1671                std::move( params ),
1672                std::move( returns ),
1673                body,
1674                scs,
1675                linkage,
1676                std::move( attributes ),
1677                funcSpec,
1678                (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
1679        );
1680        buildList( td->function.withExprs, decl->withExprs );
1681        decl->asmName = asmName;
1682        // This may be redundant on a declaration.
1683        decl->type.get_and_mutate()->qualifiers = cvq;
1684        return decl;
1685} // buildFunctionDecl
1686
1687
1688ast::Decl * buildDecl(
1689                const TypeData * td,
1690                const string &name,
1691                ast::Storage::Classes scs,
1692                ast::Expr * bitfieldWidth,
1693                ast::Function::Specs funcSpec,
1694                ast::Linkage::Spec linkage,
1695                ast::Expr * asmName,
1696                ast::Init * init,
1697                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1698        if ( td->kind == TypeData::Function ) {
1699                if ( td->function.idList ) {                                    // KR function ?
1700                        buildKRFunction( td->function );                        // transform into C11 function
1701                } // if
1702
1703                return buildFunctionDecl(
1704                        td, name, scs, funcSpec, linkage,
1705                        asmName, std::move( attributes ) );
1706        } else if ( td->kind == TypeData::Aggregate ) {
1707                return buildAggregate( td, std::move( attributes ), linkage );
1708        } else if ( td->kind == TypeData::Enum ) {
1709                return buildEnum( td, std::move( attributes ), linkage );
1710        } else if ( td->kind == TypeData::Symbolic ) {
1711                return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
1712        } else {
1713                auto ret = new ast::ObjectDecl( td->location,
1714                        name,
1715                        typebuild( td ),
1716                        init,
1717                        scs,
1718                        linkage,
1719                        bitfieldWidth,
1720                        std::move( attributes )
1721                );
1722                ret->asmName = asmName;
1723                return ret;
1724        } // if
1725        return nullptr;
1726} // buildDecl
1727
1728
1729ast::FunctionType * buildFunctionType( const TypeData * td ) {
1730        assert( td->kind == TypeData::Function );
1731        ast::FunctionType * ft = new ast::FunctionType(
1732                ( !td->function.params || td->function.params->hasEllipsis )
1733                        ? ast::VariableArgs : ast::FixedArgs,
1734                buildQualifiers( td )
1735        );
1736        buildTypeList( td->function.params, ft->params );
1737        buildForall( td->forall, ft->forall );
1738        if ( td->base ) {
1739                switch ( td->base->kind ) {
1740                case TypeData::Tuple:
1741                        buildTypeList( td->base->tuple, ft->returns );
1742                        break;
1743                default:
1744                        ft->returns.push_back( typebuild( td->base ) );
1745                        break;
1746                } // switch
1747        } else {
1748                ft->returns.push_back(
1749                        new ast::BasicType( ast::BasicType::SignedInt ) );
1750        } // if
1751        return ft;
1752} // buildFunctionType
1753
1754
1755// Transform KR routine declarations into C99 routine declarations:
1756//
1757//    rtn( a, b, c ) int a, c; double b {}  =>  int rtn( int a, double c, int b ) {}
1758//
1759// The type information for each post-declaration is moved to the corresponding pre-parameter and the post-declaration
1760// is deleted. Note, the order of the parameter names may not be the same as the declaration names. Duplicate names and
1761// extra names are disallowed.
1762//
1763// Note, there is no KR routine-prototype syntax:
1764//
1765//    rtn( a, b, c ) int a, c; double b; // invalid KR prototype
1766//    rtn(); // valid KR prototype
1767
1768void buildKRFunction( const TypeData::Function_t & function ) {
1769        assert( ! function.params );
1770        // loop over declaration first as it is easier to spot errors
1771        for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = decl->next ) {
1772                // scan ALL parameter names for each declaration name to check for duplicates
1773                for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
1774                        if ( *decl->name == *param->name ) {
1775                                // type set => parameter name already transformed by a declaration names so there is a duplicate
1776                                // declaration name attempting a second transformation
1777                                if ( param->type ) SemanticError( param->location, "duplicate declaration name \"%s\".", param->name->c_str() );
1778                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
1779                                // parameter name attempting a second transformation
1780                                if ( ! decl->type ) SemanticError( param->location, "duplicate parameter name \"%s\".", param->name->c_str() );
1781                                param->type = decl->type;                               // set copy declaration type to parameter type
1782                                decl->type = nullptr;                                   // reset declaration type
1783                                // Copy and reset attributes from declaration to parameter:
1784                                splice( param->attributes, decl->attributes );
1785                        } // if
1786                } // for
1787                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
1788                if ( decl->type ) SemanticError( decl->location, "missing name in parameter list %s", decl->name->c_str() );
1789        } // for
1790
1791        // Parameter names without a declaration default to type int:
1792        //
1793        //    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
1794
1795        for ( DeclarationNode * param = function.idList; param != nullptr; param = param->next ) {
1796                if ( ! param->type ) {                                                  // generate type int for empty parameter type
1797                        param->type = new TypeData( TypeData::Basic );
1798                        param->type->basictype = TypeData::Int;
1799                } // if
1800        } // for
1801
1802        function.params = function.idList;                                      // newly modified idList becomes parameters
1803        function.idList = nullptr;                                                      // idList now empty
1804        delete function.oldDeclList;                                            // deletes entire list
1805        function.oldDeclList = nullptr;                                         // reset
1806} // buildKRFunction
1807
1808// Local Variables: //
1809// tab-width: 4 //
1810// mode: c++ //
1811// compile-command: "make install" //
1812// End: //
Note: See TracBrowser for help on using the repository browser.