Changeset 22f94a4 for src


Ignore:
Timestamp:
Aug 11, 2020, 4:40:15 PM (22 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
0d070ca
Parents:
07d867b (diff), 129674b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into new-ast

Location:
src
Files:
1 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • src/Common/PassVisitor.proto.h

    r07d867b r22f94a4  
    3838        };
    3939
    40         std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
     40        std::stack< cleanup_t, std::vector< cleanup_t > > cleanups;
    4141};
    4242
  • src/Common/ScopedMap.h

    r07d867b r22f94a4  
    9393
    9494                reference operator* () { return *it; }
    95                 pointer operator-> () { return it.operator->(); }
     95                pointer operator-> () const { return it.operator->(); }
    9696
    9797                iterator& operator++ () {
  • src/Concurrency/Keywords.cc

    r07d867b r22f94a4  
    510510                                                new CastExpr(
    511511                                                        new VariableExpr( func->get_functionType()->get_parameters().front() ),
    512                                                         func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone()
     512                                                        func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(),
     513                                                        false
    513514                                                )
    514515                                        )
     
    888889                        new SingleInit( new UntypedExpr(
    889890                                new NameExpr( "get_monitor" ),
    890                                 {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     891                                {  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
    891892                        ))
    892893                );
     
    909910                                        {
    910911                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
    911                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     912                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
    912913                                        },
    913914                                        noDesignators,
     
    946947                                        return new SingleInit( new UntypedExpr(
    947948                                                new NameExpr( "get_monitor" ),
    948                                                 {  new CastExpr( new VariableExpr( var ), type ) }
     949                                                {  new CastExpr( new VariableExpr( var ), type, false ) }
    949950                                        ) );
    950951                                })
     
    970971                                                new SingleInit( new VariableExpr( monitors ) ),
    971972                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
    972                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     973                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
    973974                                        },
    974975                                        noDesignators,
  • src/Concurrency/Waitfor.cc

    r07d867b r22f94a4  
    384384                                                                decl_monitor
    385385                                                        )
    386                                                 )
     386                                                ),
     387                                                false
    387388                                        );
    388389
     
    408409                        new CompoundStmt({
    409410                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
    410                                 makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
     411                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t, false )                     , indexer ),
    411412                                makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
    412413                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
     
    531532                                                                decl_mask
    532533                                                        )
    533                                                 )
     534                                                ),
     535                                                false
    534536                                        ),
    535537                                        timeout
  • src/ControlStruct/ExceptTranslate.cc

    r07d867b r22f94a4  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 11:58:00 2020
    13 // Update Count     : 13
     12// Last Modified On : Wed Jun 24 11:18:00 2020
     13// Update Count     : 17
    1414//
    1515
     
    6464        }
    6565
    66         class ExceptionMutatorCore : public WithGuards {
    67                 enum Context { NoHandler, TerHandler, ResHandler };
    68 
    69                 // Also need to handle goto, break & continue.
    70                 // They need to be cut off in a ResHandler, until we enter another
    71                 // loop, switch or the goto stays within the function.
    72 
    73                 Context cur_context;
    74 
    75                 // The current (innermost) termination handler exception declaration.
    76                 ObjectDecl * handler_except_decl;
    77 
     66        class ThrowMutatorCore : public WithGuards {
     67                ObjectDecl * terminate_handler_except;
     68                enum Context { NoHandler, TerHandler, ResHandler } cur_context;
     69
     70                // The helper functions for code/syntree generation.
     71                Statement * create_either_throw(
     72                        ThrowStmt * throwStmt, const char * throwFunc );
     73                Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
     74
     75        public:
     76                ThrowMutatorCore() :
     77                        terminate_handler_except( nullptr ),
     78                        cur_context( NoHandler )
     79                {}
     80
     81                void premutate( CatchStmt *catchStmt );
     82                Statement * postmutate( ThrowStmt *throwStmt );
     83        };
     84
     85        // ThrowStmt Mutation Helpers
     86
     87        Statement * ThrowMutatorCore::create_either_throw(
     88                        ThrowStmt * throwStmt, const char * throwFunc ) {
     89                // `throwFunc`( `throwStmt->get_name()` );
     90                UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
     91                call->get_args().push_back( throwStmt->get_expr() );
     92                throwStmt->set_expr( nullptr );
     93                delete throwStmt;
     94                return new ExprStmt( call );
     95        }
     96
     97        Statement * ThrowMutatorCore::create_terminate_rethrow(
     98                        ThrowStmt *throwStmt ) {
     99                // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
     100                assert( nullptr == throwStmt->get_expr() );
     101                assert( terminate_handler_except );
     102
     103                CompoundStmt * result = new CompoundStmt();
     104                result->labels =  throwStmt->labels;
     105                result->push_back( new ExprStmt( UntypedExpr::createAssign(
     106                        nameOf( terminate_handler_except ),
     107                        new ConstantExpr( Constant::null(
     108                                terminate_handler_except->get_type()->clone()
     109                                ) )
     110                        ) ) );
     111                result->push_back( new ExprStmt(
     112                        new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
     113                        ) );
     114                delete throwStmt;
     115                return result;
     116        }
     117
     118        // Visiting/Mutating Functions
     119
     120        void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
     121                // Validate the statement's form.
     122                ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
     123                // Also checking the type would be nice.
     124                if ( !decl || !dynamic_cast<PointerType *>( decl->type ) ) {
     125                        std::string kind = (CatchStmt::Terminate == catchStmt->kind) ? "catch" : "catchResume";
     126                        SemanticError( catchStmt->location, kind + " must have pointer to an exception type" );
     127                }
     128
     129                // Track the handler context.
     130                GuardValue( cur_context );
     131                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     132                        cur_context = TerHandler;
     133
     134                        GuardValue( terminate_handler_except );
     135                        terminate_handler_except = decl;
     136                } else {
     137                        cur_context = ResHandler;
     138                }
     139        }
     140
     141        Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     142                // Ignoring throwStmt->get_target() for now.
     143                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
     144                        if ( throwStmt->get_expr() ) {
     145                                return create_either_throw( throwStmt, "$throw" );
     146                        } else if ( TerHandler == cur_context ) {
     147                                return create_terminate_rethrow( throwStmt );
     148                        } else {
     149                                abort("Invalid throw in %s at %i\n",
     150                                        throwStmt->location.filename.c_str(),
     151                                        throwStmt->location.first_line);
     152                        }
     153                } else {
     154                        if ( throwStmt->get_expr() ) {
     155                                return create_either_throw( throwStmt, "$throwResume" );
     156                        } else if ( ResHandler == cur_context ) {
     157                                // This has to be handled later.
     158                                return throwStmt;
     159                        } else {
     160                                abort("Invalid throwResume in %s at %i\n",
     161                                        throwStmt->location.filename.c_str(),
     162                                        throwStmt->location.first_line);
     163                        }
     164                }
     165        }
     166
     167        class TryMutatorCore {
    78168                // The built in types used in translation.
    79169                StructDecl * except_decl;
     
    82172
    83173                // The many helper functions for code/syntree generation.
    84                 Statement * create_given_throw(
    85                         const char * throwFunc, ThrowStmt * throwStmt );
    86                 Statement * create_terminate_throw( ThrowStmt * throwStmt );
    87                 Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
    88                 Statement * create_resume_throw( ThrowStmt * throwStmt );
    89                 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    90174                CompoundStmt * take_try_block( TryStmt * tryStmt );
    91175                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    101185                FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
    102186                ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
     187                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    103188
    104189                // Types used in translation, make sure to use clone.
     
    121206
    122207        public:
    123                 ExceptionMutatorCore() :
    124                         cur_context( NoHandler ),
    125                         handler_except_decl( nullptr ),
     208                TryMutatorCore() :
    126209                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    127210                        try_func_t( noQualifiers, false ),
     
    132215                {}
    133216
    134                 void premutate( CatchStmt *catchStmt );
    135217                void premutate( StructDecl *structDecl );
     218                Statement * postmutate( TryStmt *tryStmt );
    136219                Statement * postmutate( ThrowStmt *throwStmt );
    137                 Statement * postmutate( TryStmt *tryStmt );
    138220        };
    139221
    140         void ExceptionMutatorCore::init_func_types() {
     222        void TryMutatorCore::init_func_types() {
    141223                assert( except_decl );
    142224
     
    196278        }
    197279
    198         // ThrowStmt Mutation Helpers
    199 
    200         Statement * ExceptionMutatorCore::create_given_throw(
    201                         const char * throwFunc, ThrowStmt * throwStmt ) {
    202                 // `throwFunc`( `throwStmt->get_name` );
    203                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    204                 call->get_args().push_back( throwStmt->get_expr() );
    205                 throwStmt->set_expr( nullptr );
    206                 delete throwStmt;
    207                 return new ExprStmt( call );
    208         }
    209 
    210         Statement * ExceptionMutatorCore::create_terminate_throw(
    211                         ThrowStmt *throwStmt ) {
    212                 // __throw_terminate( `throwStmt->get_name()` ); }
    213                 return create_given_throw( "__cfaehm_throw_terminate", throwStmt );
    214         }
    215 
    216         Statement * ExceptionMutatorCore::create_terminate_rethrow(
    217                         ThrowStmt *throwStmt ) {
    218                 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
    219                 assert( nullptr == throwStmt->get_expr() );
    220                 assert( handler_except_decl );
    221 
    222                 CompoundStmt * result = new CompoundStmt();
    223                 result->labels =  throwStmt->labels;
    224                 result->push_back( new ExprStmt( UntypedExpr::createAssign(
    225                         nameOf( handler_except_decl ),
    226                         new ConstantExpr( Constant::null(
    227                                 new PointerType(
    228                                         noQualifiers,
    229                                         handler_except_decl->get_type()->clone()
    230                                         )
    231                                 ) )
    232                         ) ) );
    233                 result->push_back( new ExprStmt(
    234                         new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
    235                         ) );
    236                 delete throwStmt;
    237                 return result;
    238         }
    239 
    240         Statement * ExceptionMutatorCore::create_resume_throw(
    241                         ThrowStmt *throwStmt ) {
    242                 // __throw_resume( `throwStmt->get_name` );
    243                 return create_given_throw( "__cfaehm_throw_resume", throwStmt );
    244         }
    245 
    246         Statement * ExceptionMutatorCore::create_resume_rethrow(
    247                         ThrowStmt *throwStmt ) {
    248                 // return false;
    249                 Statement * result = new ReturnStmt(
    250                         new ConstantExpr( Constant::from_bool( false ) )
    251                         );
    252                 result->labels = throwStmt->labels;
    253                 delete throwStmt;
    254                 return result;
    255         }
    256 
    257280        // TryStmt Mutation Helpers
    258281
    259         CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
     282        CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
    260283                CompoundStmt * block = tryStmt->get_block();
    261284                tryStmt->set_block( nullptr );
     
    263286        }
    264287
    265         FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
     288        FunctionDecl * TryMutatorCore::create_try_wrapper(
    266289                        CompoundStmt *body ) {
    267290
     
    270293        }
    271294
    272         FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
     295        FunctionDecl * TryMutatorCore::create_terminate_catch(
    273296                        CatchList &handlers ) {
    274297                std::list<CaseStmt *> handler_wrappers;
     
    350373        // Create a single check from a moddified handler.
    351374        // except_obj is referenced, modded_handler will be freed.
    352         CompoundStmt * ExceptionMutatorCore::create_single_matcher(
     375        CompoundStmt * TryMutatorCore::create_single_matcher(
    353376                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    354377                // {
     
    388411        }
    389412
    390         FunctionDecl * ExceptionMutatorCore::create_terminate_match(
     413        FunctionDecl * TryMutatorCore::create_terminate_match(
    391414                        CatchList &handlers ) {
    392415                // int match(exception * except) {
     
    425448        }
    426449
    427         CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
     450        CompoundStmt * TryMutatorCore::create_terminate_caller(
    428451                        FunctionDecl * try_wrapper,
    429452                        FunctionDecl * terminate_catch,
     
    443466        }
    444467
    445         FunctionDecl * ExceptionMutatorCore::create_resume_handler(
     468        FunctionDecl * TryMutatorCore::create_resume_handler(
    446469                        CatchList &handlers ) {
    447470                // bool handle(exception * except) {
     
    480503        }
    481504
    482         CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
     505        CompoundStmt * TryMutatorCore::create_resume_wrapper(
    483506                        Statement * wraps,
    484507                        FunctionDecl * resume_handler ) {
     
    524547        }
    525548
    526         FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
     549        FunctionDecl * TryMutatorCore::create_finally_wrapper(
    527550                        TryStmt * tryStmt ) {
    528                 // void finally() { <finally code> }
     551                // void finally() { `finally->block` }
    529552                FinallyStmt * finally = tryStmt->get_finally();
    530553                CompoundStmt * body = finally->get_block();
     
    537560        }
    538561
    539         ObjectDecl * ExceptionMutatorCore::create_finally_hook(
     562        ObjectDecl * TryMutatorCore::create_finally_hook(
    540563                        FunctionDecl * finally_wrapper ) {
    541564                // struct __cfaehm_cleanup_hook __finally_hook
    542                 //      __attribute__((cleanup( finally_wrapper )));
     565                //      __attribute__((cleanup( `finally_wrapper` )));
    543566
    544567                // Make Cleanup Attribute.
     
    564587        }
    565588
     589        Statement * TryMutatorCore::create_resume_rethrow( ThrowStmt *throwStmt ) {
     590                // return false;
     591                Statement * result = new ReturnStmt(
     592                        new ConstantExpr( Constant::from_bool( false ) )
     593                        );
     594                result->labels = throwStmt->labels;
     595                delete throwStmt;
     596                return result;
     597        }
     598
    566599        // Visiting/Mutating Functions
    567         void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    568                 // Validate the Statement's form.
    569                 ObjectDecl * decl =
    570                         dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    571                 if ( decl && true /* check decl->get_type() */ ) {
    572                         // Pass.
    573                 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    574                         SemanticError(catchStmt->location, "catch must have exception type");
    575                 } else {
    576                         SemanticError(catchStmt->location, "catchResume must have exception type");
    577                 }
    578 
    579                 // Track the handler context.
    580                 GuardValue( cur_context );
    581                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    582                         cur_context = TerHandler;
    583 
    584                         GuardValue( handler_except_decl );
    585                         handler_except_decl = decl;
    586                 } else {
    587                         cur_context = ResHandler;
    588                 }
    589         }
    590 
    591         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     600        void TryMutatorCore::premutate( StructDecl *structDecl ) {
    592601                if ( !structDecl->has_body() ) {
    593602                        // Skip children?
     
    604613                        hook_decl = structDecl;
    605614                }
    606                 // Later we might get the exception type as well.
    607         }
    608 
    609         Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    610                 assert( except_decl );
    611 
    612                 // Ignoring throwStmt->get_target() for now.
    613                 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
    614                         if ( throwStmt->get_expr() ) {
    615                                 return create_terminate_throw( throwStmt );
    616                         } else if ( TerHandler == cur_context ) {
    617                                 return create_terminate_rethrow( throwStmt );
    618                         } else {
    619                                 abort("Invalid throw in %s at %i\n",
    620                                         throwStmt->location.filename.c_str(),
    621                                         throwStmt->location.first_line);
    622                         }
    623                 } else {
    624                         if ( throwStmt->get_expr() ) {
    625                                 return create_resume_throw( throwStmt );
    626                         } else if ( ResHandler == cur_context ) {
    627                                 return create_resume_rethrow( throwStmt );
    628                         } else {
    629                                 abort("Invalid throwResume in %s at %i\n",
    630                                         throwStmt->location.filename.c_str(),
    631                                         throwStmt->location.first_line);
    632                         }
    633                 }
    634         }
    635 
    636         Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
     615        }
     616
     617        Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
    637618                assert( except_decl );
    638619                assert( node_decl );
     
    688669        }
    689670
    690         void translateEHM( std::list< Declaration *> & translationUnit ) {
    691                 PassVisitor<ExceptionMutatorCore> translator;
     671        Statement * TryMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     672                // Only valid `throwResume;` statements should remain. (2/3 checks)
     673                assert( ThrowStmt::Resume == throwStmt->kind && ! throwStmt->expr );
     674                return create_resume_rethrow( throwStmt );
     675        }
     676
     677        void translateThrows( std::list< Declaration *> & translationUnit ) {
     678                PassVisitor<ThrowMutatorCore> translator;
    692679                mutateAll( translationUnit, translator );
    693680        }
     681
     682        void translateTries( std::list< Declaration *> & translationUnit ) {
     683                PassVisitor<TryMutatorCore> translator;
     684                mutateAll( translationUnit, translator );
     685        }
    694686}
  • src/ControlStruct/ExceptTranslate.h

    r07d867b r22f94a4  
    99// Author           : Andrew Beach
    1010// Created On       : Tus Jun 06 10:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:19:23 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tus May 19 11:47:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2121
    2222namespace ControlStruct {
    23         void translateEHM( std::list< Declaration *> & translationUnit );
    24         // Converts exception handling structures into their underlying C code.  Translation does use the exception
    25         // handling header, make sure it is visible wherever translation occurs.
     23        void translateThrows( std::list< Declaration *> & translationUnit );
     24        /* Replaces all throw & throwResume statements with function calls.
     25         * These still need to be resolved, so call this before the reslover.
     26         */
     27
     28        void translateTries( std::list< Declaration *> & translationUnit );
     29        /* Replaces all try blocks (and their many clauses) with function definitions and calls.
     30         * This uses the exception built-ins to produce typed output and should take place after
     31         * the resolver. It also produces virtual casts and should happen before they are expanded.
     32         */
    2633}
    2734
  • src/GenPoly/InstantiateGeneric.cc

    r07d867b r22f94a4  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu Aug 04 18:33:00 2016
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Aug 04 18:33:00 2016
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 16 10:17:00 2020
     13// Update Count     : 2
    1414//
    1515#include "InstantiateGeneric.h"
     
    297297        }
    298298
     299        template< typename AggrInst >
     300        static AggrInst * asForward( AggrInst * decl ) {
     301                if ( !decl->body ) {
     302                        return nullptr;
     303                }
     304                decl = decl->clone();
     305                decl->body = false;
     306                deleteAll( decl->members );
     307                decl->members.clear();
     308                return decl;
     309        }
     310
    299311        void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
    300312                substituteMembers( base->get_members(), baseParams, typeSubs );
     
    373385                                concDecl->set_body( inst->get_baseStruct()->has_body() );
    374386                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    375                                 insert( inst, typeSubs, concDecl ); // must insert before recursion
     387                                // Forward declare before recursion. (TODO: Only when needed, #199.)
     388                                insert( inst, typeSubs, concDecl );
     389                                if ( StructDecl *forwardDecl = asForward( concDecl ) ) {
     390                                        declsToAddBefore.push_back( forwardDecl );
     391                                }
    376392                                concDecl->acceptMutator( *visitor ); // recursively instantiate members
    377393                                declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
     
    423439                                concDecl->set_body( inst->get_baseUnion()->has_body() );
    424440                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
    425                                 insert( inst, typeSubs, concDecl ); // must insert before recursion
     441                                // Forward declare before recursion. (TODO: Only when needed, #199.)
     442                                insert( inst, typeSubs, concDecl );
     443                                if ( UnionDecl *forwardDecl = asForward( concDecl ) ) {
     444                                        declsToAddBefore.push_back( forwardDecl );
     445                                }
    426446                                concDecl->acceptMutator( *visitor ); // recursively instantiate members
    427447                                declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
  • src/GenPoly/Specialize.cc

    r07d867b r22f94a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:40:49 2019
    13 // Update Count     : 32
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Jul  2 17:42:00 2020
     13// Update Count     : 33
    1414//
    1515
     
    4242
    4343namespace GenPoly {
    44         struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     44        struct Specialize final : public WithConstTypeSubstitution,
     45                        public WithDeclsToAdd, public WithVisitorRef<Specialize> {
    4546                Expression * postmutate( ApplicationExpr *applicationExpr );
    4647                Expression * postmutate( CastExpr *castExpr );
     
    248249                } // if
    249250
    250                 // handle any specializations that may still be present
    251                 std::string oldParamPrefix = paramPrefix;
    252                 paramPrefix += "p";
    253                 // save stmtsToAddBefore in oldStmts
    254                 std::list< Statement* > oldStmts;
    255                 oldStmts.splice( oldStmts.end(), stmtsToAddBefore );
    256                 appExpr->acceptMutator( *visitor );
    257                 paramPrefix = oldParamPrefix;
    258                 // write any statements added for recursive specializations into the thunk body
    259                 thunkFunc->statements->kids.splice( thunkFunc->statements->kids.end(), stmtsToAddBefore );
    260                 // restore oldStmts into stmtsToAddBefore
    261                 stmtsToAddBefore.splice( stmtsToAddBefore.end(), oldStmts );
     251                // Handle any specializations that may still be present.
     252                {
     253                        std::string oldParamPrefix = paramPrefix;
     254                        paramPrefix += "p";
     255                        std::list< Declaration * > oldDecls;
     256                        oldDecls.splice( oldDecls.end(), declsToAddBefore );
     257
     258                        appExpr->acceptMutator( *visitor );
     259                        // Write recursive specializations into the thunk body.
     260                        for ( Declaration * decl : declsToAddBefore ) {
     261                                thunkFunc->statements->kids.push_back( new DeclStmt( decl ) );
     262                        }
     263
     264                        declsToAddBefore = std::move( oldDecls );
     265                        paramPrefix = oldParamPrefix;
     266                }
    262267
    263268                // add return (or valueless expression) to the thunk
     
    270275                thunkFunc->statements->kids.push_back( appStmt );
    271276
    272                 // add thunk definition to queue of statements to add
    273                 stmtsToAddBefore.push_back( new DeclStmt( thunkFunc ) );
     277                // Add the thunk definition (converted to DeclStmt if appproprate).
     278                declsToAddBefore.push_back( thunkFunc );
    274279                // return address of thunk function as replacement expression
    275280                return new AddressExpr( new VariableExpr( thunkFunc ) );
  • src/Parser/DeclarationNode.cc

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 16 15:32:22 2019
    13 // Update Count     : 1133
     12// Last Modified On : Tue Jun  9 20:26:55 2020
     13// Update Count     : 1134
    1414//
    1515
     
    11151115        // SUE's cannot have function specifiers, either
    11161116        //
    1117         //    inlne _Noreturn struct S { ... };         // disallowed
    1118         //    inlne _Noreturn enum   E { ... };         // disallowed
     1117        //    inline _Noreturn struct S { ... };                // disallowed
     1118        //    inline _Noreturn enum   E { ... };                // disallowed
    11191119        if ( funcSpecs.any() ) {
    11201120                SemanticError( this, "invalid function specifier for " );
  • src/Parser/ExpressionNode.cc

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 18 21:14:58 2019
    13 // Update Count     : 981
     12// Last Modified On : Wed Jul 15 08:24:08 2020
     13// Update Count     : 1046
    1414//
    1515
     
    8585        } // if
    8686        // remove "lL" for these cases because it may not imply long
    87         str.erase( posn );                                                                      // remove length
     87        str.erase( posn );                                                                      // remove length suffix and "uU"
    8888} // lnthSuffix
    8989
     
    108108} // valueToType
    109109
     110static void scanbin( string & str, unsigned long long int & v ) {
     111        v = 0;
     112        size_t last = str.length() - 1;                                         // last subscript of constant
     113        for ( unsigned int i = 2;; ) {                                          // ignore prefix
     114                if ( str[i] == '1' ) v |= 1;
     115                i += 1;
     116          if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
     117                v <<= 1;
     118        } // for
     119} // scanbin
     120
    110121Expression * build_constantInteger( string & str ) {
    111122        static const BasicType::Kind kind[2][6] = {
    112123                // short (h) must be before char (hh) because shorter type has the longer suffix
    113                 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
    114                 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
     124                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, },
     125                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, },
    115126        };
    116127
     
    120131        }; // lnthsInt
    121132
    122         unsigned long long int v;                                                       // converted integral value
    123         size_t last = str.length() - 1;                                         // last subscript of constant
    124         Expression * ret;
    125         //string fred( str );
     133        string str2( "0x0" );
     134        unsigned long long int v, v2 = 0;                                       // converted integral value
     135        Expression * ret, * ret2;
    126136
    127137        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     
    139149        } // if
    140150
     151        string::size_type posn;
     152
     153        // 'u' can appear before or after length suffix
     154        if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
     155
     156        if ( isdigit( str[str.length() - 1] ) ) {                       // no suffix ?
     157                lnthSuffix( str, type, ltype );                                 // could have length suffix
     158                if ( type == 5 && Unsigned ) str.erase( str.length() - 1 ); // L128 and terminating "uU" ?
     159        } else {
     160                // At least one digit in integer constant, so safe to backup while looking for suffix.
     161
     162                posn = str.find_last_of( "pP" );                                // pointer value
     163                if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; }
     164
     165                posn = str.find_last_of( "zZ" );                                // size_t
     166                if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
     167
     168                posn = str.rfind( "hh" );                                               // char
     169                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     170
     171                posn = str.rfind( "HH" );                                               // char
     172                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     173
     174                posn = str.find_last_of( "hH" );                                // short
     175                if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
     176
     177                posn = str.find_last_of( "nN" );                                // int (natural number)
     178                if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
     179
     180                if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
     181
     182                lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
     183          FINI: ;
     184        } // if
     185
    141186        // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
    142187
     188#if ! defined(__SIZEOF_INT128__)
     189        if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str );
     190#endif // ! __SIZEOF_INT128__
     191       
    143192        if ( str[0] == '0' ) {                                                          // radix character ?
    144193                dec = false;
    145194                if ( checkX( str[1] ) ) {                                               // hex constant ?
    146                         sscanf( (char *)str.c_str(), "%llx", &v );
     195                        if ( type < 5 ) {                                                       // not L128 ?
     196                                sscanf( (char *)str.c_str(), "%llx", &v );
     197                        } else {                                                                        // hex int128 constant
     198                                unsigned int len = str.length();
     199                                if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str );
     200                          if ( len <= (2 + 16) ) goto FHEX1;            // hex digits < 2^64
     201                                str2 = "0x" + str.substr( len - 16 );
     202                                sscanf( (char *)str2.c_str(), "%llx", &v2 );
     203                                str = str.substr( 0, len - 16 );
     204                          FHEX1: ;
     205                                sscanf( (char *)str.c_str(), "%llx", &v );
     206                        } // if
    147207                        //printf( "%llx %llu\n", v, v );
    148208                } else if ( checkB( str[1] ) ) {                                // binary constant ?
    149                         v = 0;                                                                          // compute value
    150                         for ( unsigned int i = 2;; ) {                          // ignore prefix
    151                                 if ( str[i] == '1' ) v |= 1;
    152                                 i += 1;
    153                           if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
    154                                 v <<= 1;
    155                         } // for
     209                        unsigned int len = str.length();
     210                        if ( type == 5 && len > 2 + 64 ) {
     211                                if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large " + str );
     212                                str2 = "0b" + str.substr( len - 64 );
     213                                str = str.substr( 0, len - 64 );
     214                                scanbin( str2, v2 );
     215                        } // if
     216                        scanbin( str, v );
    156217                        //printf( "%#llx %llu\n", v, v );
    157218                } else {                                                                                // octal constant
    158                         sscanf( (char *)str.c_str(), "%llo", &v );
     219                        if ( type < 5 ) {                                                       // not L128 ?
     220                                sscanf( (char *)str.c_str(), "%llo", &v );
     221#if defined(__SIZEOF_INT128__)
     222                        } else {                                                                        // octal int128 constant
     223                                unsigned int len = str.length();
     224                                if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large " + str );
     225                                if ( len <= 1 + 21 ) {                                  // value < 21 octal digitis
     226                                        sscanf( (char *)str.c_str(), "%llo", &v ); // leave value in octal
     227                                } else {
     228                                        sscanf( &str[len - 21], "%llo", &v );
     229                                        __int128 val = v;                                       // accumulate bits
     230                                        str[len - 21] ='\0';                            // shorten string
     231                                        sscanf( &str[len == 43 ? 1 : 0], "%llo", &v );
     232                                        val |= (__int128)v << 63;                       // store bits
     233                                        if ( len == 1 + 43 ) {                          // most significant 2 bits ?
     234                                                str[2] = '\0';                                  // shorten string
     235                                                sscanf( &str[1], "%llo", &v );  // process most significant 2 bits
     236                                                val |= (__int128)v << 126;              // store bits
     237                                        } // if
     238                                        v = val >> 64; v2 = (uint64_t)val;      // replace octal constant with 2 hex constants
     239                                        char buf[32];
     240                                        sprintf( buf, "%#llx", v2 );
     241                                        str2 = buf;
     242                                        sprintf( buf, "%#llx", v );
     243                                        str = buf;
     244                                } // if
     245#endif // __SIZEOF_INT128__
     246                        } // if
    159247                        //printf( "%#llo %llu\n", v, v );
    160248                } // if
    161249        } else {                                                                                        // decimal constant ?
    162                 sscanf( (char *)str.c_str(), "%llu", &v );
     250                if ( type < 5 ) {                                                               // not L128 ?
     251                        sscanf( (char *)str.c_str(), "%llu", &v );
     252#if defined(__SIZEOF_INT128__)
     253                } else {                                                                                // decimal int128 constant
     254                        #define P10_UINT64 10'000'000'000'000'000'000ULL // 19 zeroes
     255                        unsigned int len = str.length();
     256                        if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") )
     257                                SemanticError( yylloc, "128-bit decimal constant to large " + str );
     258                        if ( len <= 19 ) {                                                      // value < 19 decimal digitis
     259                                sscanf( (char *)str.c_str(), "%llu", &v ); // leave value in decimal
     260                        } else {
     261                                sscanf( &str[len - 19], "%llu", &v );
     262                                __int128 val = v;                                               // accumulate bits
     263                                str[len - 19] ='\0';                                    // shorten string
     264                                sscanf( &str[len == 39 ? 1 : 0], "%llu", &v );
     265                                val += (__int128)v * (__int128)P10_UINT64; // store bits
     266                                if ( len == 39 ) {                                              // most significant 2 bits ?
     267                                        str[1] = '\0';                                          // shorten string
     268                                        sscanf( &str[0], "%llu", &v );          // process most significant 2 bits
     269                                        val += (__int128)v * (__int128)P10_UINT64 * (__int128)P10_UINT64; // store bits
     270                                } // if
     271                                v = val >> 64; v2 = (uint64_t)val;              // replace decimal constant with 2 hex constants
     272                                char buf[32];
     273                                sprintf( buf, "%#llx", v2 );
     274                                str2 = buf;
     275                                sprintf( buf, "%#llx", v );
     276                                str = buf;
     277                        } // if
     278#endif // __SIZEOF_INT128__
     279                } // if
    163280                //printf( "%llu\n", v );
    164281        } // if
    165282
    166         string::size_type posn;
    167 
    168         if ( isdigit( str[last] ) ) {                                           // no suffix ?
    169                 lnthSuffix( str, type, ltype );                                 // could have length suffix
    170                 if ( type == -1 ) {                                                             // no suffix
    171                         valueToType( v, dec, type, Unsigned );
    172                 } // if
    173         } else {
    174                 // At least one digit in integer constant, so safe to backup while looking for suffix.
    175 
    176                 posn = str.find_last_of( "pP" );
    177                 if ( posn != string::npos ) { valueToType( v, dec, type, Unsigned ); ltype = 5; str.erase( posn, 1 ); goto FINI; }
    178 
    179                 posn = str.find_last_of( "zZ" );
    180                 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    181 
    182                 // 'u' can appear before or after length suffix
    183                 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
    184 
    185                 posn = str.rfind( "hh" );
    186                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    187 
    188                 posn = str.rfind( "HH" );
    189                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    190 
    191                 posn = str.find_last_of( "hH" );
    192                 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
    193 
    194                 posn = str.find_last_of( "nN" );
    195                 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
    196 
    197                 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
    198 
    199                 lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
    200                 if ( type == -1 ) {                                                             // only 'u' suffix ?
    201                         valueToType( v, dec, type, Unsigned );
    202                 } // if
    203           FINI: ;
    204         } // if
     283        if ( type == -1 ) {                                                                     // no suffix => determine type from value size
     284                valueToType( v, dec, type, Unsigned );
     285        } // if
     286        /* printf( "%s %llo %s %llo\n", str.c_str(), v, str2.c_str(), v2 ); */
    205287
    206288        //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
     
    214296        } else if ( ltype != -1 ) {                                                     // explicit length ?
    215297                if ( ltype == 6 ) {                                                             // int128, (int128)constant
    216                         ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     298//                      ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     299                        ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) );
     300                        ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
     301                                                                                 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) );
    217302                } else {                                                                                // explicit length, (length_type)constant
    218303                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
     
    342427                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    343428                // lookup type of associated typedef
    344                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char16_t", false );
     429                strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
    345430                break;
    346431          case 'U':
    347                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char32_t", false );
     432                strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
    348433                break;
    349434          case 'L':
    350                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "wchar_t", false );
     435                strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
    351436                break;
    352437          Default:                                                                                      // char default string type
    353438          default:
    354                 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
     439                strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
    355440        } // switch
    356441        ArrayType * at = new ArrayType( noQualifiers, strtype,
  • src/Parser/ParseNode.h

    r07d867b r22f94a4  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  7 17:56:02 2020
    13 // Update Count     : 891
     12// Last Modified On : Mon Jul  6 09:33:32 2020
     13// Update Count     : 892
    1414//
    1515
     
    8686class InitializerNode : public ParseNode {
    8787  public:
    88         InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode * des = nullptr );
     88        InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    8989        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    9090        InitializerNode( bool isDelete );
  • src/Parser/module.mk

    r07d867b r22f94a4  
    1717BUILT_SOURCES = Parser/parser.hh
    1818
    19 AM_YFLAGS = -d -t -v
     19AM_YFLAGS = -d -t -v -Wno-yacc
    2020
    2121SRC += \
  • src/Parser/parser.yy

    r07d867b r22f94a4  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 27 12:25:42 2020
    13 // Update Count     : 4483
     12// Last Modified On : Thu May 28 12:11:45 2020
     13// Update Count     : 4500
    1414//
    1515
     
    329329%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    330330%type<en> comma_expression                              comma_expression_opt
    331 %type<en> argument_expression_list              argument_expression                     default_initialize_opt
     331%type<en> argument_expression_list_opt          argument_expression                     default_initialize_opt
    332332%type<ifctl> if_control_expression
    333333%type<fctl> for_control_expression              for_control_expression_list
     
    624624                // equivalent to the old x[i,j].
    625625                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
    626         | postfix_expression '{' argument_expression_list '}' // CFA, constructor call
     626        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    627627                {
    628628                        Token fn;
     
    630630                        $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    631631                }
    632         | postfix_expression '(' argument_expression_list ')'
     632        | postfix_expression '(' argument_expression_list_opt ')'
    633633                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    634634        | postfix_expression '`' identifier                                     // CFA, postfix call
     
    662662        | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
    663663                { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
    664         | '^' primary_expression '{' argument_expression_list '}' // CFA, destructor call
     664        | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
    665665                {
    666666                        Token fn;
     
    670670        ;
    671671
    672 argument_expression_list:
     672argument_expression_list_opt:
    673673        // empty
    674674                { $$ = nullptr; }
    675675        | argument_expression
    676         | argument_expression_list ',' argument_expression
     676        | argument_expression_list_opt ',' argument_expression
    677677                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    678678        ;
     
    11961196                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    11971197                                                OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1198         | '=' comma_expression                                                                  // CFA
     1198        | '=' comma_expression                                                          // CFA
    11991199                { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12001200                                                OperKinds::LEThan, $2->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     
    12031203        | comma_expression inclexcl comma_expression '~' comma_expression // CFA
    12041204                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); }
     1205        | comma_expression ';'                                                          // CFA
     1206                { $$ = forCtrl( new ExpressionNode( build_constantInteger( *new string( "0u" ) ) ), $1, nullptr, OperKinds::LThan, nullptr, nullptr ); }
    12051207        | comma_expression ';' comma_expression                         // CFA
    12061208                { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12071209                                                OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1208         | comma_expression ';' '=' comma_expression                             // CFA
     1210        | comma_expression ';' '=' comma_expression                     // CFA
    12091211                { $$ = forCtrl( $4, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    12101212                                                OperKinds::LEThan, $4->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
     
    13041306// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
    13051307mutex_statement:
    1306         MUTEX '(' argument_expression_list ')' statement
     1308        MUTEX '(' argument_expression_list_opt ')' statement
    13071309                { SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; }
    13081310        ;
     
    13211323        WAITFOR '(' cast_expression ')'
    13221324                { $$ = $3; }
    1323 //      | WAITFOR '(' cast_expression ',' argument_expression_list ')'
     1325//      | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
    13241326//              { $$ = (ExpressionNode *)$3->set_last( $5 ); }
    1325         | WAITFOR '(' cast_expression_list ':' argument_expression_list ')'
     1327        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
    13261328                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    13271329        ;
     
    13301332        cast_expression
    13311333        | cast_expression_list ',' cast_expression
    1332                 { $$ = (ExpressionNode *)($1->set_last( $3 )); }
     1334                // { $$ = (ExpressionNode *)($1->set_last( $3 )); }
     1335                { SemanticError( yylloc, "List of mutex member is currently unimplemented." ); $$ = nullptr; }
    13331336        ;
    13341337
     
    20952098
    20962099aggregate_control:                                                                              // CFA
    2097         GENERATOR
     2100        MONITOR
     2101                { yyy = true; $$ = AggregateDecl::Monitor; }
     2102        | MUTEX STRUCT
     2103                { yyy = true; $$ = AggregateDecl::Monitor; }
     2104        | GENERATOR
    20982105                { yyy = true; $$ = AggregateDecl::Generator; }
    2099         | MONITOR GENERATOR
     2106        | MUTEX GENERATOR
    21002107                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21012108        | COROUTINE
    21022109                { yyy = true; $$ = AggregateDecl::Coroutine; }
    2103         | MONITOR
    2104                 { yyy = true; $$ = AggregateDecl::Monitor; }
    2105         | MONITOR COROUTINE
     2110        | MUTEX COROUTINE
    21062111                { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21072112        | THREAD
    21082113                { yyy = true; $$ = AggregateDecl::Thread; }
    2109         | MONITOR THREAD
     2114        | MUTEX THREAD
    21102115                { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    21112116        ;
     
    27742779        | attr_name
    27752780                { $$ = DeclarationNode::newAttribute( $1 ); }
    2776         | attr_name '(' argument_expression_list ')'
     2781        | attr_name '(' argument_expression_list_opt ')'
    27772782                { $$ = DeclarationNode::newAttribute( $1, $3 ); }
    27782783        ;
  • src/ResolvExpr/AlternativeFinder.cc

    r07d867b r22f94a4  
    12161216                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12171217                                haveAssertions, openVars, indexer );
    1218                         Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
    1219                                 indexer, alt.env );
     1218                        Cost thisCost =
     1219                                castExpr->isGenerated
     1220                                ? conversionCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),   indexer, alt.env )
     1221                                : castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), indexer, alt.env );
    12201222                        PRINT(
    12211223                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    16981700
    16991701                                // unification run for side-effects
    1700                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1702                                bool canUnify = unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1703                                (void) canUnify;
    17011704                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17021705
    1703                                 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1706                                Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(),
    17041707                                        indexer, newEnv );
     1708
     1709                                PRINT(
     1710                                        Cost legacyCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1711                                                indexer, newEnv );
     1712                                        std::cerr << "Considering initialization:";
     1713                                        std::cerr << std::endl << "  FROM: "; alt.expr->result->print(std::cerr);
     1714                                        std::cerr << std::endl << "  TO: ";   toType          ->print(std::cerr);
     1715                                        std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
     1716                                        std::cerr << std::endl << "  Legacy cost " << legacyCost;
     1717                                        std::cerr << std::endl << "  New cost " << thisCost;
     1718                                        std::cerr << std::endl;
     1719                                )
     1720                               
    17051721                                if ( thisCost != Cost::infinity ) {
    17061722                                        // count one safe conversion for each value that is thrown away
  • src/ResolvExpr/ConversionCost.cc

    r07d867b r22f94a4  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  4 14:45:00 2019
     12// Last Modified On : Wed Jul 29 16:11:00 2020
    1313// Update Count     : 28
    1414//
     
    392392        void ConversionCost::postvisit( const FunctionType * ) {}
    393393
    394         void ConversionCost::postvisit( const StructInstType * inst ) {
    395                 /*
    396                 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
    397                         if ( inst->name == destAsInst->name ) {
    398                                 cost = Cost::zero;
    399                         } // if
    400                 } // if
    401                 */
    402         }
    403 
    404         void ConversionCost::postvisit( const UnionInstType * inst ) {
    405                 /*
    406                 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
    407                         if ( inst->name == destAsInst->name ) {
    408                                 cost = Cost::zero;
    409                         } // if
    410                 } // if
    411                 */
    412         }
    413 
    414394        void ConversionCost::postvisit( const EnumInstType * ) {
    415395                static Type::Qualifiers q;
     
    685665}
    686666
    687 void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
    688         /*
    689         if ( const ast::StructInstType * dstAsInst =
    690                         dynamic_cast< const ast::StructInstType * >( dst ) ) {
    691                 if ( structInstType->name == dstAsInst->name ) {
    692                         cost = Cost::zero;
    693                 }
    694         }
    695         */
    696 }
    697 
    698 void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
    699         /*
    700         if ( const ast::UnionInstType * dstAsInst =
    701                         dynamic_cast< const ast::UnionInstType * >( dst ) ) {
    702                 if ( unionInstType->name == dstAsInst->name ) {
    703                         cost = Cost::zero;
    704                 }
    705         }
    706         */
    707 }
    708 
    709667void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    710668        (void)enumInstType;
  • src/ResolvExpr/ConversionCost.h

    r07d867b r22f94a4  
    1010// Created On       : Sun May 17 09:37:28 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  4 14:59:00 2019
     12// Last Modified On : Wed Jul 29 16:12:00 2020
    1313// Update Count     : 7
    1414//
     
    5151                void postvisit( const ReferenceType * refType );
    5252                void postvisit( const FunctionType * functionType );
    53                 void postvisit( const StructInstType * aggregateUseType );
    54                 void postvisit( const UnionInstType * aggregateUseType );
    5553                void postvisit( const EnumInstType * aggregateUseType );
    5654                void postvisit( const TraitInstType * aggregateUseType );
     
    105103        void postvisit( const ast::ReferenceType * refType );
    106104        void postvisit( const ast::FunctionType * functionType );
    107         void postvisit( const ast::StructInstType * structInstType );
    108         void postvisit( const ast::UnionInstType * unionInstType );
    109105        void postvisit( const ast::EnumInstType * enumInstType );
    110106        void postvisit( const ast::TraitInstType * traitInstType );
  • src/SynTree/Expression.h

    r07d867b r22f94a4  
    206206  public:
    207207        Expression * arg;
    208         bool isGenerated = true; // cast generated implicitly by code generation or explicit in program
     208
     209        // Inidicates cast is introduced by the CFA type system.
     210        // true for casts that the resolver introduces to force a return type
     211        // false for casts from user code
     212        // false for casts from desugaring advanced CFA features into simpler CFA
     213        // example
     214        //   int * p;     // declaration
     215        //   (float *) p; // use, with subject cast
     216        // subject cast isGenerated means we are considering an interpretation with a type mismatch
     217        // subject cast not isGenerated means someone in charge wants it that way
     218        bool isGenerated = true;
    209219
    210220        CastExpr( Expression * arg, bool isGenerated = true );
  • src/Virtual/ExpandCasts.cc

    r07d867b r22f94a4  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Aug  2 14:59:00 2017
    13 // Update Count     : 1
     12// Last Modified On : Fri Jul 31 10:29:00 2020
     13// Update Count     : 4
    1414//
    1515
     
    1818#include <cassert>                 // for assert, assertf
    1919#include <iterator>                // for back_inserter, inserter
    20 #include <map>                     // for map, _Rb_tree_iterator, map<>::ite...
    2120#include <string>                  // for string, allocator, operator==, ope...
    22 #include <utility>                 // for pair
    2321
    2422#include "Common/PassVisitor.h"    // for PassVisitor
     23#include "Common/ScopedMap.h"      // for ScopedMap
    2524#include "Common/SemanticError.h"  // for SemanticError
     25#include "SymTab/Mangler.h"        // for mangleType
    2626#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2727#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3131
    3232namespace Virtual {
     33
     34        // Indented until the new ast code gets added.
     35
     36        /// Maps virtual table types the instance for that type.
     37        class VirtualTableMap final {
     38                ScopedMap<std::string, ObjectDecl *> vtable_instances;
     39        public:
     40                void enterScope() {
     41                        vtable_instances.beginScope();
     42                }
     43                void leaveScope() {
     44                        vtable_instances.endScope();
     45                }
     46
     47                ObjectDecl * insert( ObjectDecl * vtableDecl ) {
     48                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
     49                        ObjectDecl *& value = vtable_instances[ mangledName ];
     50                        if ( value ) {
     51                                if ( vtableDecl->storageClasses.is_extern ) {
     52                                        return nullptr;
     53                                } else if ( ! value->storageClasses.is_extern ) {
     54                                        return value;
     55                                }
     56                        }
     57                        value = vtableDecl;
     58                        return nullptr;
     59                }
     60
     61                ObjectDecl * lookup( const Type * vtableType ) {
     62                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
     63                        const auto it = vtable_instances.find( mangledName );
     64                        return ( vtable_instances.end() == it ) ? nullptr : it->second;
     65                }
     66        };
    3367
    3468        /* Currently virtual depends on the rather brittle name matching between
     
    3973         */
    4074
     75        namespace {
     76
    4177        std::string get_vtable_name( std::string const & name ) {
    4278                return name + "_vtable";
     
    5389        std::string get_vtable_inst_name_root( std::string const & name ) {
    5490                return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
    55         }
    56 
    57         bool is_vtable_name( std::string const & name ) {
    58                 return (name.substr( name.size() - 7 ) == "_vtable" );
    5991        }
    6092
     
    6496        }
    6597
     98        } // namespace
     99
    66100        class VirtualCastCore {
    67         std::map<std::string, ObjectDecl *> vtable_instances;
    68         FunctionDecl *vcast_decl;
    69         StructDecl *pvt_decl;
    70 
    71101                Type * pointer_to_pvt(int level_of_indirection) {
    72102                        Type * type = new StructInstType(
     
    80110        public:
    81111                VirtualCastCore() :
    82                         vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr )
     112                        indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
    83113                {}
    84114
     
    88118
    89119                Expression * postmutate( VirtualCastExpr * castExpr );
     120
     121                VirtualTableMap indexer;
     122        private:
     123                FunctionDecl *vcast_decl;
     124                StructDecl *pvt_decl;
    90125        };
    91126
     
    107142        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    108143                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    109                         vtable_instances[objectDecl->get_name()] = objectDecl;
    110                 }
    111         }
     144                        if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) {
     145                                std::string msg = "Repeated instance of virtual table, original found at: ";
     146                                msg += existing->location.filename;
     147                                msg += ":" + toString( existing->location.first_line );
     148                                SemanticError( objectDecl->location, msg );
     149                        }
     150                }
     151        }
     152
     153        namespace {
     154
     155        /// Better error locations for generated casts.
     156        CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
     157                if ( castExpr->location.isSet() ) {
     158                        return castExpr->location;
     159                } else if ( castExpr->arg->location.isSet() ) {
     160                        return castExpr->arg->location;
     161                } else if ( castExpr->result->location.isSet() ) {
     162                        return castExpr->result->location;
     163                } else {
     164                        return CodeLocation();
     165                }
     166        }
     167
     168        [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
     169                SemanticError( castLocation( castExpr ), message );
     170        }
     171
     172        /// Get the virtual table type used in a virtual cast.
     173        Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
     174                const Type * objectType;
     175                if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
     176                        objectType = target->base;
     177                } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
     178                        objectType = target->base;
     179                } else {
     180                        castError( castExpr, "Virtual cast type must be a pointer or reference type." );
     181                }
     182                assert( objectType );
     183
     184                const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
     185                if ( nullptr == structType ) {
     186                        castError( castExpr, "Virtual cast type must refer to a structure type." );
     187                }
     188                const StructDecl * structDecl = structType->baseStruct;
     189                assert( structDecl );
     190
     191                const ObjectDecl * fieldDecl = nullptr;
     192                if ( 0 < structDecl->members.size() ) {
     193                        const Declaration * memberDecl = structDecl->members.front();
     194                        assert( memberDecl );
     195                        fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     196                        if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
     197                                fieldDecl = nullptr;
     198                        }
     199                }
     200                if ( nullptr == fieldDecl ) {
     201                        castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
     202                }
     203                const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
     204                if ( nullptr == fieldType ) {
     205                        castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
     206                }
     207                assert( fieldType->base );
     208                auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
     209                assert( virtualStructType );
     210
     211                // Here is the type, but if it is polymorphic it will have lost information.
     212                // (Always a clone so that it may always be deleted.)
     213                StructInstType * virtualType = virtualStructType->clone();
     214                if ( ! structType->parameters.empty() ) {
     215                        deleteAll( virtualType->parameters );
     216                        virtualType->parameters.clear();
     217                        cloneAll( structType->parameters, virtualType->parameters );
     218                }
     219                return virtualType;
     220        }
     221
     222        } // namespace
    112223
    113224        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    114                 assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
     225                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    115226
    116227                assert( vcast_decl );
    117228                assert( pvt_decl );
    118229
    119                 // May only cast to a pointer or reference type.
    120                 // A earlier validation should give a syntax error, this is
    121                 // just to make sure errors don't creep during translation.
    122                 // Move to helper with more detailed error messages.
    123                 PointerType * target_type =
    124                         dynamic_cast<PointerType *>( castExpr->get_result() );
    125                 assert( target_type );
    126 
    127                 StructInstType * target_struct =
    128                         dynamic_cast<StructInstType *>( target_type->get_base() );
    129                 assert( target_struct );
    130 
    131                 StructDecl * target_decl = target_struct->get_baseStruct();
    132 
    133                 std::map<std::string, ObjectDecl *>::iterator found =
    134                         vtable_instances.find(
    135                                 get_vtable_inst_name( target_decl->get_name() ) );
    136                 if ( vtable_instances.end() == found ) {
    137                         assertf( false, "virtual table instance not found." );
    138                 }
    139                 ObjectDecl * table = found->second;
     230                const Type * vtable_type = getVirtualTableType( castExpr );
     231                ObjectDecl * table = indexer.lookup( vtable_type );
     232                if ( nullptr == table ) {
     233                        SemanticError( castLocation( castExpr ),
     234                                "Could not find virtual table instance." );
     235                }
    140236
    141237                Expression * result = new CastExpr(
    142                         //new ApplicationExpr(
    143                                 //new AddressExpr( new VariableExpr( vcast_decl ) ),
    144                                 //new CastExpr( new VariableExpr( vcast_decl ),
    145                                 //      new PointerType( noQualifiers,
    146                                 //              vcast_decl->get_type()->clone()
    147                                 //              )
    148                                 //      ),
    149238                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    150239                                        new CastExpr(
     
    163252                castExpr->set_result( nullptr );
    164253                delete castExpr;
     254                delete vtable_type;
    165255                return result;
    166256        }
  • src/main.cc

    r07d867b r22f94a4  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb  8 08:33:50 2020
    13 // Update Count     : 633
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue May 19 12:03:00 2020
     13// Update Count     : 634
    1414//
    1515
     
    312312                } // if
    313313
     314                PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    314315                PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    315316                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     
    360361                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    361362
    362                 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );
     363                PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    363364
    364365                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
Note: See TracChangeset for help on using the changeset viewer.