Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    rd3b7937 r98735ef  
    382382                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    383383                if ( st ) {
    384                         assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
     384                        //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
    385385                        structInst->set_baseStruct( st );
    386386                } // if
     
    585585        }
    586586
     587        template< typename OutputIterator >
     588        void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
     589                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
     590                copy->get_args().push_back( new VariableExpr( dstParam ) );
     591                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
     592                copy->get_args().push_back( new SizeofExpr( unionType ) );
     593
     594                *out++ = new ExprStmt( noLabels, copy );
     595        }
     596
    587597        //E ?=?(E volatile*, int),
    588598        //  ?=?(E _Atomic volatile*, int);
     
    649659        }
    650660
     661        /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
     662        TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
     663                TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
     664
     665                if ( src->get_kind() == TypeDecl::Any ) {
     666                        // just include assignment operator assertion
     667                        TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
     668                        FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
     669                        assignFunctionType->get_returnVals().push_back(
     670                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
     671                        assignFunctionType->get_parameters().push_back(
     672                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
     673                        assignFunctionType->get_parameters().push_back(
     674                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
     675                        FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
     676                        dst->get_assertions().push_back( assignAssert );
     677                }
     678
     679                return dst;
     680        }
     681
    651682        Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    652683                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    653684
    654685                // Make function polymorphic in same parameters as generic struct, if applicable
     686                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    655687                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    656688                std::list< Expression* > structParams;  // List of matching parameters to put on types
     689                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    657690                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    658                         TypeDecl *typeParam = (*param)->clone();
     691                        isGeneric = true;
     692                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    659693                        assignType->get_forall().push_back( typeParam );
    660                         structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     694                        TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
     695                        genericSubs.add( (*param)->get_name(), newParamType );
     696                        structParams.push_back( new TypeExpr( newParamType ) );
    661697                }
    662698
    663                 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     699                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    664700                assignType->get_returnVals().push_back( returnVal );
    665701
     
    689725                                }
    690726
    691                                 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
    692                                         makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     727                                if ( isGeneric ) {
     728                                        // rewrite member type in terms of the type variables on this operator
     729                                        DeclarationWithType *fixedMember = dwt->clone();
     730                                        genericSubs.apply( fixedMember );
     731
     732                                        // assign to both destination and return value
     733                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
     734                                                makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     735                                                makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     736                                        } else {
     737                                                makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
     738                                                makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
     739                                        } // if
    693740                                } else {
    694                                         makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     741                                        // assign to destination
     742                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
     743                                                makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     744                                        } else {
     745                                                makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     746                                        } // if
    695747                                } // if
    696748                        } // if
    697749                } // for
    698                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     750                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    699751
    700752                return assignDecl;
     
    705757
    706758                // Make function polymorphic in same parameters as generic union, if applicable
     759                bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    707760                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    708761                std::list< Expression* > unionParams;  // List of matching parameters to put on types
    709762                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    710                         TypeDecl *typeParam = (*param)->clone();
     763                        isGeneric = true;
     764                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    711765                        assignType->get_forall().push_back( typeParam );
    712766                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    713767                }
    714768
    715                 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
     769                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    716770                assignType->get_returnVals().push_back( returnVal );
    717771
     
    727781                assignDecl->fixUniqueId();
    728782
    729                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    730                 copy->get_args().push_back( new VariableExpr( dstParam ) );
    731                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    732                 copy->get_args().push_back( new SizeofExpr( cloneWithParams( refType, unionParams ) ) );
    733 
    734                 assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
    735                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     783                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
     784                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
     785               
     786                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    736787
    737788                return assignDecl;
Note: See TracChangeset for help on using the changeset viewer.