Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    rb3b2077 r9facf3b  
    6161#include <algorithm>
    6262#include "InitTweak/InitTweak.h"
     63#include "CodeGen/CodeGenerator.h"
    6364
    6465#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
    6566
    6667namespace SymTab {
    67         class HoistStruct : public Visitor {
     68        class HoistStruct final : public Visitor {
    6869          public:
    6970                /// Flattens nested struct types
     
    8687        };
    8788
     89        /// Fix return types so that every function returns exactly one value
     90        class ReturnTypeFixer final : public Visitor {
     91          public:
     92
     93                typedef Visitor Parent;
     94                using Parent::visit;
     95
     96                static void fix( std::list< Declaration * > &translationUnit );
     97
     98                virtual void visit( FunctionDecl * functionDecl );
     99
     100                virtual void visit( FunctionType * ftype );
     101        };
     102
    88103        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    89         class EnumAndPointerDecayPass : public Visitor {
     104        class EnumAndPointerDecayPass final : public Visitor {
    90105                typedef Visitor Parent;
    91106                virtual void visit( EnumDecl *aggregateDecl );
     
    94109
    95110        /// Associates forward declarations of aggregates with their definitions
    96         class Pass2 : public Indexer {
     111        class LinkReferenceToTypes final : public Indexer {
    97112                typedef Indexer Parent;
    98113          public:
    99                 Pass2( bool doDebug, const Indexer *indexer );
     114                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    100115          private:
    101                 virtual void visit( StructInstType *structInst );
    102                 virtual void visit( UnionInstType *unionInst );
    103                 virtual void visit( TraitInstType *contextInst );
    104                 virtual void visit( StructDecl *structDecl );
    105                 virtual void visit( UnionDecl *unionDecl );
    106                 virtual void visit( TypeInstType *typeInst );
     116                using Indexer::visit;
     117                void visit( StructInstType *structInst ) final;
     118                void visit( UnionInstType *unionInst ) final;
     119                void visit( TraitInstType *contextInst ) final;
     120                void visit( StructDecl *structDecl ) final;
     121                void visit( UnionDecl *unionDecl ) final;
     122                void visit( TypeInstType *typeInst ) final;
    107123
    108124                const Indexer *indexer;
     
    182198        };
    183199
    184         class CompoundLiteral : public GenPoly::DeclMutator {
     200        class CompoundLiteral final : public GenPoly::DeclMutator {
    185201                DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass;
    186202
    187                 virtual DeclarationWithType * mutate( ObjectDecl *objectDecl );
    188                 virtual Expression *mutate( CompoundLiteralExpr *compLitExpr );
     203                using GenPoly::DeclMutator::mutate;
     204                DeclarationWithType * mutate( ObjectDecl *objectDecl ) final;
     205                Expression *mutate( CompoundLiteralExpr *compLitExpr ) final;
    189206        };
    190207
    191208        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    192209                EnumAndPointerDecayPass epc;
    193                 Pass2 pass2( doDebug, 0 );
     210                LinkReferenceToTypes lrt( doDebug, 0 );
    194211                Pass3 pass3( 0 );
    195212                CompoundLiteral compoundliteral;
     
    197214                EliminateTypedef::eliminateTypedef( translationUnit );
    198215                HoistStruct::hoistStruct( translationUnit );
     216                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    199217                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
    200218                acceptAll( translationUnit, epc );
    201                 acceptAll( translationUnit, pass2 );
     219                acceptAll( translationUnit, lrt );
    202220                ReturnChecker::checkFunctionReturns( translationUnit );
    203221                compoundliteral.mutateDeclarationList( translationUnit );
     
    208226        void validateType( Type *type, const Indexer *indexer ) {
    209227                EnumAndPointerDecayPass epc;
    210                 Pass2 pass2( false, indexer );
     228                LinkReferenceToTypes lrt( false, indexer );
    211229                Pass3 pass3( indexer );
    212230                type->accept( epc );
    213                 type->accept( pass2 );
     231                type->accept( lrt );
    214232                type->accept( pass3 );
    215233        }
     
    322340        }
    323341
    324         Pass2::Pass2( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
     342        LinkReferenceToTypes::LinkReferenceToTypes( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
    325343                if ( other_indexer ) {
    326344                        indexer = other_indexer;
     
    330348        }
    331349
    332         void Pass2::visit( StructInstType *structInst ) {
     350        void LinkReferenceToTypes::visit( StructInstType *structInst ) {
    333351                Parent::visit( structInst );
    334352                StructDecl *st = indexer->lookupStruct( structInst->get_name() );
     
    344362        }
    345363
    346         void Pass2::visit( UnionInstType *unionInst ) {
     364        void LinkReferenceToTypes::visit( UnionInstType *unionInst ) {
    347365                Parent::visit( unionInst );
    348366                UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
     
    357375        }
    358376
    359         void Pass2::visit( TraitInstType *contextInst ) {
     377        void LinkReferenceToTypes::visit( TraitInstType *contextInst ) {
    360378                Parent::visit( contextInst );
     379                if ( contextInst->get_name() == "sized" ) {
     380                        // "sized" is a special trait with no members - just flick the sized status on for the type variable
     381                        if ( contextInst->get_parameters().size() != 1 ) {
     382                                throw SemanticError( "incorrect number of context parameters: ", contextInst );
     383                        }
     384                        TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( contextInst->get_parameters().front() );
     385                        TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
     386                        TypeDecl * decl = inst->get_baseType();
     387                        decl->set_sized( true );
     388                        // since "sized" is special, the next few steps don't apply
     389                        return;
     390                }
    361391                TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );
    362392                if ( ! ctx ) {
     
    384414        }
    385415
    386         void Pass2::visit( StructDecl *structDecl ) {
     416        void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
    387417                // visit struct members first so that the types of self-referencing members are updated properly
    388418                Parent::visit( structDecl );
     
    398428        }
    399429
    400         void Pass2::visit( UnionDecl *unionDecl ) {
     430        void LinkReferenceToTypes::visit( UnionDecl *unionDecl ) {
    401431                Parent::visit( unionDecl );
    402432                if ( ! unionDecl->get_members().empty() ) {
     
    411441        }
    412442
    413         void Pass2::visit( TypeInstType *typeInst ) {
     443        void LinkReferenceToTypes::visit( TypeInstType *typeInst ) {
    414444                if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
    415445                        if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
     
    582612
    583613                typedeclNames[ typeDecl->get_name() ] = typeDecl;
    584                 return typeDecl;
     614                return Mutator::mutate( typeDecl );
    585615        }
    586616
     
    652682        void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
    653683                if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
    654                         Type *type;
     684                        Type *type = nullptr;
    655685                        if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) {
    656686                                type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() );
     
    733763                return new VariableExpr( newtempvar );
    734764        }
     765
     766        void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
     767                ReturnTypeFixer fixer;
     768                acceptAll( translationUnit, fixer );
     769        }
     770
     771        void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) {
     772                Parent::visit( functionDecl );
     773                FunctionType * ftype = functionDecl->get_functionType();
     774                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     775                assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %d", functionDecl->get_name().c_str(), retVals.size() );
     776                if ( retVals.size() == 1 ) {
     777                        // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging)
     778                        // ensure other return values have a name
     779                        DeclarationWithType * ret = retVals.front();
     780                        if ( ret->get_name() == "" ) {
     781                                ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) );
     782                        }
     783                }
     784        }
     785
     786        void ReturnTypeFixer::visit( FunctionType * ftype ) {
     787                // xxx - need to handle named return values - this information needs to be saved somehow
     788                // so that resolution has access to the names.
     789                // Note that this pass needs to happen early so that other passes which look for tuple types
     790                // find them in all of the right places, including function return types.
     791                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     792                if ( retVals.size() > 1 ) {
     793                        // generate a single return parameter which is the tuple of all of the return values
     794                        TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
     795                        // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
     796                        ObjectDecl * newRet = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
     797                        deleteAll( retVals );
     798                        retVals.clear();
     799                        retVals.push_back( newRet );
     800                }
     801        }
    735802} // namespace SymTab
    736803
Note: See TracChangeset for help on using the changeset viewer.