source: src/Parser/TypeData.cc @ 427a577

ast-experimental
Last change on this file since 427a577 was c468150, checked in by Andrew Beach <ajbeach@…>, 19 months ago

Split up ParseNode?.h so that headers match implementation. May have a bit less to include total because of it.

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