source: src/Parser/TypeData.cc @ 647d633

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

Moved a field and functions from DeclarationNode? to TypeData?. Trying to make the line between them cleaner.

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