source: src/Parser/TypeData.cc @ 561354f

ADT
Last change on this file since 561354f was 561354f, checked in by JiadaL <j82liang@…>, 12 months ago

Save progress

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