source: src/Parser/TypeData.cc @ 4eb3a7c5

Last change on this file since 4eb3a7c5 was 4eb3a7c5, checked in by Peter A. Buhr <pabuhr@…>, 3 months ago

first attempt at correct distribution of attributes for aggregates

  • Property mode set to 100644
File size: 43.5 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
481void buildForall(
482                const DeclarationNode * firstNode,
483                std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
484        {
485                std::vector<ast::ptr<ast::Type>> tmpList;
486                buildTypeList( firstNode, tmpList );
487                for ( auto tmp : tmpList ) {
488                        outputList.emplace_back(
489                                strict_dynamic_cast<const ast::TypeInstType *>(
490                                        tmp.release() ) );
491                }
492        }
493        auto n = firstNode;
494        for ( auto i = outputList.begin() ;
495                        i != outputList.end() ;
496                        ++i, n = (DeclarationNode*)n->get_next() ) {
497                // Only the object type class adds additional assertions.
498                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
499                        continue;
500                }
501
502                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
503                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
504                auto mutTypeDecl = ast::mutate( td );
505                const CodeLocation & location = mutTypeDecl->location;
506                *i = mutTypeDecl;
507
508                // add assertion parameters to `type' tyvars in reverse order
509                // add assignment operator:  T * ?=?(T *, T)
510                newAssertions.push_back( new ast::FunctionDecl(
511                        location,
512                        "?=?",
513                        {}, // forall
514                        {}, // assertions
515                        {
516                                new ast::ObjectDecl(
517                                        location,
518                                        "",
519                                        new ast::ReferenceType( i->get() ),
520                                        (ast::Init *)nullptr,
521                                        ast::Storage::Classes(),
522                                        ast::Linkage::Cforall,
523                                        (ast::Expr *)nullptr
524                                ),
525                                new ast::ObjectDecl(
526                                        location,
527                                        "",
528                                        i->get(),
529                                        (ast::Init *)nullptr,
530                                        ast::Storage::Classes(),
531                                        ast::Linkage::Cforall,
532                                        (ast::Expr *)nullptr
533                                ),
534                        }, // params
535                        {
536                                new ast::ObjectDecl(
537                                        location,
538                                        "",
539                                        i->get(),
540                                        (ast::Init *)nullptr,
541                                        ast::Storage::Classes(),
542                                        ast::Linkage::Cforall,
543                                        (ast::Expr *)nullptr
544                                ),
545                        }, // returns
546                        (ast::CompoundStmt *)nullptr,
547                        ast::Storage::Classes(),
548                        ast::Linkage::Cforall
549                ) );
550
551                // add default ctor:  void ?{}(T *)
552                newAssertions.push_back( new ast::FunctionDecl(
553                        location,
554                        "?{}",
555                        {}, // forall
556                        {}, // assertions
557                        {
558                                new ast::ObjectDecl(
559                                        location,
560                                        "",
561                                        new ast::ReferenceType( i->get() ),
562                                        (ast::Init *)nullptr,
563                                        ast::Storage::Classes(),
564                                        ast::Linkage::Cforall,
565                                        (ast::Expr *)nullptr
566                                ),
567                        }, // params
568                        {}, // returns
569                        (ast::CompoundStmt *)nullptr,
570                        ast::Storage::Classes(),
571                        ast::Linkage::Cforall
572                ) );
573
574                // add copy ctor:  void ?{}(T *, T)
575                newAssertions.push_back( new ast::FunctionDecl(
576                        location,
577                        "?{}",
578                        {}, // forall
579                        {}, // assertions
580                        {
581                                new ast::ObjectDecl(
582                                        location,
583                                        "",
584                                        new ast::ReferenceType( i->get() ),
585                                        (ast::Init *)nullptr,
586                                        ast::Storage::Classes(),
587                                        ast::Linkage::Cforall,
588                                        (ast::Expr *)nullptr
589                                ),
590                                new ast::ObjectDecl(
591                                        location,
592                                        "",
593                                        i->get(),
594                                        (ast::Init *)nullptr,
595                                        ast::Storage::Classes(),
596                                        ast::Linkage::Cforall,
597                                        (ast::Expr *)nullptr
598                                ),
599                        }, // params
600                        {}, // returns
601                        (ast::CompoundStmt *)nullptr,
602                        ast::Storage::Classes(),
603                        ast::Linkage::Cforall
604                ) );
605
606                // add dtor:  void ^?{}(T *)
607                newAssertions.push_back( new ast::FunctionDecl(
608                        location,
609                        "^?{}",
610                        {}, // forall
611                        {}, // assertions
612                        {
613                                new ast::ObjectDecl(
614                                        location,
615                                        "",
616                                        new ast::ReferenceType( i->get() ),
617                                        (ast::Init *)nullptr,
618                                        ast::Storage::Classes(),
619                                        ast::Linkage::Cforall,
620                                        (ast::Expr *)nullptr
621                                ),
622                        }, // params
623                        {}, // returns
624                        (ast::CompoundStmt *)nullptr,
625                        ast::Storage::Classes(),
626                        ast::Linkage::Cforall
627                ) );
628
629                spliceBegin( mutTypeDecl->assertions, newAssertions );
630        } // for
631}
632
633
634void buildForall(
635                const DeclarationNode * firstNode,
636                std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
637        buildList( firstNode, outputForall );
638        auto n = firstNode;
639        for ( auto i = outputForall.begin() ;
640                        i != outputForall.end() ;
641                        ++i, n = (DeclarationNode*)n->get_next() ) {
642                // Only the object type class adds additional assertions.
643                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
644                        continue;
645                }
646
647                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
648                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
649                auto mutTypeDecl = ast::mutate( td );
650                const CodeLocation & location = mutTypeDecl->location;
651                *i = mutTypeDecl;
652
653                // add assertion parameters to `type' tyvars in reverse order
654                // add assignment operator:  T * ?=?(T *, T)
655                newAssertions.push_back( new ast::FunctionDecl(
656                        location,
657                        "?=?",
658                        {}, // forall
659                        {}, // assertions
660                        {
661                                new ast::ObjectDecl(
662                                        location,
663                                        "",
664                                        new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
665                                        (ast::Init *)nullptr,
666                                        ast::Storage::Classes(),
667                                        ast::Linkage::Cforall,
668                                        (ast::Expr *)nullptr
669                                ),
670                                new ast::ObjectDecl(
671                                        location,
672                                        "",
673                                        new ast::TypeInstType( td->name, *i ),
674                                        (ast::Init *)nullptr,
675                                        ast::Storage::Classes(),
676                                        ast::Linkage::Cforall,
677                                        (ast::Expr *)nullptr
678                                ),
679                        }, // params
680                        {
681                                new ast::ObjectDecl(
682                                        location,
683                                        "",
684                                        new ast::TypeInstType( td->name, *i ),
685                                        (ast::Init *)nullptr,
686                                        ast::Storage::Classes(),
687                                        ast::Linkage::Cforall,
688                                        (ast::Expr *)nullptr
689                                ),
690                        }, // returns
691                        (ast::CompoundStmt *)nullptr,
692                        ast::Storage::Classes(),
693                        ast::Linkage::Cforall
694                ) );
695
696                // add default ctor:  void ?{}(T *)
697                newAssertions.push_back( new ast::FunctionDecl(
698                        location,
699                        "?{}",
700                        {}, // forall
701                        {}, // assertions
702                        {
703                                new ast::ObjectDecl(
704                                        location,
705                                        "",
706                                        new ast::ReferenceType(
707                                                new ast::TypeInstType( td->name, i->get() ) ),
708                                        (ast::Init *)nullptr,
709                                        ast::Storage::Classes(),
710                                        ast::Linkage::Cforall,
711                                        (ast::Expr *)nullptr
712                                ),
713                        }, // params
714                        {}, // returns
715                        (ast::CompoundStmt *)nullptr,
716                        ast::Storage::Classes(),
717                        ast::Linkage::Cforall
718                ) );
719
720                // add copy ctor:  void ?{}(T *, T)
721                newAssertions.push_back( new ast::FunctionDecl(
722                        location,
723                        "?{}",
724                        {}, // forall
725                        {}, // assertions
726                        {
727                                new ast::ObjectDecl(
728                                        location,
729                                        "",
730                                        new ast::ReferenceType(
731                                                new ast::TypeInstType( td->name, *i ) ),
732                                        (ast::Init *)nullptr,
733                                        ast::Storage::Classes(),
734                                        ast::Linkage::Cforall,
735                                        (ast::Expr *)nullptr
736                                ),
737                                new ast::ObjectDecl(
738                                        location,
739                                        "",
740                                        new ast::TypeInstType( td->name, *i ),
741                                        (ast::Init *)nullptr,
742                                        ast::Storage::Classes(),
743                                        ast::Linkage::Cforall,
744                                        (ast::Expr *)nullptr
745                                ),
746                        }, // params
747                        {}, // returns
748                        (ast::CompoundStmt *)nullptr,
749                        ast::Storage::Classes(),
750                        ast::Linkage::Cforall
751                ) );
752
753                // add dtor:  void ^?{}(T *)
754                newAssertions.push_back( new ast::FunctionDecl(
755                        location,
756                        "^?{}",
757                        {}, // forall
758                        {}, // assertions
759                        {
760                                new ast::ObjectDecl(
761                                        location,
762                                        "",
763                                        new ast::ReferenceType(
764                                                new ast::TypeInstType( i->get() )
765                                        ),
766                                        (ast::Init *)nullptr,
767                                        ast::Storage::Classes(),
768                                        ast::Linkage::Cforall,
769                                        (ast::Expr *)nullptr
770                                ),
771                        }, // params
772                        {}, // returns
773                        (ast::CompoundStmt *)nullptr,
774                        ast::Storage::Classes(),
775                        ast::Linkage::Cforall
776                ) );
777
778                spliceBegin( mutTypeDecl->assertions, newAssertions );
779        } // for
780} // buildForall
781
782
783ast::Type * typebuild( const TypeData * td ) {
784        assert( td );
785        switch ( td->kind ) {
786        case TypeData::Unknown:
787                // fill in implicit int
788                return new ast::BasicType(
789                        ast::BasicType::SignedInt,
790                        buildQualifiers( td )
791                );
792        case TypeData::Basic:
793                return buildBasicType( td );
794        case TypeData::Pointer:
795                return buildPointer( td );
796        case TypeData::Array:
797                return buildArray( td );
798        case TypeData::Reference:
799                return buildReference( td );
800        case TypeData::Function:
801                return buildFunctionType( td );
802        case TypeData::AggregateInst:
803                return buildAggInst( td );
804        case TypeData::EnumConstant:
805                return new ast::EnumInstType( "", buildQualifiers( td ) );
806        case TypeData::SymbolicInst:
807                return buildSymbolicInst( td );
808        case TypeData::Tuple:
809                return buildTuple( td );
810        case TypeData::Typeof:
811        case TypeData::Basetypeof:
812                return buildTypeof( td );
813        case TypeData::Vtable:
814                return buildVtable( td );
815        case TypeData::Builtin:
816                switch ( td->builtintype ) {
817                case DeclarationNode::Zero:
818                        return new ast::ZeroType();
819                case DeclarationNode::One:
820                        return new ast::OneType();
821                default:
822                        return new ast::VarArgsType( buildQualifiers( td ) );
823                } // switch
824        case TypeData::GlobalScope:
825                return new ast::GlobalScopeType();
826        case TypeData::Qualified:
827                return new ast::QualifiedType(
828                        typebuild( td->qualified.parent ),
829                        typebuild( td->qualified.child ),
830                        buildQualifiers( td )
831                );
832        case TypeData::Symbolic:
833        case TypeData::Enum:
834        case TypeData::Aggregate:
835                assert( false );
836        } // switch
837
838        return nullptr;
839} // typebuild
840
841
842TypeData * typeextractAggregate( const TypeData * td, bool toplevel ) {
843        TypeData * ret = nullptr;
844
845        switch ( td->kind ) {
846        case TypeData::Aggregate:
847                if ( ! toplevel && td->aggregate.body ) {
848                        ret = td->clone();
849                } // if
850                break;
851        case TypeData::Enum:
852                if ( ! toplevel && td->enumeration.body ) {
853                        ret = td->clone();
854                } // if
855                break;
856        case TypeData::AggregateInst:
857                if ( td->aggInst.aggregate ) {
858                        ret = typeextractAggregate( td->aggInst.aggregate, false );
859                } // if
860                break;
861        default:
862                if ( td->base ) {
863                        ret = typeextractAggregate( td->base, false );
864                } // if
865        } // switch
866        return ret;
867} // typeextractAggregate
868
869
870ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
871        return td->qualifiers;
872} // buildQualifiers
873
874
875static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
876        SemanticError( yylloc, "invalid type specifier \"%s\" for type \"%s\".", msg.c_str(), DeclarationNode::basicTypeNames[basictype] );
877} // genTSError
878
879ast::Type * buildBasicType( const TypeData * td ) {
880        ast::BasicType::Kind ret;
881
882        switch ( td->basictype ) {
883        case DeclarationNode::Void:
884                if ( td->signedness != DeclarationNode::NoSignedness ) {
885                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
886                } // if
887                if ( td->length != DeclarationNode::NoLength ) {
888                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
889                } // if
890                return new ast::VoidType( buildQualifiers( td ) );
891                break;
892
893        case DeclarationNode::Bool:
894                if ( td->signedness != DeclarationNode::NoSignedness ) {
895                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
896                } // if
897                if ( td->length != DeclarationNode::NoLength ) {
898                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
899                } // if
900
901                ret = ast::BasicType::Bool;
902                break;
903
904        case DeclarationNode::Char:
905                // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the
906                // character types. The implementation shall define char to have the same range, representation, and behavior as
907                // either signed char or unsigned char.
908                static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
909
910                if ( td->length != DeclarationNode::NoLength ) {
911                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
912                } // if
913
914                ret = chartype[ td->signedness ];
915                break;
916
917        case DeclarationNode::Int:
918                static ast::BasicType::Kind inttype[2][4] = {
919                        { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
920                        { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
921                };
922
923        Integral: ;
924                if ( td->signedness == DeclarationNode::NoSignedness ) {
925                        const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed;
926                } // if
927                ret = inttype[ td->signedness ][ td->length ];
928                break;
929
930        case DeclarationNode::Int128:
931                ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
932                if ( td->length != DeclarationNode::NoLength ) {
933                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
934                } // if
935                break;
936
937        case DeclarationNode::Float:
938        case DeclarationNode::Double:
939        case DeclarationNode::LongDouble:                                       // not set until below
940        case DeclarationNode::uuFloat80:
941        case DeclarationNode::uuFloat128:
942        case DeclarationNode::uFloat16:
943        case DeclarationNode::uFloat32:
944        case DeclarationNode::uFloat32x:
945        case DeclarationNode::uFloat64:
946        case DeclarationNode::uFloat64x:
947        case DeclarationNode::uFloat128:
948        case DeclarationNode::uFloat128x:
949                static ast::BasicType::Kind floattype[2][12] = {
950                        { 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, },
951                        { 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, },
952                };
953
954        FloatingPoint: ;
955                if ( td->signedness != DeclarationNode::NoSignedness ) {
956                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
957                } // if
958                if ( td->length == DeclarationNode::Short || td->length == DeclarationNode::LongLong ) {
959                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
960                } // if
961                if ( td->basictype != DeclarationNode::Double && td->length == DeclarationNode::Long ) {
962                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
963                } // if
964                if ( td->complextype == DeclarationNode::Imaginary ) {
965                        genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
966                } // if
967                if ( (td->basictype == DeclarationNode::uuFloat80 || td->basictype == DeclarationNode::uuFloat128) && td->complextype == DeclarationNode::Complex ) { // gcc unsupported
968                        genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
969                } // if
970                if ( td->length == DeclarationNode::Long ) {
971                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
972                } // if
973
974                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
975                //printf( "XXXX %d %d %d %d\n", td->complextype, td->basictype, DeclarationNode::Float, ret );
976                break;
977
978        case DeclarationNode::NoBasicType:
979                // No basic type in declaration => default double for Complex/Imaginary and int type for integral types
980                if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) {
981                        const_cast<TypeData *>(td)->basictype = DeclarationNode::Double;
982                        goto FloatingPoint;
983                } // if
984
985                const_cast<TypeData *>(td)->basictype = DeclarationNode::Int;
986                goto Integral;
987        default:
988                assertf( false, "unknown basic type" );
989                return nullptr;
990        } // switch
991
992        ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
993        return bt;
994} // buildBasicType
995
996
997ast::PointerType * buildPointer( const TypeData * td ) {
998        ast::PointerType * pt;
999        if ( td->base ) {
1000                pt = new ast::PointerType(
1001                        typebuild( td->base ),
1002                        buildQualifiers( td )
1003                );
1004        } else {
1005                pt = new ast::PointerType(
1006                        new ast::BasicType( ast::BasicType::SignedInt ),
1007                        buildQualifiers( td )
1008                );
1009        } // if
1010        return pt;
1011} // buildPointer
1012
1013
1014ast::ArrayType * buildArray( const TypeData * td ) {
1015        ast::ArrayType * at;
1016        if ( td->base ) {
1017                at = new ast::ArrayType(
1018                        typebuild( td->base ),
1019                        maybeBuild( td->array.dimension ),
1020                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
1021                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
1022                        buildQualifiers( td )
1023                );
1024        } else {
1025                at = new ast::ArrayType(
1026                        new ast::BasicType( ast::BasicType::SignedInt ),
1027                        maybeBuild( td->array.dimension ),
1028                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
1029                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
1030                        buildQualifiers( td )
1031                );
1032        } // if
1033        return at;
1034} // buildArray
1035
1036
1037ast::ReferenceType * buildReference( const TypeData * td ) {
1038        ast::ReferenceType * rt;
1039        if ( td->base ) {
1040                rt = new ast::ReferenceType(
1041                        typebuild( td->base ),
1042                        buildQualifiers( td )
1043                );
1044        } else {
1045                rt = new ast::ReferenceType(
1046                        new ast::BasicType( ast::BasicType::SignedInt ),
1047                        buildQualifiers( td )
1048                );
1049        } // if
1050        return rt;
1051} // buildReference
1052
1053
1054ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
1055        assert( td->kind == TypeData::Aggregate );
1056        ast::AggregateDecl * at;
1057        switch ( td->aggregate.kind ) {
1058        case ast::AggregateDecl::Struct:
1059        case ast::AggregateDecl::Coroutine:
1060        case ast::AggregateDecl::Exception:
1061        case ast::AggregateDecl::Generator:
1062        case ast::AggregateDecl::Monitor:
1063        case ast::AggregateDecl::Thread:
1064                at = new ast::StructDecl( td->location,
1065                        *td->aggregate.name,
1066                        td->aggregate.kind,
1067                        std::move( attributes ),
1068                        linkage
1069                );
1070                buildForall( td->aggregate.params, at->params );
1071                break;
1072        case ast::AggregateDecl::Union:
1073                at = new ast::UnionDecl( td->location,
1074                        *td->aggregate.name,
1075                        std::move( attributes ),
1076                        linkage
1077                );
1078                buildForall( td->aggregate.params, at->params );
1079                break;
1080        case ast::AggregateDecl::Trait:
1081                at = new ast::TraitDecl( td->location,
1082                        *td->aggregate.name,
1083                        std::move( attributes ),
1084                        linkage
1085                );
1086                buildList( td->aggregate.params, at->params );
1087                break;
1088        default:
1089                assert( false );
1090        } // switch
1091
1092        buildList( td->aggregate.fields, at->members );
1093        at->set_body( td->aggregate.body );
1094
1095        return at;
1096} // buildAggregate
1097
1098
1099ast::BaseInstType * buildComAggInst(
1100                const TypeData * td,
1101                std::vector<ast::ptr<ast::Attribute>> && attributes,
1102                ast::Linkage::Spec linkage ) {
1103        switch ( td->kind ) {
1104        case TypeData::Enum:
1105                if ( td->enumeration.body ) {
1106                        ast::EnumDecl * typedecl =
1107                                buildEnum( td, std::move( attributes ), linkage );
1108                        return new ast::EnumInstType(
1109                                typedecl,
1110                                buildQualifiers( td )
1111                        );
1112                } else {
1113                        return new ast::EnumInstType(
1114                                *td->enumeration.name,
1115                                buildQualifiers( td )
1116                        );
1117                } // if
1118                break;
1119        case TypeData::Aggregate:
1120                if ( td->aggregate.body ) {
1121                        ast::AggregateDecl * typedecl =
1122                                buildAggregate( td, std::move( attributes ), linkage );
1123                        switch ( td->aggregate.kind ) {
1124                        case ast::AggregateDecl::Struct:
1125                        case ast::AggregateDecl::Coroutine:
1126                        case ast::AggregateDecl::Monitor:
1127                        case ast::AggregateDecl::Thread:
1128                                return new ast::StructInstType(
1129                                        strict_dynamic_cast<ast::StructDecl *>( typedecl ),
1130                                        buildQualifiers( td )
1131                                );
1132                        case ast::AggregateDecl::Union:
1133                                return new ast::UnionInstType(
1134                                        strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
1135                                        buildQualifiers( td )
1136                                );
1137                        case ast::AggregateDecl::Trait:
1138                                assert( false );
1139                                break;
1140                        default:
1141                                assert( false );
1142                        } // switch
1143                } else {
1144                        switch ( td->aggregate.kind ) {
1145                        case ast::AggregateDecl::Struct:
1146                        case ast::AggregateDecl::Coroutine:
1147                        case ast::AggregateDecl::Monitor:
1148                        case ast::AggregateDecl::Thread:
1149                                return new ast::StructInstType(
1150                                        *td->aggregate.name,
1151                                        buildQualifiers( td )
1152                                );
1153                        case ast::AggregateDecl::Union:
1154                                return new ast::UnionInstType(
1155                                        *td->aggregate.name,
1156                                        buildQualifiers( td )
1157                                );
1158                        case ast::AggregateDecl::Trait:
1159                                return new ast::TraitInstType(
1160                                        *td->aggregate.name,
1161                                        buildQualifiers( td )
1162                                );
1163                        default:
1164                                assert( false );
1165                        } // switch
1166                        break;
1167                } // if
1168                break;
1169        default:
1170                assert( false );
1171        } // switch
1172        assert( false );
1173} // buildAggInst
1174
1175
1176ast::BaseInstType * buildAggInst( const TypeData * td ) {
1177        assert( td->kind == TypeData::AggregateInst );
1178
1179        ast::BaseInstType * ret = nullptr;
1180        TypeData * type = td->aggInst.aggregate;
1181        switch ( type->kind ) {
1182        case TypeData::Enum:
1183                return new ast::EnumInstType(
1184                        *type->enumeration.name,
1185                        buildQualifiers( type )
1186                );
1187        case TypeData::Aggregate:
1188                switch ( type->aggregate.kind ) {
1189                case ast::AggregateDecl::Struct:
1190                case ast::AggregateDecl::Coroutine:
1191                case ast::AggregateDecl::Monitor:
1192                case ast::AggregateDecl::Thread:
1193                        ret = new ast::StructInstType(
1194                                *type->aggregate.name,
1195                                buildQualifiers( type )
1196                        );
1197                        break;
1198                case ast::AggregateDecl::Union:
1199                        ret = new ast::UnionInstType(
1200                                *type->aggregate.name,
1201                                buildQualifiers( type )
1202                        );
1203                        break;
1204                case ast::AggregateDecl::Trait:
1205                        ret = new ast::TraitInstType(
1206                                *type->aggregate.name,
1207                                buildQualifiers( type )
1208                        );
1209                        break;
1210                default:
1211                        assert( false );
1212                } // switch
1213                break;
1214        default:
1215                assert( false );
1216        } // switch
1217
1218        ret->hoistType = td->aggInst.hoistType;
1219        buildList( td->aggInst.params, ret->params );
1220        return ret;
1221} // buildAggInst
1222
1223
1224ast::NamedTypeDecl * buildSymbolic(
1225                const TypeData * td,
1226                std::vector<ast::ptr<ast::Attribute>> attributes,
1227                const std::string & name,
1228                ast::Storage::Classes scs,
1229                ast::Linkage::Spec linkage ) {
1230        assert( td->kind == TypeData::Symbolic );
1231        ast::NamedTypeDecl * ret;
1232        assert( td->base );
1233        if ( td->symbolic.isTypedef ) {
1234                ret = new ast::TypedefDecl(
1235                        td->location,
1236                        name,
1237                        scs,
1238                        typebuild( td->base ),
1239                        linkage
1240                );
1241        } else {
1242                ret = new ast::TypeDecl(
1243                        td->location,
1244                        name,
1245                        scs,
1246                        typebuild( td->base ),
1247                        ast::TypeDecl::Dtype,
1248                        true
1249                );
1250        } // if
1251        buildList( td->symbolic.assertions, ret->assertions );
1252        splice( ret->base.get_and_mutate()->attributes, attributes );
1253        return ret;
1254} // buildSymbolic
1255
1256
1257ast::EnumDecl * buildEnum(
1258                const TypeData * td,
1259                std::vector<ast::ptr<ast::Attribute>> && attributes,
1260                ast::Linkage::Spec linkage ) {
1261        assert( td->kind == TypeData::Enum );
1262        ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
1263        ast::EnumDecl * ret = new ast::EnumDecl(
1264                td->location,
1265                *td->enumeration.name,
1266                td->enumeration.typed,
1267                std::move( attributes ),
1268                linkage,
1269                baseType
1270        );
1271        buildList( td->enumeration.constants, ret->members );
1272        auto members = ret->members.begin();
1273        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
1274        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
1275                if ( cur->enumInLine ) {
1276                        // Do Nothing
1277                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
1278                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
1279                } else if ( cur->has_enumeratorValue() ) {
1280                        ast::Decl * member = members->get_and_mutate();
1281                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
1282                        object->init = new ast::SingleInit(
1283                                td->location,
1284                                maybeMoveBuild( cur->consume_enumeratorValue() ),
1285                                ast::NoConstruct
1286                        );
1287                } else if ( !cur->initializer ) {
1288                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
1289                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
1290                        }
1291                }
1292                // else cur is a List Initializer and has been set as init in buildList()
1293                // if
1294        } // for
1295        ret->body = td->enumeration.body;
1296        return ret;
1297} // buildEnum
1298
1299
1300ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
1301        assert( td->kind == TypeData::SymbolicInst );
1302        ast::TypeInstType * ret = new ast::TypeInstType(
1303                *td->symbolic.name,
1304                ast::TypeDecl::Dtype,
1305                buildQualifiers( td )
1306        );
1307        buildList( td->symbolic.actuals, ret->params );
1308        return ret;
1309} // buildSymbolicInst
1310
1311
1312ast::TupleType * buildTuple( const TypeData * td ) {
1313        assert( td->kind == TypeData::Tuple );
1314        std::vector<ast::ptr<ast::Type>> types;
1315        buildTypeList( td->tuple, types );
1316        ast::TupleType * ret = new ast::TupleType(
1317                std::move( types ),
1318                buildQualifiers( td )
1319        );
1320        return ret;
1321} // buildTuple
1322
1323
1324ast::TypeofType * buildTypeof( const TypeData * td ) {
1325        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
1326        assert( td->typeexpr );
1327        return new ast::TypeofType(
1328                td->typeexpr->build(),
1329                td->kind == TypeData::Typeof
1330                        ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
1331                buildQualifiers( td )
1332        );
1333} // buildTypeof
1334
1335
1336ast::VTableType * buildVtable( const TypeData * td ) {
1337        assert( td->base );
1338        return new ast::VTableType(
1339                typebuild( td->base ),
1340                buildQualifiers( td )
1341        );
1342} // buildVtable
1343
1344
1345ast::FunctionDecl * buildFunctionDecl(
1346                const TypeData * td,
1347                const string &name,
1348                ast::Storage::Classes scs,
1349                ast::Function::Specs funcSpec,
1350                ast::Linkage::Spec linkage,
1351                ast::Expr * asmName,
1352                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1353        assert( td->kind == TypeData::Function );
1354        // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
1355        bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
1356        ast::CV::Qualifiers cvq = buildQualifiers( td );
1357        std::vector<ast::ptr<ast::TypeDecl>> forall;
1358        std::vector<ast::ptr<ast::DeclWithType>> assertions;
1359        std::vector<ast::ptr<ast::DeclWithType>> params;
1360        std::vector<ast::ptr<ast::DeclWithType>> returns;
1361        buildList( td->function.params, params );
1362        buildForall( td->forall, forall );
1363        // Functions do not store their assertions there anymore.
1364        for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
1365                auto mut = type_param.get_and_mutate();
1366                splice( assertions, mut->assertions );
1367        }
1368        if ( td->base ) {
1369                switch ( td->base->kind ) {
1370                case TypeData::Tuple:
1371                        buildList( td->base->tuple, returns );
1372                        break;
1373                default:
1374                        returns.push_back( dynamic_cast<ast::DeclWithType *>(
1375                                buildDecl(
1376                                        td->base,
1377                                        "",
1378                                        ast::Storage::Classes(),
1379                                        (ast::Expr *)nullptr, // bitfieldWidth
1380                                        ast::Function::Specs(),
1381                                        ast::Linkage::Cforall,
1382                                        (ast::Expr *)nullptr // asmName
1383                                )
1384                        ) );
1385                } // switch
1386        } else {
1387                returns.push_back( new ast::ObjectDecl(
1388                        td->location,
1389                        "",
1390                        new ast::BasicType( ast::BasicType::SignedInt ),
1391                        (ast::Init *)nullptr,
1392                        ast::Storage::Classes(),
1393                        ast::Linkage::Cforall
1394                ) );
1395        } // if
1396        ast::Stmt * stmt = maybeBuild( td->function.body );
1397        ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
1398        ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
1399                name,
1400                std::move( forall ),
1401                std::move( assertions ),
1402                std::move( params ),
1403                std::move( returns ),
1404                body,
1405                scs,
1406                linkage,
1407                std::move( attributes ),
1408                funcSpec,
1409                (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
1410        );
1411        buildList( td->function.withExprs, decl->withExprs );
1412        decl->asmName = asmName;
1413        // This may be redundant on a declaration.
1414        decl->type.get_and_mutate()->qualifiers = cvq;
1415        return decl;
1416} // buildFunctionDecl
1417
1418
1419ast::Decl * buildDecl(
1420                const TypeData * td,
1421                const string &name,
1422                ast::Storage::Classes scs,
1423                ast::Expr * bitfieldWidth,
1424                ast::Function::Specs funcSpec,
1425                ast::Linkage::Spec linkage,
1426                ast::Expr * asmName,
1427                ast::Init * init,
1428                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1429        if ( td->kind == TypeData::Function ) {
1430                if ( td->function.idList ) {                                    // KR function ?
1431                        buildKRFunction( td->function );                        // transform into C11 function
1432                } // if
1433
1434                return buildFunctionDecl(
1435                        td, name, scs, funcSpec, linkage,
1436                        asmName, std::move( attributes ) );
1437        } else if ( td->kind == TypeData::Aggregate ) {
1438                return buildAggregate( td, std::move( attributes ), linkage );
1439        } else if ( td->kind == TypeData::Enum ) {
1440                return buildEnum( td, std::move( attributes ), linkage );
1441        } else if ( td->kind == TypeData::Symbolic ) {
1442                return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
1443        } else {
1444                auto ret = new ast::ObjectDecl( td->location,
1445                        name,
1446                        typebuild( td ),
1447                        init,
1448                        scs,
1449                        linkage,
1450                        bitfieldWidth,
1451                        std::move( attributes )
1452                );
1453                ret->asmName = asmName;
1454                return ret;
1455        } // if
1456        return nullptr;
1457} // buildDecl
1458
1459
1460ast::FunctionType * buildFunctionType( const TypeData * td ) {
1461        assert( td->kind == TypeData::Function );
1462        ast::FunctionType * ft = new ast::FunctionType(
1463                ( !td->function.params || td->function.params->hasEllipsis )
1464                        ? ast::VariableArgs : ast::FixedArgs,
1465                buildQualifiers( td )
1466        );
1467        buildTypeList( td->function.params, ft->params );
1468        buildForall( td->forall, ft->forall );
1469        if ( td->base ) {
1470                switch ( td->base->kind ) {
1471                case TypeData::Tuple:
1472                        buildTypeList( td->base->tuple, ft->returns );
1473                        break;
1474                default:
1475                        ft->returns.push_back( typebuild( td->base ) );
1476                        break;
1477                } // switch
1478        } else {
1479                ft->returns.push_back(
1480                        new ast::BasicType( ast::BasicType::SignedInt ) );
1481        } // if
1482        return ft;
1483} // buildFunctionType
1484
1485
1486// Transform KR routine declarations into C99 routine declarations:
1487//
1488//    rtn( a, b, c ) int a, c; double b {}  =>  int rtn( int a, double c, int b ) {}
1489//
1490// The type information for each post-declaration is moved to the corresponding pre-parameter and the post-declaration
1491// is deleted. Note, the order of the parameter names may not be the same as the declaration names. Duplicate names and
1492// extra names are disallowed.
1493//
1494// Note, there is no KR routine-prototype syntax:
1495//
1496//    rtn( a, b, c ) int a, c; double b; // invalid KR prototype
1497//    rtn(); // valid KR prototype
1498
1499void buildKRFunction( const TypeData::Function_t & function ) {
1500        assert( ! function.params );
1501        // loop over declaration first as it is easier to spot errors
1502        for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = dynamic_cast< DeclarationNode * >( decl->get_next() ) ) {
1503                // scan ALL parameter names for each declaration name to check for duplicates
1504                for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
1505                        if ( *decl->name == *param->name ) {
1506                                // type set => parameter name already transformed by a declaration names so there is a duplicate
1507                                // declaration name attempting a second transformation
1508                                if ( param->type ) SemanticError( param->location, "duplicate declaration name \"%s\".", param->name->c_str() );
1509                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
1510                                // parameter name attempting a second transformation
1511                                if ( ! decl->type ) SemanticError( param->location, "duplicate parameter name \"%s\".", param->name->c_str() );
1512                                param->type = decl->type;                               // set copy declaration type to parameter type
1513                                decl->type = nullptr;                                   // reset declaration type
1514                                // Copy and reset attributes from declaration to parameter:
1515                                splice( param->attributes, decl->attributes );
1516                        } // if
1517                } // for
1518                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
1519                if ( decl->type ) SemanticError( decl->location, "missing name in parameter list %s", decl->name->c_str() );
1520        } // for
1521
1522        // Parameter names without a declaration default to type int:
1523        //
1524        //    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
1525
1526        for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
1527                if ( ! param->type ) {                                                  // generate type int for empty parameter type
1528                        param->type = new TypeData( TypeData::Basic );
1529                        param->type->basictype = DeclarationNode::Int;
1530                } // if
1531        } // for
1532
1533        function.params = function.idList;                                      // newly modified idList becomes parameters
1534        function.idList = nullptr;                                                      // idList now empty
1535        delete function.oldDeclList;                                            // deletes entire list
1536        function.oldDeclList = nullptr;                                         // reset
1537} // buildKRFunction
1538
1539// Local Variables: //
1540// tab-width: 4 //
1541// mode: c++ //
1542// compile-command: "make install" //
1543// End: //
Note: See TracBrowser for help on using the repository browser.