source: src/Parser/TypeData.cc @ c1e66d9

Last change on this file since c1e66d9 was c1e66d9, checked in by JiadaL <j82liang@…>, 5 months ago

Fix designator value in enumerated array and implemented enumerated array with inlined enume declaration

  • Property mode set to 100644
File size: 43.2 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        if ( td->declType) {
1024                at->declaredType = buildEnum( td->declType, std::vector<ast::ptr<ast::Attribute>>(), ast::Linkage::Cforall );
1025        }
1026        return at;
1027} // buildArray
1028
1029
1030ast::ReferenceType * buildReference( const TypeData * td ) {
1031        ast::ReferenceType * rt;
1032        if ( td->base ) {
1033                rt = new ast::ReferenceType(
1034                        typebuild( td->base ),
1035                        buildQualifiers( td )
1036                );
1037        } else {
1038                rt = new ast::ReferenceType(
1039                        new ast::BasicType( ast::BasicType::SignedInt ),
1040                        buildQualifiers( td )
1041                );
1042        } // if
1043        return rt;
1044} // buildReference
1045
1046
1047ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
1048        assert( td->kind == TypeData::Aggregate );
1049        ast::AggregateDecl * at;
1050        switch ( td->aggregate.kind ) {
1051        case ast::AggregateDecl::Struct:
1052        case ast::AggregateDecl::Coroutine:
1053        case ast::AggregateDecl::Exception:
1054        case ast::AggregateDecl::Generator:
1055        case ast::AggregateDecl::Monitor:
1056        case ast::AggregateDecl::Thread:
1057                at = new ast::StructDecl( td->location,
1058                        *td->aggregate.name,
1059                        td->aggregate.kind,
1060                        std::move( attributes ),
1061                        linkage
1062                );
1063                buildForall( td->aggregate.params, at->params );
1064                break;
1065        case ast::AggregateDecl::Union:
1066                at = new ast::UnionDecl( td->location,
1067                        *td->aggregate.name,
1068                        std::move( attributes ),
1069                        linkage
1070                );
1071                buildForall( td->aggregate.params, at->params );
1072                break;
1073        case ast::AggregateDecl::Trait:
1074                at = new ast::TraitDecl( td->location,
1075                        *td->aggregate.name,
1076                        std::move( attributes ),
1077                        linkage
1078                );
1079                buildList( td->aggregate.params, at->params );
1080                break;
1081        default:
1082                assert( false );
1083        } // switch
1084
1085        buildList( td->aggregate.fields, at->members );
1086        at->set_body( td->aggregate.body );
1087
1088        return at;
1089} // buildAggregate
1090
1091
1092ast::BaseInstType * buildComAggInst(
1093                const TypeData * type,
1094                std::vector<ast::ptr<ast::Attribute>> && attributes,
1095                ast::Linkage::Spec linkage ) {
1096        switch ( type->kind ) {
1097        case TypeData::Enum:
1098                if ( type->enumeration.body ) {
1099                        ast::EnumDecl * typedecl =
1100                                buildEnum( type, std::move( attributes ), linkage );
1101                        return new ast::EnumInstType(
1102                                typedecl,
1103                                buildQualifiers( type )
1104                        );
1105                } else {
1106                        return new ast::EnumInstType(
1107                                *type->enumeration.name,
1108                                buildQualifiers( type )
1109                        );
1110                } // if
1111                break;
1112        case TypeData::Aggregate:
1113                if ( type->aggregate.body ) {
1114                        ast::AggregateDecl * typedecl =
1115                                buildAggregate( type, std::move( attributes ), linkage );
1116                        switch ( type->aggregate.kind ) {
1117                        case ast::AggregateDecl::Struct:
1118                        case ast::AggregateDecl::Coroutine:
1119                        case ast::AggregateDecl::Monitor:
1120                        case ast::AggregateDecl::Thread:
1121                                return new ast::StructInstType(
1122                                        strict_dynamic_cast<ast::StructDecl *>( typedecl ),
1123                                        buildQualifiers( type )
1124                                );
1125                        case ast::AggregateDecl::Union:
1126                                return new ast::UnionInstType(
1127                                        strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
1128                                        buildQualifiers( type )
1129                                );
1130                        case ast::AggregateDecl::Trait:
1131                                assert( false );
1132                                break;
1133                        default:
1134                                assert( false );
1135                        } // switch
1136                } else {
1137                        switch ( type->aggregate.kind ) {
1138                        case ast::AggregateDecl::Struct:
1139                        case ast::AggregateDecl::Coroutine:
1140                        case ast::AggregateDecl::Monitor:
1141                        case ast::AggregateDecl::Thread:
1142                                return new ast::StructInstType(
1143                                        *type->aggregate.name,
1144                                        buildQualifiers( type )
1145                                );
1146                        case ast::AggregateDecl::Union:
1147                                return new ast::UnionInstType(
1148                                        *type->aggregate.name,
1149                                        buildQualifiers( type )
1150                                );
1151                        case ast::AggregateDecl::Trait:
1152                                return new ast::TraitInstType(
1153                                        *type->aggregate.name,
1154                                        buildQualifiers( type )
1155                                );
1156                        default:
1157                                assert( false );
1158                        } // switch
1159                        break;
1160                } // if
1161                break;
1162        default:
1163                assert( false );
1164        } // switch
1165        assert( false );
1166} // buildAggInst
1167
1168
1169ast::BaseInstType * buildAggInst( const TypeData * td ) {
1170        assert( td->kind == TypeData::AggregateInst );
1171
1172        ast::BaseInstType * ret = nullptr;
1173        TypeData * type = td->aggInst.aggregate;
1174        switch ( type->kind ) {
1175        case TypeData::Enum:
1176                return new ast::EnumInstType(
1177                        *type->enumeration.name,
1178                        buildQualifiers( type )
1179                );
1180        case TypeData::Aggregate:
1181                switch ( type->aggregate.kind ) {
1182                case ast::AggregateDecl::Struct:
1183                case ast::AggregateDecl::Coroutine:
1184                case ast::AggregateDecl::Monitor:
1185                case ast::AggregateDecl::Thread:
1186                        ret = new ast::StructInstType(
1187                                *type->aggregate.name,
1188                                buildQualifiers( type )
1189                        );
1190                        break;
1191                case ast::AggregateDecl::Union:
1192                        ret = new ast::UnionInstType(
1193                                *type->aggregate.name,
1194                                buildQualifiers( type )
1195                        );
1196                        break;
1197                case ast::AggregateDecl::Trait:
1198                        ret = new ast::TraitInstType(
1199                                *type->aggregate.name,
1200                                buildQualifiers( type )
1201                        );
1202                        break;
1203                default:
1204                        assert( false );
1205                } // switch
1206                break;
1207        default:
1208                assert( false );
1209        } // switch
1210
1211        ret->hoistType = td->aggInst.hoistType;
1212        buildList( td->aggInst.params, ret->params );
1213        return ret;
1214} // buildAggInst
1215
1216
1217ast::NamedTypeDecl * buildSymbolic(
1218                const TypeData * td,
1219                std::vector<ast::ptr<ast::Attribute>> attributes,
1220                const std::string & name,
1221                ast::Storage::Classes scs,
1222                ast::Linkage::Spec linkage ) {
1223        assert( td->kind == TypeData::Symbolic );
1224        ast::NamedTypeDecl * ret;
1225        assert( td->base );
1226        if ( td->symbolic.isTypedef ) {
1227                ret = new ast::TypedefDecl(
1228                        td->location,
1229                        name,
1230                        scs,
1231                        typebuild( td->base ),
1232                        linkage
1233                );
1234        } else {
1235                ret = new ast::TypeDecl(
1236                        td->location,
1237                        name,
1238                        scs,
1239                        typebuild( td->base ),
1240                        ast::TypeDecl::Dtype,
1241                        true
1242                );
1243        } // if
1244        buildList( td->symbolic.assertions, ret->assertions );
1245        splice( ret->base.get_and_mutate()->attributes, attributes );
1246        return ret;
1247} // buildSymbolic
1248
1249
1250ast::EnumDecl * buildEnum(
1251                const TypeData * td,
1252                std::vector<ast::ptr<ast::Attribute>> && attributes,
1253                ast::Linkage::Spec linkage ) {
1254        assert( td->kind == TypeData::Enum );
1255        ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
1256        ast::EnumDecl * ret = new ast::EnumDecl(
1257                td->location,
1258                *td->enumeration.name,
1259                td->enumeration.typed,
1260                std::move( attributes ),
1261                linkage,
1262                baseType
1263        );
1264        buildList( td->enumeration.constants, ret->members );
1265        auto members = ret->members.begin();
1266        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
1267        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
1268                if ( cur->enumInLine ) {
1269                        // Do Nothing
1270                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
1271                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
1272                } else if ( cur->has_enumeratorValue() ) {
1273                        ast::Decl * member = members->get_and_mutate();
1274                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
1275                        object->init = new ast::SingleInit(
1276                                td->location,
1277                                maybeMoveBuild( cur->consume_enumeratorValue() ),
1278                                ast::NoConstruct
1279                        );
1280                } else if ( !cur->initializer ) {
1281                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
1282                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
1283                        }
1284                }
1285                // else cur is a List Initializer and has been set as init in buildList()
1286                // if
1287        } // for
1288        ret->body = td->enumeration.body;
1289        return ret;
1290} // buildEnum
1291
1292
1293ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
1294        assert( td->kind == TypeData::SymbolicInst );
1295        ast::TypeInstType * ret = new ast::TypeInstType(
1296                *td->symbolic.name,
1297                ast::TypeDecl::Dtype,
1298                buildQualifiers( td )
1299        );
1300        buildList( td->symbolic.actuals, ret->params );
1301        return ret;
1302} // buildSymbolicInst
1303
1304
1305ast::TupleType * buildTuple( const TypeData * td ) {
1306        assert( td->kind == TypeData::Tuple );
1307        std::vector<ast::ptr<ast::Type>> types;
1308        buildTypeList( td->tuple, types );
1309        ast::TupleType * ret = new ast::TupleType(
1310                std::move( types ),
1311                buildQualifiers( td )
1312        );
1313        return ret;
1314} // buildTuple
1315
1316
1317ast::TypeofType * buildTypeof( const TypeData * td ) {
1318        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
1319        assert( td->typeexpr );
1320        return new ast::TypeofType(
1321                td->typeexpr->build(),
1322                td->kind == TypeData::Typeof
1323                        ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
1324                buildQualifiers( td )
1325        );
1326} // buildTypeof
1327
1328
1329ast::VTableType * buildVtable( const TypeData * td ) {
1330        assert( td->base );
1331        return new ast::VTableType(
1332                typebuild( td->base ),
1333                buildQualifiers( td )
1334        );
1335} // buildVtable
1336
1337
1338ast::FunctionDecl * buildFunctionDecl(
1339                const TypeData * td,
1340                const string &name,
1341                ast::Storage::Classes scs,
1342                ast::Function::Specs funcSpec,
1343                ast::Linkage::Spec linkage,
1344                ast::Expr * asmName,
1345                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1346        assert( td->kind == TypeData::Function );
1347        // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
1348        bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
1349        ast::CV::Qualifiers cvq = buildQualifiers( td );
1350        std::vector<ast::ptr<ast::TypeDecl>> forall;
1351        std::vector<ast::ptr<ast::DeclWithType>> assertions;
1352        std::vector<ast::ptr<ast::DeclWithType>> params;
1353        std::vector<ast::ptr<ast::DeclWithType>> returns;
1354        buildList( td->function.params, params );
1355        buildForall( td->forall, forall );
1356        // Functions do not store their assertions there anymore.
1357        for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
1358                auto mut = type_param.get_and_mutate();
1359                splice( assertions, mut->assertions );
1360        }
1361        if ( td->base ) {
1362                switch ( td->base->kind ) {
1363                case TypeData::Tuple:
1364                        buildList( td->base->tuple, returns );
1365                        break;
1366                default:
1367                        returns.push_back( dynamic_cast<ast::DeclWithType *>(
1368                                buildDecl(
1369                                        td->base,
1370                                        "",
1371                                        ast::Storage::Classes(),
1372                                        (ast::Expr *)nullptr, // bitfieldWidth
1373                                        ast::Function::Specs(),
1374                                        ast::Linkage::Cforall,
1375                                        (ast::Expr *)nullptr // asmName
1376                                )
1377                        ) );
1378                } // switch
1379        } else {
1380                returns.push_back( new ast::ObjectDecl(
1381                        td->location,
1382                        "",
1383                        new ast::BasicType( ast::BasicType::SignedInt ),
1384                        (ast::Init *)nullptr,
1385                        ast::Storage::Classes(),
1386                        ast::Linkage::Cforall
1387                ) );
1388        } // if
1389        ast::Stmt * stmt = maybeBuild( td->function.body );
1390        ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
1391        ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
1392                name,
1393                std::move( forall ),
1394                std::move( assertions ),
1395                std::move( params ),
1396                std::move( returns ),
1397                body,
1398                scs,
1399                linkage,
1400                std::move( attributes ),
1401                funcSpec,
1402                (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
1403        );
1404        buildList( td->function.withExprs, decl->withExprs );
1405        decl->asmName = asmName;
1406        // This may be redundant on a declaration.
1407        decl->type.get_and_mutate()->qualifiers = cvq;
1408        return decl;
1409} // buildFunctionDecl
1410
1411
1412ast::Decl * buildDecl(
1413                const TypeData * td,
1414                const string &name,
1415                ast::Storage::Classes scs,
1416                ast::Expr * bitfieldWidth,
1417                ast::Function::Specs funcSpec,
1418                ast::Linkage::Spec linkage,
1419                ast::Expr * asmName,
1420                ast::Init * init,
1421                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
1422        if ( td->kind == TypeData::Function ) {
1423                if ( td->function.idList ) {                                    // KR function ?
1424                        buildKRFunction( td->function );                        // transform into C11 function
1425                } // if
1426
1427                return buildFunctionDecl(
1428                        td, name, scs, funcSpec, linkage,
1429                        asmName, std::move( attributes ) );
1430        } else if ( td->kind == TypeData::Aggregate ) {
1431                return buildAggregate( td, std::move( attributes ), linkage );
1432        } else if ( td->kind == TypeData::Enum ) {
1433                return buildEnum( td, std::move( attributes ), linkage );
1434        } else if ( td->kind == TypeData::Symbolic ) {
1435                return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
1436        } else {
1437                auto ret = new ast::ObjectDecl( td->location,
1438                        name,
1439                        typebuild( td ),
1440                        init,
1441                        scs,
1442                        linkage,
1443                        bitfieldWidth,
1444                        std::move( attributes )
1445                );
1446                ret->asmName = asmName;
1447                return ret;
1448        } // if
1449        return nullptr;
1450} // buildDecl
1451
1452
1453ast::FunctionType * buildFunctionType( const TypeData * td ) {
1454        assert( td->kind == TypeData::Function );
1455        ast::FunctionType * ft = new ast::FunctionType(
1456                ( !td->function.params || td->function.params->hasEllipsis )
1457                        ? ast::VariableArgs : ast::FixedArgs,
1458                buildQualifiers( td )
1459        );
1460        buildTypeList( td->function.params, ft->params );
1461        buildForall( td->forall, ft->forall );
1462        if ( td->base ) {
1463                switch ( td->base->kind ) {
1464                case TypeData::Tuple:
1465                        buildTypeList( td->base->tuple, ft->returns );
1466                        break;
1467                default:
1468                        ft->returns.push_back( typebuild( td->base ) );
1469                        break;
1470                } // switch
1471        } else {
1472                ft->returns.push_back(
1473                        new ast::BasicType( ast::BasicType::SignedInt ) );
1474        } // if
1475        return ft;
1476} // buildFunctionType
1477
1478
1479// Transform KR routine declarations into C99 routine declarations:
1480//
1481//    rtn( a, b, c ) int a, c; double b {}  =>  int rtn( int a, double c, int b ) {}
1482//
1483// The type information for each post-declaration is moved to the corresponding pre-parameter and the post-declaration
1484// is deleted. Note, the order of the parameter names may not be the same as the declaration names. Duplicate names and
1485// extra names are disallowed.
1486//
1487// Note, there is no KR routine-prototype syntax:
1488//
1489//    rtn( a, b, c ) int a, c; double b; // invalid KR prototype
1490//    rtn(); // valid KR prototype
1491
1492void buildKRFunction( const TypeData::Function_t & function ) {
1493        assert( ! function.params );
1494        // loop over declaration first as it is easier to spot errors
1495        for ( DeclarationNode * decl = function.oldDeclList; decl != nullptr; decl = dynamic_cast< DeclarationNode * >( decl->get_next() ) ) {
1496                // scan ALL parameter names for each declaration name to check for duplicates
1497                for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
1498                        if ( *decl->name == *param->name ) {
1499                                // type set => parameter name already transformed by a declaration names so there is a duplicate
1500                                // declaration name attempting a second transformation
1501                                if ( param->type ) SemanticError( param->location, string( "duplicate declaration name " ) + *param->name );
1502                                // declaration type reset => declaration already transformed by a parameter name so there is a duplicate
1503                                // parameter name attempting a second transformation
1504                                if ( ! decl->type ) SemanticError( param->location, string( "duplicate parameter name " ) + *param->name );
1505                                param->type = decl->type;                               // set copy declaration type to parameter type
1506                                decl->type = nullptr;                                   // reset declaration type
1507                                // Copy and reset attributes from declaration to parameter:
1508                                splice( param->attributes, decl->attributes );
1509                        } // if
1510                } // for
1511                // declaration type still set => type not moved to a matching parameter so there is a missing parameter name
1512                if ( decl->type ) SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
1513        } // for
1514
1515        // Parameter names without a declaration default to type int:
1516        //
1517        //    rtb( a, b, c ) const char * b; {} => int rtn( int a, const char * b, int c ) {}
1518
1519        for ( DeclarationNode * param = function.idList; param != nullptr; param = dynamic_cast< DeclarationNode * >( param->get_next() ) ) {
1520                if ( ! param->type ) {                                                  // generate type int for empty parameter type
1521                        param->type = new TypeData( TypeData::Basic );
1522                        param->type->basictype = DeclarationNode::Int;
1523                } // if
1524        } // for
1525
1526        function.params = function.idList;                                      // newly modified idList becomes parameters
1527        function.idList = nullptr;                                                      // idList now empty
1528        delete function.oldDeclList;                                            // deletes entire list
1529        function.oldDeclList = nullptr;                                         // reset
1530} // buildKRFunction
1531
1532// Local Variables: //
1533// tab-width: 4 //
1534// mode: c++ //
1535// compile-command: "make install" //
1536// End: //
Note: See TracBrowser for help on using the repository browser.