Changes in / [bd46af4:8217e8f]


Ignore:
Location:
src
Files:
1 added
120 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rbd46af4 r8217e8f  
    182182                        genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
    183183                        output << ")" << endl;
     184                        output << indent;
    184185                }
    185186
     
    321322        void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){
    322323                assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
    323                 // xxx - generate something reasonable for constructor/destructor pairs
    324                 output << "<ctorinit>";
     324                // pseudo-output for constructor/destructor pairs
     325                output << "<ctorinit>{" << std::endl << ++indent << "ctor: ";
     326                maybeAccept( init->get_ctor(), *this );
     327                output << ", " << std::endl << indent << "dtor: ";
     328                maybeAccept( init->get_dtor(), *this );
     329                output << std::endl << --indent << "}";
    325330        }
    326331
     
    336341                        if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) {
    337342                                std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
    338                                 switch ( opInfo.type ) {
    339                                   case OT_PREFIXASSIGN:
    340                                   case OT_POSTFIXASSIGN:
    341                                   case OT_INFIXASSIGN:
    342                                   case OT_CTOR:
    343                                   case OT_DTOR:
    344                                         {
    345                                                 assert( arg != applicationExpr->get_args().end() );
    346                                                 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
    347                                                         // remove & from first assignment/ctor argument
    348                                                         *arg = addrExpr->get_arg();
    349                                                 } else {
    350                                                         // no address-of operator, so must be a pointer - add dereference
    351                                                         // NOTE: if the assertion starts to trigger, check that the application expr isn't being shared.
    352                                                         // Since its arguments are modified here, this assertion most commonly triggers when the application
    353                                                         // is visited multiple times.
    354                                                         UntypedExpr * newExpr = new UntypedExpr( new NameExpr( "*?" ) );
    355                                                         newExpr->get_args().push_back( *arg );
    356                                                         Type * type = InitTweak::getPointerBase( (*arg)->get_result() );
    357                                                         assertf( type, "First argument to a derefence must be a pointer. Ensure that expressions are not being shared." );
    358                                                         newExpr->set_result( type->clone() );
    359                                                         *arg = newExpr;
    360                                                 } // if
    361                                                 break;
    362                                         }
    363 
    364                                   default:
    365                                         // do nothing
    366                                         ;
    367                                 } // switch
    368 
    369343                                switch ( opInfo.type ) {
    370344                                  case OT_INDEX:
     
    695669                extension( commaExpr );
    696670                output << "(";
     671                if ( genC ) {
     672                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
     673                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     674                }
    697675                commaExpr->get_arg1()->accept( *this );
    698676                output << " , ";
     
    758736                for ( Statement * stmt : stmts ) {
    759737                        output << lineDirective( stmt ) << indent;
    760             output << printLabels( stmt->get_labels() );
     738                        output << printLabels( stmt->get_labels() );
    761739                        if ( i+1 == numStmts ) {
    762740                                // last statement in a statement expression needs to be handled specially -
     
    803781        void CodeGenerator::visit( ExprStmt * exprStmt ) {
    804782                assert( exprStmt );
    805                 Expression * expr = exprStmt->get_expr();
    806783                if ( genC ) {
    807784                        // cast the top-level expression to void to reduce gcc warnings.
    808                         expr = new CastExpr( expr );
    809                 }
    810                 expr->accept( *this );
     785                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     786                }
     787                exprStmt->get_expr()->accept( *this );
    811788                output << ";";
    812789        }
  • src/CodeGen/CodeGenerator.h

    rbd46af4 r8217e8f  
    1919#include <ostream>                // for ostream, operator<<
    2020#include <string>                 // for string
     21
     22#include "Common/Indenter.h"      // for Indenter
    2123
    2224#include "SynTree/Declaration.h"  // for DeclarationWithType (ptr only), Fun...
  • src/CodeGen/GenType.cc

    rbd46af4 r8217e8f  
    3737                virtual void visit( PointerType *pointerType );
    3838                virtual void visit( ArrayType *arrayType );
     39                virtual void visit( ReferenceType *refType );
    3940                virtual void visit( StructInstType *structInst );
    4041                virtual void visit( UnionInstType *unionInst );
     
    147148        }
    148149
     150        void GenType::visit( ReferenceType *refType ) {
     151                assert( refType->get_base() != 0);
     152                assertf( ! genC, "Reference types should not reach code generation." );
     153                handleQualifiers( refType );
     154                typeString = "&" + typeString;
     155                refType->get_base()->accept( *this );
     156        }
     157
    149158        void GenType::visit( FunctionType *funcType ) {
    150159                std::ostringstream os;
  • src/CodeGen/OperatorTable.cc

    rbd46af4 r8217e8f  
    1414//
    1515
    16 #include <map>      // for map, _Rb_tree_const_iterator, map<>::const_iterator
    17 #include <utility>  // for pair
     16#include <algorithm>  // for any_of
     17#include <map>        // for map, _Rb_tree_const_iterator, map<>::const_iterator
     18#include <utility>    // for pair
    1819
    1920#include "OperatorTable.h"
     
    9394                } // if
    9495        }
     96
     97        /// determines if a given function name is one of the operator types between [begin, end)
     98        template<typename Iterator>
     99        bool isOperatorType( const std::string & funcName, Iterator begin, Iterator end ) {
     100                OperatorInfo info;
     101                if ( operatorLookup( funcName, info ) ) {
     102                        return std::find( begin, end, info.type ) != end;
     103                }
     104                return false;
     105        }
     106
     107        bool isConstructor( const std::string & funcName ) {
     108                static OperatorType types[] = { OT_CTOR };
     109                return isOperatorType( funcName, std::begin(types), std::end(types) );
     110        }
     111
     112        bool isDestructor( const std::string & funcName ) {
     113                static OperatorType types[] = { OT_DTOR };
     114                return isOperatorType( funcName, std::begin(types), std::end(types) );
     115        }
     116
     117        bool isAssignment( const std::string & funcName ) {
     118                static OperatorType types[] = { OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN };
     119                return isOperatorType( funcName, std::begin(types), std::end(types) );
     120        }
     121
     122        bool isCtorDtor( const std::string & funcName ) {
     123                static OperatorType types[] = { OT_CTOR, OT_DTOR };
     124                return isOperatorType( funcName, std::begin(types), std::end(types) );
     125        }
     126
     127        bool isCtorDtorAssign( const std::string & funcName ) {
     128                static OperatorType types[] = { OT_CTOR, OT_DTOR, OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN };
     129                return isOperatorType( funcName, std::begin(types), std::end(types) );
     130        }
    95131} // namespace CodeGen
    96132
  • src/CodeGen/OperatorTable.h

    rbd46af4 r8217e8f  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // OperatorTable.h -- 
     7// OperatorTable.h --
    88//
    99// Author           : Richard C. Bilson
     
    4242
    4343        bool operatorLookup( std::string funcName, OperatorInfo &info );
     44
     45        bool isConstructor( const std::string & );
     46        bool isDestructor( const std::string & );
     47        bool isAssignment( const std::string & );
     48        bool isCtorDtor( const std::string & );
     49        bool isCtorDtorAssign( const std::string & );
    4450} // namespace CodeGen
    4551
  • src/Common/PassVisitor.h

    rbd46af4 r8217e8f  
    114114        virtual void visit( PointerType *pointerType ) override final;
    115115        virtual void visit( ArrayType *arrayType ) override final;
     116        virtual void visit( ReferenceType *referenceType ) override final;
    116117        virtual void visit( FunctionType *functionType ) override final;
    117118        virtual void visit( StructInstType *aggregateUseType ) override final;
     
    200201        virtual Type* mutate( PointerType *pointerType ) override final;
    201202        virtual Type* mutate( ArrayType *arrayType ) override final;
     203        virtual Type* mutate( ReferenceType *referenceType ) override final;
    202204        virtual Type* mutate( FunctionType *functionType ) override final;
    203205        virtual Type* mutate( StructInstType *aggregateUseType ) override final;
  • src/Common/PassVisitor.impl.h

    rbd46af4 r8217e8f  
    792792
    793793template< typename pass_type >
     794void PassVisitor< pass_type >::visit( ReferenceType * node ) {
     795        VISIT_BODY( node );
     796}
     797
     798template< typename pass_type >
    794799void PassVisitor< pass_type >::visit( FunctionType * node ) {
    795800        VISIT_BODY( node );
     
    11291134
    11301135template< typename pass_type >
     1136Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
     1137        MUTATE_BODY( Type, node );
     1138}
     1139
     1140template< typename pass_type >
    11311141Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
    11321142        MUTATE_BODY( Type, node );
  • src/Common/utility.h

    rbd46af4 r8217e8f  
    309309template< typename T1, typename T2 >
    310310struct group_iterate_t {
    311         group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {
    312                 assertf(v1.size() == v2.size(), "group iteration requires containers of the same size.");
     311        group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) {
     312                assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%lu, %lu>.", v1.size(), v2.size());
    313313        };
    314314
     
    335335};
    336336
     337/// performs bounds check to ensure that all arguments are of the same length.
    337338template< typename... Args >
    338339group_iterate_t<Args...> group_iterate( Args &&... args ) {
    339         return group_iterate_t<Args...>(std::forward<Args>( args )...);
     340        return group_iterate_t<Args...>(false, std::forward<Args>( args )...);
     341}
     342
     343/// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
     344template< typename... Args >
     345group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
     346        return group_iterate_t<Args...>(true, std::forward<Args>( args )...);
    340347}
    341348
  • src/Concurrency/Keywords.cc

    rbd46af4 r8217e8f  
    2121#include "Common/SemanticError.h"  // for SemanticError
    2222#include "Common/utility.h"        // for deleteAll, map_range
    23 #include "InitTweak/InitTweak.h"   // for isConstructor
     23#include "CodeGen/OperatorTable.h" // for isConstructor
     24#include "InitTweak/InitTweak.h"   // for getPointerBase
    2425#include "Parser/LinkageSpec.h"    // for Cforall
    2526#include "SymTab/AddVisit.h"       // for acceptAndAdd
     
    289290                        LinkageSpec::Cforall,
    290291                        nullptr,
    291                         new PointerType(
     292                        new ReferenceType(
    292293                                noQualifiers,
    293294                                new StructInstType(
     
    445446
    446447                //Makes sure it's not a copy
    447                 PointerType* pty = dynamic_cast< PointerType * >( ty );
    448                 if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
     448                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
     449                if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg );
    449450
    450451                //Make sure the we are pointing directly to a type
    451                 Type* base = pty->get_base();
    452                 if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
     452                Type* base = rty->get_base();
     453                if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
     454                if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
    453455
    454456                //Make sure that typed isn't mutex
     
    520522                Visitor::visit(decl);
    521523
    522                 if( ! InitTweak::isConstructor(decl->get_name()) ) return;
     524                if( ! CodeGen::isConstructor(decl->get_name()) ) return;
    523525
    524526                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
    525                 auto ptr = dynamic_cast< PointerType * >( param->get_type() );
    526                 // if( ptr ) std::cerr << "FRED1" << std::endl;
    527                 auto type  = dynamic_cast< StructInstType * >( ptr->get_base() );
     527                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
    528528                // if( type ) std::cerr << "FRED2" << std::endl;
    529529                if( type && type->get_baseStruct()->is_thread() ) {
  • src/GenPoly/Box.cc

    rbd46af4 r8217e8f  
    5656#include "Common/UniqueName.h"
    5757#include "Common/utility.h"
     58
     59#include "CodeGen/OperatorTable.h"
    5860
    5961#include "InitTweak/InitTweak.h"
     
    570572                        // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
    571573                        if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
    572                                 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
     574                                if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
    573575                                        assert( assign->get_args().size() == 2 );
    574576                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
     
    610612                                                }
    611613                                        } else {
    612                                                 throw SemanticError( "Cannot pass non-struct type for generic struct" );
     614                                                throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
    613615                                        }
    614616                                }
     
    10251027                                                } // if
    10261028                                                if ( baseType1 || baseType2 ) {
     1029                                                        delete ret->get_result();
    10271030                                                        ret->set_result( appExpr->get_result()->clone() );
    10281031                                                        if ( appExpr->get_env() ) {
     
    10381041                                                assert( ! appExpr->get_args().empty() );
    10391042                                                if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
     1043                                                        // remove dereference from polymorphic types since they are boxed.
    10401044                                                        Expression *ret = appExpr->get_args().front();
     1045                                                        // fix expr type to remove pointer
    10411046                                                        delete ret->get_result();
    10421047                                                        ret->set_result( appExpr->get_result()->clone() );
     
    11281133
    11291134                        assert( appExpr->get_function()->has_result() );
    1130                         PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
    1131                         FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
     1135                        FunctionType * function = getFunctionType( appExpr->get_function()->get_result() );
     1136                        assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() );
    11321137
    11331138                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
     
    12061211                                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
    12071212                                                                assert( appExpr->get_function()->has_result() );
    1208                                                                 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
    1209                                                                 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
     1213                                                                FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
     1214                                                                assert( function );
    12101215                                                                needs = needsAdapter( function, scopeTyVars );
    12111216                                                        } // if
     
    12161221                        // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
    12171222                        // out of the if condition.
     1223                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
     1224                        // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
    12181225                        bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
    1219                         addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
    12201226                        if ( polytype || needs ) {
    12211227                                Expression *ret = addrExpr->get_arg();
     
    12841290                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    12851291                                        std::string adapterName = makeAdapterName( mangleName );
    1286                                         paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) );
     1292                                        // adapter may not be used in body, pass along with unused attribute.
     1293                                        paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
    12871294                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
    12881295                                }
     
    13901397                        std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
    13911398                        std::list< DeclarationWithType *> inferredParams;
    1392                         ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
     1399                        // size/align/offset parameters may not be used in body, pass along with unused attribute.
     1400                        ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0,
     1401                                           { new Attribute( "unused" ) } );
    13931402                        ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
    13941403                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
     
    14131422                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
    14141423//      *assert = (*assert)->acceptMutator( *this );
     1424                                        // assertion parameters may not be used in body, pass along with unused attribute.
     1425                                        (*assert)->get_attributes().push_back( new Attribute( "unused" ) );
    14151426                                        inferredParams.push_back( *assert );
    14161427                                }
  • src/GenPoly/Lvalue.cc

    rbd46af4 r8217e8f  
    2727#include "SynTree/Mutator.h"
    2828#include "SymTab/Indexer.h"
     29#include "SymTab/Autogen.h"
    2930
    3031#include "ResolvExpr/Resolver.h"
     
    3536#include "Common/UniqueName.h"
    3637#include "Common/utility.h"
     38#include "Common/PassVisitor.h"
     39
     40#include "InitTweak/InitTweak.h"
     41
     42#if 0
     43#define PRINT(x) x
     44#else
     45#define PRINT(x)
     46#endif
    3747
    3848namespace GenPoly {
    3949        namespace {
    40                 /// Replace uses of lvalue returns with appropriate pointers
    41                 class Pass1 : public Mutator {
    42                   public:
    43                         Pass1();
    44 
    45                         virtual Expression *mutate( ApplicationExpr *appExpr );
    46                         virtual Statement *mutate( ReturnStmt *appExpr );
    47                         virtual DeclarationWithType *mutate( FunctionDecl *funDecl );
    48                   private:
    49                         DeclarationWithType* retval;
    50                 };
    51 
    52                 /// Replace declarations of lvalue returns with appropriate pointers
    53                 class Pass2 : public Visitor {
    54                   public:
    55                         virtual void visit( FunctionType *funType );
    56                   private:
     50                // TODO: fold this into the general createDeref function??
     51                Expression * mkDeref( Expression * arg ) {
     52                        if ( SymTab::dereferenceOperator ) {
     53                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     54                                deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
     55                                Type * base = InitTweak::getPointerBase( arg->get_result() );
     56                                assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
     57                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
     58                                delete ret->get_result();
     59                                ret->set_result( base->clone() );
     60                                ret->get_result()->set_lvalue( true );
     61                                return ret;
     62                        } else {
     63                                return UntypedExpr::createDeref( arg );
     64                        }
     65                }
     66
     67                struct ReferenceConversions final {
     68                        Expression * postmutate( CastExpr * castExpr );
     69                        Expression * postmutate( AddressExpr * addrExpr );
     70                };
     71
     72                /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
     73                struct FixIntrinsicArgs final {
     74                        Expression * postmutate( ApplicationExpr * appExpr );
     75                };
     76
     77                struct FixIntrinsicResult final {
     78                        Expression * postmutate( ApplicationExpr * appExpr );
     79                };
     80
     81                /// Replace reference types with pointer types
     82                struct ReferenceTypeElimination final {
     83                        Type * postmutate( ReferenceType * refType );
    5784                };
    5885
     
    6087                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    6188                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    62                 class GeneralizedLvalue : public Mutator {
    63                         typedef Mutator Parent;
    64 
    65                         virtual Expression * mutate( MemberExpr * memExpr );
    66                         virtual Expression * mutate( AddressExpr * addressExpr );
     89                struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
     90                        Expression * postmutate( AddressExpr * addressExpr );
     91                        Expression * postmutate( MemberExpr * memExpr );
    6792
    6893                        template<typename Func>
    6994                        Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
    7095                };
     96
     97                /// Removes redundant &*/*& pattern that this pass can generate
     98                struct CollapseAddrDeref final {
     99                        Expression * postmutate( AddressExpr * addressExpr );
     100                        Expression * postmutate( ApplicationExpr * appExpr );
     101                };
     102
     103                struct AddrRef final : public WithGuards {
     104                        void premutate( AddressExpr * addrExpr );
     105                        Expression * postmutate( AddressExpr * addrExpr );
     106                        void premutate( Expression * expr );
     107
     108                        bool first = true;
     109                        bool current = false;
     110                        int refDepth = 0;
     111                };
    71112        } // namespace
    72113
     114        static bool referencesEliminated = false;
     115        // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
     116        bool referencesPermissable() {
     117                return ! referencesEliminated;
     118        }
     119
    73120        void convertLvalue( std::list< Declaration* >& translationUnit ) {
    74                 Pass1 p1;
    75                 Pass2 p2;
    76                 GeneralizedLvalue genLval;
    77                 mutateAll( translationUnit, p1 );
    78                 acceptAll( translationUnit, p2 );
     121                std::cerr << "convertLvalue" << std::endl;
     122                PassVisitor<ReferenceConversions> refCvt;
     123                PassVisitor<ReferenceTypeElimination> elim;
     124                PassVisitor<GeneralizedLvalue> genLval;
     125                PassVisitor<FixIntrinsicArgs> fixer;
     126                PassVisitor<CollapseAddrDeref> collapser;
     127                PassVisitor<AddrRef> addrRef;
     128                PassVisitor<FixIntrinsicResult> intrinsicResults;
     129                mutateAll( translationUnit, intrinsicResults );
     130                mutateAll( translationUnit, addrRef );
     131                mutateAll( translationUnit, refCvt );
     132                mutateAll( translationUnit, fixer );
     133                mutateAll( translationUnit, collapser );
    79134                mutateAll( translationUnit, genLval );
     135                mutateAll( translationUnit, elim );  // last because other passes need reference types to work
     136
     137                // from this point forward, no other pass should create reference types.
     138                referencesEliminated = true;
    80139        }
    81140
    82141        Expression * generalizedLvalue( Expression * expr ) {
    83                 GeneralizedLvalue genLval;
     142                PassVisitor<GeneralizedLvalue> genLval;
    84143                return expr->acceptMutator( genLval );
    85144        }
    86145
    87146        namespace {
    88                 Type* isLvalueRet( FunctionType *function ) {
    89                         if ( function->get_returnVals().empty() ) return 0;
    90                         Type *ty = function->get_returnVals().front()->get_type();
    91                         return ty->get_lvalue() ? ty : 0;
    92                 }
    93 
    94                 bool isIntrinsicApp( ApplicationExpr *appExpr ) {
    95                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
    96                                 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
    97                         } else {
    98                                 return false;
    99                         } // if
    100                 }
    101 
    102                 Pass1::Pass1() {
    103                 }
    104 
    105                 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) {
    106                         if ( funcDecl->get_statements() ) {
    107                                 DeclarationWithType* oldRetval = retval;
    108                                 retval = 0;
    109                                 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) {
    110                                         retval = funcDecl->get_functionType()->get_returnVals().front();
    111                                 }
    112                                 // fix expressions and return statements in this function
    113                                 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) );
    114                                 retval = oldRetval;
    115                         } // if
    116                         return funcDecl;
    117                 }
    118 
    119                 Expression * Pass1::mutate( ApplicationExpr *appExpr ) {
    120                         appExpr->get_function()->acceptMutator( *this );
    121                         mutateAll( appExpr->get_args(), *this );
    122 
    123                         PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    124                         FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    125 
    126                         Type *funType = isLvalueRet( function );
    127                         if ( funType && ! isIntrinsicApp( appExpr ) ) {
    128                                 Expression *expr = appExpr;
    129                                 Type *appType = appExpr->get_result();
    130                                 if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
    131                                         // make sure cast for polymorphic type is inside dereference
    132                                         expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
    133                                 }
    134                                 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    135                                 deref->set_result( appType->clone() );
    136                                 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
    137                                 deref->get_args().push_back( expr );
    138                                 return deref;
    139                         } else {
    140                                 return appExpr;
    141                         } // if
    142                 }
    143 
    144                 Statement * Pass1::mutate(ReturnStmt *retStmt) {
    145                         if ( retval && retStmt->get_expr() ) {
    146                                 if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
    147                                         // ***** Code Removal ***** because casts may be stripped already
    148 
    149                                         // strip casts because not allowed to take address of cast
    150                                         // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) {
    151                                         //      retStmt->set_expr( castExpr->get_arg() );
    152                                         //      retStmt->get_expr()->set_env( castExpr->get_env() );
    153                                         //      castExpr->set_env( 0 );
    154                                         //      castExpr->set_arg( 0 );
    155                                         //      delete castExpr;
    156                                         // } // while
    157                                         retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) );
     147                // true for intrinsic function calls that return a reference
     148                bool isIntrinsicReference( Expression * expr ) {
     149                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
     150                                std::string fname = InitTweak::getFunctionName( untyped );
     151                                // known intrinsic-reference prelude functions
     152                                return fname == "*?" || fname == "?[?]";
     153                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
     154                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
     155                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     156                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     157                                        Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
     158                                        return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
     159                                }
     160                        }
     161                        return false;
     162                }
     163
     164                Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
     165                        if ( isIntrinsicReference( appExpr ) ) {
     166                                // eliminate reference types from intrinsic applications - now they return lvalues
     167                                Type * result = appExpr->get_result();
     168                                appExpr->set_result( result->stripReferences()->clone() );
     169                                appExpr->get_result()->set_lvalue( true );
     170                                Expression * ret = new CastExpr( appExpr, result );
     171                                ret->set_env( appExpr->get_env() );
     172                                appExpr->set_env( nullptr );
     173                                return ret;
     174                        }
     175                        return appExpr;
     176                }
     177
     178                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
     179                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
     180                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     181                                FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
     182                                assertf( ftype, "Function declaration does not have function type." );
     183                                // can be of differing lengths only when function is variadic
     184                                assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
     185
     186
     187                                unsigned int i = 0;
     188                                const unsigned int end = ftype->get_parameters().size();
     189                                for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
     190                                        if (i == end) break;
     191                                        Expression *& arg = std::get<0>( p );
     192                                        Type * formal = std::get<1>( p )->get_type();
     193                                        PRINT(
     194                                                std::cerr << "pair<0>: " << arg << std::endl;
     195                                                std::cerr << "pair<1>: " << formal << std::endl;
     196                                        )
     197                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
     198                                                if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
     199                                                        if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
     200                                                                // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
     201                                                                PRINT(
     202                                                                        std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     203                                                                )
     204                                                                arg = new AddressExpr( arg );
     205                                                        }
     206                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     207                                                        // std::cerr << "===adding deref to arg" << std::endl;
     208                                                        // if the parameter is a reference, add a dereference to the reference-typed argument.
     209                                                        Type * baseType = InitTweak::getPointerBase( arg->get_result() );
     210                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
     211                                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
     212                                                        delete arg->get_result();
     213                                                        arg->set_result( ptrType );
     214                                                        arg = mkDeref( arg );
     215                                                }
     216                                        }
     217                                        ++i;
     218                                }
     219                        }
     220                        return appExpr;
     221                }
     222
     223                // idea: &&&E: get outer &, inner &
     224                // at inner &, record depth D of reference type
     225                // at outer &, add D derefs.
     226                void AddrRef::premutate( Expression * expr ) {
     227                        GuardValue( current );
     228                        GuardValue( first );
     229                        current = false;
     230                        first = true;
     231                }
     232
     233                void AddrRef::premutate( AddressExpr * addrExpr ) {
     234                        GuardValue( current );
     235                        GuardValue( first );
     236                        current = first;
     237                        first = false;
     238                        if ( current ) {
     239                                GuardValue( refDepth );
     240                                refDepth = 0;
     241                        }
     242                }
     243
     244                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
     245                        if ( refDepth == 0 ) {
     246                                if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
     247                                        // try to avoid ?[?]
     248                                        refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
     249                                }
     250                        }
     251                        if ( current ) {
     252                                Expression * ret = addrExpr;
     253                                while ( refDepth ) {
     254                                        ret = mkDeref( ret );
     255                                        refDepth--;
     256                                }
     257                                return ret;
     258                        }
     259                        return addrExpr;
     260                }
     261
     262                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
     263                        // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
     264                        // In this case, remove the outer address expression and return the argument.
     265                        // TODO: It's possible that this might catch too much and require a more sophisticated check.
     266                        return addrExpr;
     267                }
     268
     269                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
     270                        // xxx - is it possible to convert directly between reference types with a different base? E.g.,
     271                        //   int x;
     272                        //   (double&)x;
     273                        // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
     274                        // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
     275                        // pointer casts in the right places.
     276
     277                        // conversion to reference type
     278                        if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
     279                                (void)refType;
     280                                if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     281                                        // nothing to do if casting from reference to reference.
     282                                        (void)otherRef;
     283                                        PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
     284                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
     285                                                Expression * callExpr = castExpr->get_arg();
     286                                                PRINT(
     287                                                        std::cerr << "but arg is deref -- &" << std::endl;
     288                                                        std::cerr << callExpr << std::endl;
     289                                                )
     290                                                callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
     291                                                delete callExpr->get_result();
     292                                                callExpr->set_result( refType->clone() );
     293                                                // move environment out to new top-level
     294                                                callExpr->set_env( castExpr->get_env() );
     295                                                castExpr->set_arg( nullptr );
     296                                                castExpr->set_env( nullptr );
     297                                                delete castExpr;
     298                                                return callExpr;
     299                                        }
     300                                        int depth1 = refType->referenceDepth();
     301                                        int depth2 = otherRef->referenceDepth();
     302                                        assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
     303                                        PRINT( std::cerr << castExpr << std::endl; )
     304                                        return castExpr;
     305                                } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
     306                                        // conversion from lvalue to reference
     307                                        // xxx - keep cast, but turn into pointer cast??
     308                                        // xxx - memory
     309                                        PRINT(
     310                                                std::cerr << "convert lvalue to reference -- &" << std::endl;
     311                                                std::cerr << castExpr->get_arg() << std::endl;
     312                                        )
     313                                        AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
     314                                        if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
     315                                                // must keep cast if cast-to type is different from the actual type
     316                                                castExpr->set_arg( ret );
     317                                                return castExpr;
     318                                        }
     319                                        ret->set_env( castExpr->get_env() );
     320                                        delete ret->get_result();
     321                                        ret->set_result( castExpr->get_result() );
     322                                        castExpr->set_env( nullptr );
     323                                        castExpr->set_arg( nullptr );
     324                                        castExpr->set_result( nullptr );
     325                                        delete castExpr;
     326                                        return ret;
    158327                                } else {
    159                                         throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" );
    160                                 } // if
    161                         } // if
    162                         return retStmt;
    163                 }
    164 
    165                 void Pass2::visit( FunctionType *funType ) {
    166                         std::string typeName;
    167                         if ( isLvalueRet( funType ) ) {
    168                                 DeclarationWithType *retParm = funType->get_returnVals().front();
    169 
    170                                 // make a new parameter that is a pointer to the type of the old return value
    171                                 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
    172                         } // if
    173 
    174                         Visitor::visit( funType );
     328                                        // rvalue to reference conversion -- introduce temporary
     329                                }
     330                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
     331                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     332                                (void)refType;
     333                                // conversion from reference to rvalue
     334                                PRINT(
     335                                        std::cerr << "convert reference to rvalue -- *" << std::endl;
     336                                        std::cerr << "was = " << castExpr << std::endl;
     337                                )
     338                                Expression * ret = castExpr->get_arg();
     339                                TypeSubstitution * env = castExpr->get_env();
     340                                castExpr->set_env( nullptr );
     341                                if ( ! isIntrinsicReference( ret ) ) {
     342                                        // dereference if not already dereferenced
     343                                        ret = mkDeref( ret );
     344                                }
     345                                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
     346                                        // can remove cast if types are compatible, changing expression type to value type
     347                                        ret->set_result( castExpr->get_result()->clone() );
     348                                        castExpr->set_arg( nullptr );
     349                                        delete castExpr;
     350                                } else {
     351                                        // must keep cast if types are different
     352                                        castExpr->set_arg( ret );
     353                                        ret = castExpr;
     354                                }
     355                                ret->set_env( env );
     356                                PRINT( std::cerr << "now: " << ret << std::endl; )
     357                                return ret;
     358                        }
     359                        return castExpr;
     360                }
     361
     362                Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
     363                        Type * base = refType->get_base();
     364                        Type::Qualifiers qualifiers = refType->get_qualifiers();
     365                        refType->set_base( nullptr );
     366                        delete refType;
     367                        return new PointerType( qualifiers, base );
    175368                }
    176369
     
    180373                                Expression * arg1 = commaExpr->get_arg1()->clone();
    181374                                Expression * arg2 = commaExpr->get_arg2()->clone();
    182                                 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );
     375                                Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
    183376                                ret->set_env( expr->get_env() );
    184377                                expr->set_env( nullptr );
    185378                                delete expr;
    186                                 return ret->acceptMutator( *this );
     379                                return ret;
    187380                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
    188381                                Expression * arg1 = condExpr->get_arg1()->clone();
    189382                                Expression * arg2 = condExpr->get_arg2()->clone();
    190383                                Expression * arg3 = condExpr->get_arg3()->clone();
    191                                 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ), mkExpr( arg3 ) );
     384                                ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
    192385                                ret->set_env( expr->get_env() );
    193386                                expr->set_env( nullptr );
     
    202395                                unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
    203396                                ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
    204                                 return ret->acceptMutator( *this );
     397                                return ret;
    205398                        }
    206399                        return expr;
    207400                }
    208401
    209                 Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) {
    210                         Parent::mutate( memExpr );
     402                Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
    211403                        return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
    212404                }
    213405
    214                 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
    215                         addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
     406                Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
    216407                        return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
     408                }
     409
     410                Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
     411                        Expression * arg = addrExpr->get_arg();
     412                        if ( isIntrinsicReference( arg ) ) {
     413                                std::string fname = InitTweak::getFunctionName( arg );
     414                                if ( fname == "*?" ) {
     415                                        Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
     416                                        Expression * ret = arg0;
     417                                        ret->set_env( addrExpr->get_env() );
     418                                        arg0 = nullptr;
     419                                        addrExpr->set_env( nullptr );
     420                                        delete addrExpr;
     421                                        return ret;
     422                                }
     423                        }
     424                        return addrExpr;
     425                }
     426
     427                Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
     428                        if ( isIntrinsicReference( appExpr ) ) {
     429                                std::string fname = InitTweak::getFunctionName( appExpr );
     430                                if ( fname == "*?" ) {
     431                                        Expression * arg = InitTweak::getCallArg( appExpr, 0 );
     432                                        // xxx - this isn't right, because it can remove casts that should be there...
     433                                        // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
     434                                        //      arg = castExpr->get_arg();
     435                                        // }
     436                                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
     437                                                Expression * ret = addrExpr->get_arg();
     438                                                ret->set_env( appExpr->get_env() );
     439                                                addrExpr->set_arg( nullptr );
     440                                                appExpr->set_env( nullptr );
     441                                                delete appExpr;
     442                                                return ret;
     443                                        }
     444                                }
     445                        }
     446                        return appExpr;
    217447                }
    218448        } // namespace
  • src/GenPoly/Lvalue.h

    rbd46af4 r8217e8f  
    2424        void convertLvalue( std::list< Declaration* >& translationUnit );
    2525
     26        /// true after reference types have been eliminated from the source code. After this point, reference types should not be added to the AST.
     27        bool referencesPermissable();
     28
    2629        /// applies transformations that allow GCC to accept more complicated lvalue expressions, e.g. &(a, b)
    2730        Expression * generalizedLvalue( Expression * expr );
  • src/GenPoly/Specialize.cc

    rbd46af4 r8217e8f  
    101101                        // conversion of 0 (null) to function type does not require tuple specialization
    102102                        if ( dynamic_cast< ZeroType * >( actualType ) ) return false;
    103                         FunctionType * aftype = getFunctionType( actualType );
    104                         assertf( aftype, "formal type is a function type, but actual type is not." );
     103                        FunctionType * aftype = getFunctionType( actualType->stripReferences() );
     104                        assertf( aftype, "formal type is a function type, but actual type is not: %s", toString( actualType ).c_str() );
    105105                        if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true;
    106106                        for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) {
  • src/InitTweak/FixInit.cc

    rbd46af4 r8217e8f  
    2626#include "FixGlobalInit.h"
    2727#include "CodeGen/GenType.h"  // for warning/error messages
     28#include "CodeGen/OperatorTable.h"
    2829#include "Common/PassVisitor.h"
    2930#include "GenPoly/DeclMutator.h"
     
    238239                        SemanticError errors;
    239240                  private:
    240                         void handleFirstParam( Expression * firstParam );
    241241                        template< typename... Params >
    242242                        void emit( CodeLocation, const Params &... params );
     
    363363                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    364364                                        assert( ftype );
    365                                         if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    366                                                 Type * t1 = ftype->get_parameters().front()->get_type();
     365                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
     366                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    367367                                                Type * t2 = ftype->get_parameters().back()->get_type();
    368                                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
    369 
    370                                                 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     368                                                assert( t1 );
     369
     370                                                if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) {
    371371                                                        // optimization: don't need to copy construct in order to call a copy constructor
    372372                                                        return appExpr;
    373373                                                } // if
    374                                         } else if ( isDestructor( funcDecl->get_name() ) ) {
     374                                        } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
    375375                                                // correctness: never copy construct arguments to a destructor
    376376                                                return appExpr;
     
    401401
    402402                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    403                         return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     403                        return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    404404                }
    405405
     
    489489                                impCpCtorExpr->get_returnDecls().push_back( ret );
    490490                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    491                                 if ( ! result->get_lvalue() ) {
     491                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    492492                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    493493                                        destructRet( ret, impCpCtorExpr );
     
    975975                        if ( ! funcDecl ) return false;
    976976                        if ( ! funcDecl->get_statements() ) return false;
    977                         return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     977                        return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
    978978                }
    979979
     
    992992
    993993                        function = funcDecl;
    994                         isCtor = isConstructor( function->get_name() );
     994                        isCtor = CodeGen::isConstructor( function->get_name() );
    995995                        if ( checkWarnings( function ) ) {
    996996                                FunctionType * type = function->get_functionType();
    997997                                assert( ! type->get_parameters().empty() );
    998998                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
    999                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
    1000                                 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
     999                                Type * thisType = getPointerBase( thisParam->get_type() );
     1000                                StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
    10011001                                if ( structType ) {
    10021002                                        structDecl = structType->get_baseStruct();
     
    10311031
    10321032                        if ( ! unhandled.empty() ) {
    1033                                 // need to explicitly re-add function parameters in order to resolve copy constructors
     1033                                // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
    10341034                                enterScope();
    10351035                                maybeAccept( function->get_functionType(), *this );
     
    10461046                                        // insert and resolve default/copy constructor call for each field that's unhandled
    10471047                                        std::list< Statement * > stmt;
    1048                                         UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );
    1049 
    10501048                                        Expression * arg2 = 0;
    10511049                                        if ( isCopyConstructor( function ) ) {
     
    10561054                                        }
    10571055                                        InitExpander srcParam( arg2 );
    1058                                         SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
     1056                                        // cast away reference type and construct field.
     1057                                        Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
     1058                                        Expression * memberDest = new MemberExpr( field, thisExpr );
     1059                                        SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor );
    10591060
    10601061                                        assert( stmt.size() <= 1 );
     
    10831084                }
    10841085
     1086                /// true if expr is effectively just the 'this' parameter
     1087                bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) {
     1088                        // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc.
     1089                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
     1090                                return varExpr->get_var() == thisParam;
     1091                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
     1092                                return isThisExpression( castExpr->get_arg(), thisParam );
     1093                        }
     1094                        return false;
     1095                }
     1096
     1097                /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr
     1098                MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) {
     1099                        if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
     1100                                if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1101                                        return memberExpr;
     1102                                }
     1103                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     1104                                return isThisMemberExpr( castExpr->get_arg(), thisParam );
     1105                        }
     1106                        return nullptr;
     1107                }
     1108
    10851109                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    10861110                        if ( ! checkWarnings( function ) ) return;
     
    10911115                                Expression * firstParam = appExpr->get_args().front();
    10921116
    1093                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
     1117                                if ( isThisExpression( firstParam, thisParam ) ) {
    10941118                                        // if calling another constructor on thisParam, assume that function handles
    10951119                                        // all members - if it doesn't a warning will appear in that function.
    1096                                         if ( varExpr->get_var() == thisParam ) {
    1097                                                 unhandled.clear();
    1098                                         }
    1099                                 } else {
    1100                                         // if first parameter is a member expression then
    1101                                         // remove the member from unhandled set.
    1102                                         handleFirstParam( firstParam );
    1103                                 }
    1104                         }
    1105 
    1106                         Parent::visit( appExpr );
    1107                 }
    1108 
    1109                 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
    1110                         using namespace std;
    1111                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
    1112                                 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) {
    1113                                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1114                                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1115                                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1116                                                                 if ( varExpr->get_var() == thisParam ) {
    1117                                                                         unhandled.erase( memberExpr->get_member() );
    1118                                                                 }
    1119                                                         }
    1120                                                 }
     1120                                        unhandled.clear();
     1121                                } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
     1122                                        // if first parameter is a member expression on the this parameter,
     1123                                        // then remove the member from unhandled set.
     1124                                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1125                                                unhandled.erase( memberExpr->get_member() );
    11211126                                        }
    11221127                                }
    11231128                        }
     1129                        Parent::visit( appExpr );
    11241130                }
    11251131
     
    11281134                        if ( ! isCtor ) return;
    11291135
    1130                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1131                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1132                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1133                                                 if ( varExpr->get_var() == thisParam ) {
    1134                                                         if ( unhandled.count( memberExpr->get_member() ) ) {
    1135                                                                 // emit a warning because a member was used before it was constructed
    1136                                                                 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
    1137                                                         }
    1138                                                 }
    1139                                         }
     1136                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1137                                if ( unhandled.count( memberExpr->get_member() ) ) {
     1138                                        // emit a warning because a member was used before it was constructed
     1139                                        usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
    11401140                                }
    11411141                        }
     
    11831183                        ctorExpr->set_callExpr( nullptr );
    11841184                        ctorExpr->set_env( nullptr );
     1185                        delete ctorExpr;
    11851186
    11861187                        Expression *& firstArg = callExpr->get_args().front();
    1187                         UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
    1188                         assign->get_args().push_back( new VariableExpr( tmp ) );
    1189                         assign->get_args().push_back( firstArg );
    1190                         assign->set_result( ctorExpr->get_result()->clone() );
    1191                         firstArg = assign;
    1192 
    1193                         CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) );
     1188
     1189                        // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
     1190
     1191                        // generate the type of assignment operator using the type of tmp minus any reference types
     1192                        Type * type = tmp->get_type()->stripReferences();
     1193                        FunctionType * ftype = SymTab::genAssignType( type );
     1194
     1195                        // generate fake assignment decl and call it using &tmp and &firstArg
     1196                        // since tmp is guaranteed to be a reference and we want to assign pointers
     1197                        FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
     1198                        ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
     1199                        assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
     1200                        Expression * addrArg = new AddressExpr( firstArg );
     1201                        // if firstArg has type T&&, then &firstArg has type T*&.
     1202                        // Cast away the reference to a value type so that the argument
     1203                        // matches the assignment's parameter types
     1204                        if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
     1205                                addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
     1206                        }
     1207                        assign->get_args().push_back( addrArg );
     1208                        firstArg = new VariableExpr( tmp );
     1209
     1210                        // for constructor expr:
     1211                        //   T x;
     1212                        //   x{};
     1213                        // results in:
     1214                        //   T x;
     1215                        //   T & tmp;
     1216                        //   &tmp = &x, ?{}(tmp), tmp
     1217                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11941218                        commaExpr->set_env( env );
    1195                         delete ctorExpr;
    11961219                        return commaExpr;
    11971220                }
  • src/InitTweak/GenInit.cc

    rbd46af4 r8217e8f  
    2121
    2222#include "Common/PassVisitor.h"
     23#include "CodeGen/OperatorTable.h"
    2324
    2425#include "GenPoly/DeclMutator.h"
     
    5455
    5556          protected:
    56                 FunctionType * ftype;
     57                FunctionType * ftype = nullptr;
    5758                std::string funcName;
    5859        };
     
    137138                std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    138139                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    139                 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     140                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    140141                // is being returned
    141                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {
     142                if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
    142143                        // explicitly construct the return value using the return expression and the retVal object
    143144                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    144                         UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
    145                         construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
    146                         construct->get_args().push_back( returnStmt->get_expr() );
    147                         stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct));
     145
     146                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
    148147
    149148                        // return the retVal object
     
    212211
    213212        bool CtorDtor::isManaged( Type * type ) const {
     213                // at least for now, references are never constructed
     214                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    214215                // need to clear and reset qualifiers when determining if a type is managed
    215216                ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     
    235236        void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
    236237                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    237                 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
     238                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
    238239                        std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
    239240                        assert( ! params.empty() );
    240                         PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
    241                         managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
     241                        Type * type = InitTweak::getPointerBase( params.front()->get_type() );
     242                        assert( type );
     243                        managedTypes.insert( SymTab::Mangler::mangle( type ) );
    242244                }
    243245        }
  • src/InitTweak/InitTweak.cc

    rbd46af4 r8217e8f  
    170170
    171171                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    172                         increment->get_args().push_back( new AddressExpr( index->clone() ) );
     172                        increment->get_args().push_back( index->clone() );
    173173                        *out++ = new ExprStmt( noLabels, increment );
    174174                }
     
    380380                template<typename CallExpr>
    381381                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
    382                         if ( pos >= callExpr->get_args().size() ) assertf( false, "asking for argument that doesn't exist. Return NULL/throw exception?" );
     382                        if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
    383383                        for ( Expression *& arg : callExpr->get_args() ) {
    384384                                if ( pos == 0 ) return arg;
     
    458458                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    459459                        return arrayType->get_base();
     460                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
     461                        return refType->get_base();
    460462                } else {
    461463                        return NULL;
     
    543545                if ( ftype->get_parameters().size() != 2 ) return 0;
    544546
    545                 Type * t1 = ftype->get_parameters().front()->get_type();
     547                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    546548                Type * t2 = ftype->get_parameters().back()->get_type();
    547                 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
    548                 assert( ptrType );
    549 
    550                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     549                assert( t1 );
     550
     551                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
    551552                        return function;
    552553                } else {
  • src/InitTweak/InitTweak.h

    rbd46af4 r8217e8f  
    2525// helper functions for initialization
    2626namespace InitTweak {
    27         bool isConstructor( const std::string & );
    28         bool isDestructor( const std::string & );
    29         bool isAssignment( const std::string & );
    30         bool isCtorDtor( const std::string & );
    31         bool isCtorDtorAssign( const std::string & );
    32 
    3327        FunctionDecl * isAssignment( Declaration * decl );
    3428        FunctionDecl * isDestructor( Declaration * decl );
  • src/Makefile.in

    rbd46af4 r8217e8f  
    224224        SynTree/driver_cfa_cpp-PointerType.$(OBJEXT) \
    225225        SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT) \
     226        SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT) \
    226227        SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT) \
    227228        SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT) \
     
    520521        SynTree/VoidType.cc SynTree/BasicType.cc \
    521522        SynTree/PointerType.cc SynTree/ArrayType.cc \
    522         SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
    523         SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
     523        SynTree/ReferenceType.cc SynTree/FunctionType.cc \
     524        SynTree/ReferenceToType.cc SynTree/TupleType.cc \
     525        SynTree/TypeofType.cc SynTree/AttrType.cc \
    524526        SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \
    525527        SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \
     
    867869SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
    868870        SynTree/$(DEPDIR)/$(am__dirstamp)
     871SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT):  \
     872        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    869873SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT):  \
    870874        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     
    10701074@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po@am__quote@
    10711075@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po@am__quote@
     1076@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po@am__quote@
    10721077@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po@am__quote@
    10731078@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po@am__quote@
     
    21672172@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    21682173@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ArrayType.obj `if test -f 'SynTree/ArrayType.cc'; then $(CYGPATH_W) 'SynTree/ArrayType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ArrayType.cc'; fi`
     2174
     2175SynTree/driver_cfa_cpp-ReferenceType.o: SynTree/ReferenceType.cc
     2176@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
     2177@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
     2178@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.o' libtool=no @AMDEPBACKSLASH@
     2179@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2180@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
     2181
     2182SynTree/driver_cfa_cpp-ReferenceType.obj: SynTree/ReferenceType.cc
     2183@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
     2184@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
     2185@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.obj' libtool=no @AMDEPBACKSLASH@
     2186@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2187@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
    21692188
    21702189SynTree/driver_cfa_cpp-FunctionType.o: SynTree/FunctionType.cc
  • src/Parser/DeclarationNode.cc

    rbd46af4 r8217e8f  
    331331} // DeclarationNode::newTypeDecl
    332332
    333 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers ) {
    334         DeclarationNode * newnode = new DeclarationNode;
    335         newnode->type = new TypeData( TypeData::Pointer );
     333DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) {
     334        DeclarationNode * newnode = new DeclarationNode;
     335        newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference );
    336336        if ( qualifiers ) {
    337337                return newnode->addQualifiers( qualifiers );
     
    750750DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) {
    751751        if ( p ) {
    752                 assert( p->type->kind == TypeData::Pointer );
     752                assert( p->type->kind == TypeData::Pointer || TypeData::Reference );
    753753                setBase( p->type );
    754754                p->type = nullptr;
     
    772772DeclarationNode * DeclarationNode::addNewPointer( DeclarationNode * p ) {
    773773        if ( p ) {
    774                 assert( p->type->kind == TypeData::Pointer );
     774                assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
    775775                if ( type ) {
    776776                        switch ( type->kind ) {
  • src/Parser/ExpressionNode.cc

    rbd46af4 r8217e8f  
    305305Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
    306306        std::list< Expression * > args;
    307         args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node) ) );
     307        args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx
    308308        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    309309} // build_unary_ptr
     
    318318Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
    319319        std::list< Expression * > args;
    320         args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node1) ) );
     320        args.push_back( maybeMoveBuild< Expression >(expr_node1) );
    321321        args.push_back( maybeMoveBuild< Expression >(expr_node2) );
    322322        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
  • src/Parser/ParseNode.h

    rbd46af4 r8217e8f  
    237237        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    238238        static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
    239         static DeclarationNode * newPointer( DeclarationNode * qualifiers );
     239        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    240240        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
    241241        static DeclarationNode * newVarArray( DeclarationNode * qualifiers );
  • src/Parser/TypeData.cc

    rbd46af4 r8217e8f  
    3030          case Unknown:
    3131          case Pointer:
     32          case Reference:
    3233          case EnumConstant:
    3334                // nothing else to initialize
     
    99100          case Unknown:
    100101          case Pointer:
     102          case Reference:
    101103          case EnumConstant:
    102104                // nothing to destroy
     
    165167          case EnumConstant:
    166168          case Pointer:
     169          case Reference:
    167170                // nothing else to copy
    168171                break;
     
    400403                        // add dtor:  void ^?{}(T *)
    401404                        FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
    402                         dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     405                        dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    403406                        td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) );
    404407
    405408                        // add copy ctor:  void ?{}(T *, T)
    406409                        FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
    407                         copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     410                        copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    408411                        copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    409412                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) );
     
    411414                        // add default ctor:  void ?{}(T *)
    412415                        FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
    413                         ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     416                        ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    414417                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) );
    415418
    416419                        // add assignment operator:  T * ?=?(T *, T)
    417420                        FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
    418                         assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     421                        assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    419422                        assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    420423                        assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
     
    436439          case TypeData::Array:
    437440                return buildArray( td );
     441          case TypeData::Reference:
     442                return buildReference( td );
    438443          case TypeData::Function:
    439444                return buildFunction( td );
     
    614619        buildForall( td->forall, at->get_forall() );
    615620        return at;
    616 } // buildPointer
     621} // buildArray
     622
     623ReferenceType * buildReference( const TypeData * td ) {
     624        ReferenceType * rt;
     625        if ( td->base ) {
     626                rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
     627        } else {
     628                rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     629        } // if
     630        buildForall( td->forall, rt->get_forall() );
     631        return rt;
     632} // buildReference
    617633
    618634AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
  • src/Parser/TypeData.h

    rbd46af4 r8217e8f  
    2020
    2121struct TypeData {
    22         enum Kind { Basic, Pointer, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
     22        enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    2323                                SymbolicInst, Tuple, Typeof, Builtin, Unknown };
    2424
     
    103103PointerType * buildPointer( const TypeData * );
    104104ArrayType * buildArray( const TypeData * );
     105ReferenceType * buildReference( const TypeData * );
    105106AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
    106107ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
  • src/Parser/lex.ll

    rbd46af4 r8217e8f  
    236236__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    237237long                    { KEYWORD_RETURN(LONG); }
    238 lvalue                  { KEYWORD_RETURN(LVALUE); }                             // CFA
    239238monitor                 { KEYWORD_RETURN(MONITOR); }                    // CFA
    240239mutex                   { KEYWORD_RETURN(MUTEX); }                              // CFA
  • src/Parser/parser.yy

    rbd46af4 r8217e8f  
    118118%token RESTRICT                                                                                 // C99
    119119%token ATOMIC                                                                                   // C11
    120 %token FORALL LVALUE MUTEX VIRTUAL                                              // CFA
     120%token FORALL MUTEX VIRTUAL                                             // CFA
    121121%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    122122%token BOOL COMPLEX IMAGINARY                                                   // C99
     
    668668        conditional_expression
    669669        | unary_expression assignment_operator assignment_expression
    670                 { $$ = new ExpressionNode( build_binary_ptr( $2, $1, $3 ) ); }
     670                { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); }
    671671        ;
    672672
     
    14251425        | VOLATILE
    14261426                { $$ = DeclarationNode::newTypeQualifier( Type::Volatile ); }
    1427         | LVALUE                                                                                        // CFA
    1428                 { $$ = DeclarationNode::newTypeQualifier( Type::Lvalue ); }
    14291427        | MUTEX
    14301428                { $$ = DeclarationNode::newTypeQualifier( Type::Mutex ); }
     
    24072405variable_ptr:
    24082406        ptrref_operator variable_declarator
    2409                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2407                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    24102408        | ptrref_operator type_qualifier_list variable_declarator
    2411                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2409                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    24122410        | '(' variable_ptr ')' attribute_list_opt
    24132411                { $$ = $2->addQualifiers( $4 ); }                               // redundant parenthesis
     
    24552453function_ptr:
    24562454        ptrref_operator function_declarator
    2457                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2455                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    24582456        | ptrref_operator type_qualifier_list function_declarator
    2459                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2457                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    24602458        | '(' function_ptr ')'
    24612459                { $$ = $2; }
     
    24952493KR_function_ptr:
    24962494        ptrref_operator KR_function_declarator
    2497                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2495                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    24982496        | ptrref_operator type_qualifier_list KR_function_declarator
    2499                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2497                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    25002498        | '(' KR_function_ptr ')'
    25012499                { $$ = $2; }
     
    25392537type_ptr:
    25402538        ptrref_operator variable_type_redeclarator
    2541                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2539                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    25422540        | ptrref_operator type_qualifier_list variable_type_redeclarator
    2543                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2541                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    25442542        | '(' type_ptr ')' attribute_list_opt
    25452543                { $$ = $2->addQualifiers( $4 ); }
     
    25832581identifier_parameter_ptr:
    25842582        ptrref_operator identifier_parameter_declarator
    2585                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2583                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    25862584        | ptrref_operator type_qualifier_list identifier_parameter_declarator
    2587                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2585                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    25882586        | '(' identifier_parameter_ptr ')' attribute_list_opt
    25892587                { $$ = $2->addQualifiers( $4 ); }
     
    26432641type_parameter_ptr:
    26442642        ptrref_operator type_parameter_redeclarator
    2645                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2643                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    26462644        | ptrref_operator type_qualifier_list type_parameter_redeclarator
    2647                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2645                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    26482646        | '(' type_parameter_ptr ')' attribute_list_opt
    26492647                { $$ = $2->addQualifiers( $4 ); }
     
    26862684abstract_ptr:
    26872685        ptrref_operator
    2688                 { $$ = DeclarationNode::newPointer( 0 ); }
     2686                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    26892687        | ptrref_operator type_qualifier_list
    2690                 { $$ = DeclarationNode::newPointer( $2 ); }
     2688                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    26912689        | ptrref_operator abstract_declarator
    2692                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2690                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    26932691        | ptrref_operator type_qualifier_list abstract_declarator
    2694                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2692                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    26952693        | '(' abstract_ptr ')' attribute_list_opt
    26962694                { $$ = $2->addQualifiers( $4 ); }
     
    27752773abstract_parameter_ptr:
    27762774        ptrref_operator
    2777                 { $$ = DeclarationNode::newPointer( nullptr ); }
     2775                { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
    27782776        | ptrref_operator type_qualifier_list
    2779                 { $$ = DeclarationNode::newPointer( $2 ); }
     2777                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    27802778        | ptrref_operator abstract_parameter_declarator
    2781                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr ) ); }
     2779                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    27822780        | ptrref_operator type_qualifier_list abstract_parameter_declarator
    2783                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2781                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    27842782        | '(' abstract_parameter_ptr ')' attribute_list_opt
    27852783                { $$ = $2->addQualifiers( $4 ); }
     
    28542852variable_abstract_ptr:
    28552853        ptrref_operator
    2856                 { $$ = DeclarationNode::newPointer( 0 ); }
     2854                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    28572855        | ptrref_operator type_qualifier_list
    2858                 { $$ = DeclarationNode::newPointer( $2 ); }
     2856                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    28592857        | ptrref_operator variable_abstract_declarator
    2860                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2858                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    28612859        | ptrref_operator type_qualifier_list variable_abstract_declarator
    2862                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2860                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    28632861        | '(' variable_abstract_ptr ')' attribute_list_opt
    28642862                { $$ = $2->addQualifiers( $4 ); }
     
    29002898                // No SUE declaration in parameter list.
    29012899        ptrref_operator type_specifier_nobody
    2902                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2900                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29032901        | type_qualifier_list ptrref_operator type_specifier_nobody
    2904                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2902                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29052903        | ptrref_operator cfa_abstract_function
    2906                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2904                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29072905        | type_qualifier_list ptrref_operator cfa_abstract_function
    2908                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2906                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29092907        | ptrref_operator cfa_identifier_parameter_declarator_tuple
    2910                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2908                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29112909        | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
    2912                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2910                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29132911        ;
    29142912
     
    29882986cfa_abstract_ptr:                                                                               // CFA
    29892987        ptrref_operator type_specifier
    2990                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2988                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29912989        | type_qualifier_list ptrref_operator type_specifier
    2992                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2990                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29932991        | ptrref_operator cfa_abstract_function
    2994                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2992                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29952993        | type_qualifier_list ptrref_operator cfa_abstract_function
    2996                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2994                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29972995        | ptrref_operator cfa_abstract_declarator_tuple
    2998                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2996                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29992997        | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
    3000                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2998                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    30012999        ;
    30023000
  • src/ResolvExpr/Alternative.cc

    rbd46af4 r8217e8f  
    2828                : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
    2929
    30         Alternative::Alternative( const Alternative &other ) {
    31                 initialize( other, *this );
     30        Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    3231        }
    3332
    3433        Alternative &Alternative::operator=( const Alternative &other ) {
    3534                if ( &other == this ) return *this;
    36                 initialize( other, *this );
     35                delete expr;
     36                cost = other.cost;
     37                cvtCost = other.cvtCost;
     38                expr = maybeClone( other.expr );
     39                env = other.env;
    3740                return *this;
    3841        }
     
    5154                other.expr = nullptr;
    5255                return *this;
    53         }
    54 
    55         void Alternative::initialize( const Alternative &src, Alternative &dest ) {
    56                 dest.cost = src.cost;
    57                 dest.cvtCost = src.cvtCost;
    58                 dest.expr = maybeClone( src.expr );
    59                 dest.env = src.env;
    6056        }
    6157
  • src/ResolvExpr/Alternative.h

    rbd46af4 r8217e8f  
    3535                ~Alternative();
    3636
    37                 void initialize( const Alternative &src, Alternative &dest );
    38 
    3937                void print( std::ostream &os, int indent = 0 ) const;
    4038
  • src/ResolvExpr/AlternativeFinder.cc

    rbd46af4 r8217e8f  
    6767
    6868        Cost sumCost( const AltList &in ) {
    69                 Cost total;
     69                Cost total = Cost::zero;
    7070                for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    7171                        total += i->cost;
     
    144144                        expr->get_result()->accept( global_renamer );
    145145                }
    146         }
     146
     147                void referenceToRvalueConversion( Expression *& expr ) {
     148                        if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     149                                // cast away reference from expr
     150                                expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     151                        }
     152                }
     153        } // namespace
    147154
    148155        template< typename InputIterator, typename OutputIterator >
     
    213220        void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
    214221                // adds anonymous member interpretations whenever an aggregate value type is seen.
    215                 Expression * expr = alt.expr->clone();
    216                 std::unique_ptr< Expression > manager( expr ); // RAII for expr
    217                 alt.env.apply( expr->get_result() );
    218                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) {
     222                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     223                std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
     224                alt.env.apply( aggrExpr->get_result() );
     225                Type * aggrType = aggrExpr->get_result();
     226                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     227                        aggrType = aggrType->stripReferences();
     228                        aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     229                }
     230
     231                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    219232                        NameExpr nameExpr( "" );
    220                         addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
    221                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {
     233                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
     234                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    222235                        NameExpr nameExpr( "" );
    223                         addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
     236                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
    224237                } // if
    225238        }
     
    277290                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    278291
    279                 Cost convCost( 0, 0, 0 );
     292                Cost convCost = Cost::zero;
    280293                std::list< DeclarationWithType* >& formals = function->get_parameters();
    281294                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     
    290303                                actualType->print( std::cerr, 8 );
    291304                        )
    292                         Cost actualCost;
     305                        Cost actualCost = Cost::zero;
    293306                        if ( formal == formals.end() ) {
    294307                                if ( function->get_isVarArgs() ) {
    295                                         convCost += Cost( 1, 0, 0 );
     308                                        convCost.incUnsafe();
     309                                        // convert reference-typed expressions to value-typed expressions
     310                                        referenceToRvalueConversion( *actualExpr );
    296311                                        continue;
    297312                                } else {
     
    305320                                std::cerr << std::endl << " to ";
    306321                                formalType->print( std::cerr, 8 );
     322                                std::cerr << std::endl << "environment is: ";
     323                                alt.env.print( std::cerr, 8 );
     324                                std::cerr << std::endl;
    307325                        )
    308326                        Cost newCost = conversionCost( actualType, formalType, indexer, alt.env );
     
    316334                        convCost += newCost;
    317335                        actualCost += newCost;
    318                         if ( actualCost != Cost( 0, 0, 0 ) ) {
     336                        if ( actualCost != Cost::zero ) {
    319337                                Type *newType = formalType->clone();
    320338                                alt.env.apply( newType );
    321339                                *actualExpr = new CastExpr( *actualExpr, newType );
    322340                        }
    323                         convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 );
     341                        convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
    324342                        ++formal; // can't be in for-loop update because of the continue
    325343                }
     
    343361                        }
    344362                        convCost += newCost;
    345                         convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
     363                        convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
    346364                }
    347365
     
    400418                        Expression * actual = actualIt->expr;
    401419                        Type * actualType = actual->get_result();
     420
    402421                        PRINT(
    403422                                std::cerr << "formal type is ";
     
    408427                        )
    409428                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     429                                // std::cerr << "unify failed" << std::endl;
    410430                                return false;
    411431                        }
     
    452472                        // match flattened actuals with formal parameters - actuals will be grouped to match
    453473                        // with formals as appropriate
    454                         Cost cost;
     474                        Cost cost = Cost::zero;
    455475                        std::list< Expression * > newExprs;
    456476                        ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
     
    613633                AssertionSet newNeed;
    614634                //AssertionParentSet needParents;
     635                PRINT(
     636                        std::cerr << "env is: " << std::endl;
     637                        newAlt.env.print( std::cerr, 0 );
     638                        std::cerr << std::endl;
     639                )
     640
    615641                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
    616642//      PRINT(
     
    643669                        makeExprList( instantiatedActuals, appExpr->get_args() );
    644670                        PRINT(
     671                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    645672                                std::cerr << "need assertions:" << std::endl;
    646673                                printAssertionSet( resultNeed, std::cerr, 8 );
     
    663690                                UntypedExpr *vexpr = untypedExpr->clone();
    664691                                vexpr->set_result( pt.clone() );
    665                                 alternatives.push_back( Alternative( vexpr, env, Cost()) );
     692                                alternatives.push_back( Alternative( vexpr, env, Cost::zero) );
    666693                                return;
    667694                        }
     
    681708                AltList candidates;
    682709                SemanticError errors;
    683                 for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
     710                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    684711                        try {
    685712                                PRINT(
     
    688715                                )
    689716                                // check if the type is pointer to function
    690                                 PointerType *pointer;
    691                                 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
     717                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    692718                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     719                                                referenceToRvalueConversion( func->expr );
    693720                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    694721                                                        // XXX
     
    696723                                                        makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    697724                                                }
    698                                         } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) {
    699                                                 EqvClass eqvClass;
    700                                                 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    701                                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
    702                                                                 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    703                                                                         makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    704                                                                 } // for
    705                                                         } // if
     725                                        }
     726                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     727                                        referenceToRvalueConversion( func->expr );
     728                                        EqvClass eqvClass;
     729                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
     730                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     731                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     732                                                                makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     733                                                        } // for
    706734                                                } // if
    707735                                        } // if
     
    722750                                        }
    723751
    724                                         for ( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     752                                        for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    725753                                                // check if the type is pointer to function
    726                                                 PointerType *pointer;
    727                                                 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
     754                                                if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    728755                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     756                                                                referenceToRvalueConversion( funcOp->expr );
    729757                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    730758                                                                        AltList currentAlt;
     
    753781                                PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    754782                                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    755                                 std::cerr << "Case +++++++++++++" << std::endl;
     783                                std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
    756784                                std::cerr << "formals are:" << std::endl;
    757785                                printAll( function->get_parameters(), std::cerr, 8 );
     
    796824        bool isLvalue( Expression *expr ) {
    797825                // xxx - recurse into tuples?
    798                 return expr->has_result() && expr->get_result()->get_lvalue();
     826                return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    799827        }
    800828
     
    810838
    811839        Expression * restructureCast( Expression * argExpr, Type * toType ) {
    812                 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) {
    813                         // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
    814                         // to its corresponding target type, producing the tuple of those cast expressions. If there are
    815                         // more components of the tuple than components in the target type, then excess components do not
    816                         // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
     840                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
     841                        // Argument expression is a tuple and the target type is not void and not a reference type.
     842                        // Cast each member of the tuple to its corresponding target type, producing the tuple of those
     843                        // cast expressions. If there are more components of the tuple than components in the target type,
     844                        // then excess components do not come out in the result expression (but UniqueExprs ensure that
     845                        // side effects will still be done).
    817846                        if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
    818847                                // expressions which may contain side effects require a single unique instance of the expression.
     
    855884                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    856885                        // to.
    857                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     886                        int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size();
    858887                        if ( discardedValues < 0 ) continue;
    859888                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    860889                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    861890                        // unification run for side-effects
    862                         unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
    863                         Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
     891                        unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
     892                        Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env );
    864893                        if ( thisCost != Cost::infinity ) {
    865894                                // count one safe conversion for each value that is thrown away
    866                                 thisCost += Cost( 0, 0, discardedValues );
     895                                thisCost.incSafe( discardedValues );
    867896
    868897                                candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     
    895924                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    896925                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    897                         if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
    898                                 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    899                         } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
    900                                 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    901                         } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
    902                                 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     926                        // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     927                        std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
     928                        Type * aggrType = aggrExpr->get_result();
     929                        if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     930                                aggrType = aggrType->stripReferences();
     931                                aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     932                        }
     933                        // find member of the given type
     934                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
     935                                addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     936                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
     937                                addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     938                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
     939                                addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
    903940                        } // if
    904941                } // for
     
    915952                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    916953                        VariableExpr newExpr( *i, nameExpr->get_argName() );
    917                         alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     954                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    918955                        PRINT(
    919956                                std::cerr << "decl is ";
     
    10591096                        for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    10601097                                VariableExpr newExpr( *i );
    1061                                 alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     1098                                alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    10621099                                renameTypes( alternatives.back().expr );
    10631100                        } // for
     
    12321269                                if ( thisCost != Cost::infinity ) {
    12331270                                        // count one safe conversion for each value that is thrown away
    1234                                         thisCost += Cost( 0, 0, discardedValues );
     1271                                        thisCost.incSafe( discardedValues );
    12351272                                        candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    12361273                                }
  • src/ResolvExpr/CastCost.cc

    rbd46af4 r8217e8f  
    4646                                assert( type );
    4747                                if ( type->get_base() ) {
    48                                         return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     48                                        return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
    4949                                } // if
    5050                        } // if
    5151                } // if
    5252                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    53                         return Cost( 0, 0, 0 );
     53                        return Cost::zero;
    5454                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    55                         return Cost( 0, 0, 1 );
     55                        return Cost::safe;
     56                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     57                        return convertToReferenceCost( src, refType, indexer, env );
    5658                } else {
    5759                        CastCost converter( dest, indexer, env );
     
    6163                        } else {
    6264                                // xxx - why are we adding cost 0 here?
    63                                 return converter.get_cost() + Cost( 0, 0, 0 );
     65                                return converter.get_cost() + Cost::zero;
    6466                        } // if
    6567                } // if
     
    7476                if ( destAsPointer && basicType->isInteger() ) {
    7577                        // necessary for, e.g. unsigned long => void*
    76                         cost = Cost( 1, 0, 0 );
     78                        cost = Cost::unsafe;
    7779                } else {
    78                         ConversionCost::visit( basicType );
     80                        cost = conversionCost( basicType, dest, indexer, env );
    7981                } // if
    8082        }
     
    8385                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    8486                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    85                                 cost = Cost( 0, 0, 1 );
     87                                cost = Cost::safe;
    8688                        } else {
    8789                                TypeEnvironment newEnv( env );
     
    9092                                int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
    9193                                if ( castResult > 0 ) {
    92                                         cost = Cost( 0, 0, 1 );
     94                                        cost = Cost::safe;
    9395                                } else if ( castResult < 0 ) {
    9496                                        cost = Cost::infinity;
     
    98100                        if ( destAsBasic->isInteger() ) {
    99101                                // necessary for, e.g. void* => unsigned long
    100                                 cost = Cost( 1, 0, 0 );
     102                                cost = Cost::unsafe;
    101103                        } // if
    102104                }
  • src/ResolvExpr/CommonType.cc

    rbd46af4 r8217e8f  
    1717#include "SynTree/Type.h"
    1818#include "Unify.h"
    19 
    2019
    2120/// #define DEBUG
     
    3130                virtual void visit( PointerType *pointerType );
    3231                virtual void visit( ArrayType *arrayType );
     32                virtual void visit( ReferenceType *refType );
    3333                virtual void visit( FunctionType *functionType );
    3434                virtual void visit( StructInstType *aggregateUseType );
     
    4242                virtual void visit( OneType *oneType );
    4343
    44                 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer );
     44                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
     45                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    4546
    4647                Type *result;
     
    5253        };
    5354
     55        Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
     56                Type * result = nullptr, * common = nullptr;
     57                AssertionSet have, need;
     58                OpenVarSet newOpen( openVars );
     59                // need unify to bind type variables
     60                if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
     61                        // std::cerr << "unify success" << std::endl;
     62                        if ( widenSecond ) {
     63                                if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
     64                                        result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
     65                                        result->get_qualifiers() |= other->get_qualifiers();
     66                                }
     67                        } else if ( widenFirst ) {
     68                                if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
     69                                        result = common;
     70                                        result->get_qualifiers() |= refType->get_qualifiers();
     71                                }
     72                        }
     73                } else {
     74                        // std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
     75                }
     76                // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
     77                return result;
     78        }
     79
    5480        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    5581                CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     82
     83                int depth1 = type1->referenceDepth();
     84                int depth2 = type2->referenceDepth();
     85                if ( depth1 > 0 || depth2 > 0 ) {
     86                        int diff = depth1-depth2;
     87                        // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
     88                        if ( diff > 1 || diff < -1 ) return nullptr;
     89
     90                        // special case where one type has a reference depth of 1 larger than the other
     91                        if ( diff > 0 ) {
     92                                return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars );
     93                        } else if ( diff < 0 ) {
     94                                return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars );
     95                        }
     96                        // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
     97                }
     98
    5699                type1->accept( visitor );
    57100                Type *result = visitor.get_result();
     
    142185        }
    143186
    144         void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) {
     187        template< typename Pointer >
     188        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    145189                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    146190                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    188232
    189233        void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
     234
     235        void CommonType::visit( ReferenceType *refType ) {
     236                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     237                        if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
     238                                getCommonWithVoidPointer( otherRef, refType );
     239                        } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     240                                getCommonWithVoidPointer( refType, otherRef );
     241                        } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
     242                                           && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
     243                                Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
     244                                refType->get_base()->get_qualifiers() = Type::Qualifiers();
     245                                otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
     246                                AssertionSet have, need;
     247                                OpenVarSet newOpen( openVars );
     248                                if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
     249                                        if ( tq1 < tq2 ) {
     250                                                result = refType->clone();
     251                                        } else {
     252                                                result = otherRef->clone();
     253                                        } // if
     254                                        result->get_qualifiers() = tq1 | tq2;
     255                                } else {
     256                                        /// std::cout << "place for ptr-to-type" << std::endl;
     257                                } // if
     258                                refType->get_base()->get_qualifiers() = tq1;
     259                                otherRef->get_base()->get_qualifiers() = tq2;
     260                        } // if
     261                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     262                        result = refType->clone();
     263                        result->get_qualifiers() |= type2->get_qualifiers();
     264                } // if
     265        }
     266
    190267        void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    191268        void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
     
    195272                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    196273                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    197                         Type * temp = type2;
     274                        ValueGuard< Type * > temp( type2 );
    198275                        type2 = enumInstType;
    199                         temp->accept( *this );
    200                         type2 = temp;
     276                        temp.old->accept( *this );
    201277                } // if
    202278        }
  • src/ResolvExpr/ConversionCost.cc

    rbd46af4 r8217e8f  
    2121
    2222namespace ResolvExpr {
    23         const Cost Cost::zero = Cost( 0, 0, 0 );
    24         const Cost Cost::infinity = Cost( -1, -1, -1 );
     23        const Cost Cost::zero = Cost( 0, 0, 0, 0 );
     24        const Cost Cost::infinity = Cost( -1, -1, -1, -1 );
     25        const Cost Cost::unsafe = Cost( 1, 0, 0, 0 );
     26        const Cost Cost::poly = Cost( 0, 1, 0, 0 );
     27        const Cost Cost::safe = Cost( 0, 0, 1, 0 );
     28        const Cost Cost::reference = Cost( 0, 0, 0, 1 );
     29
    2530
    2631        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     
    4146                                assert( type );
    4247                                if ( type->get_base() ) {
    43                                         return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     48                                        return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
    4449                                } // if
    4550                        } // if
     
    5459                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    5560///     std::cout << "compatible!" << std::endl;
    56                         return Cost( 0, 0, 0 );
     61                        return Cost::zero;
    5762                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    58                         return Cost( 0, 0, 1 );
     63                        return Cost::safe;
     64                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     65                        // std::cerr << "conversionCost: dest is reference" << std::endl;
     66                        return convertToReferenceCost( src, refType, indexer, env );
    5967                } else {
    6068                        ConversionCost converter( dest, indexer, env );
     
    6371                                return Cost::infinity;
    6472                        } else {
    65                                 return converter.get_cost() + Cost( 0, 0, 0 );
    66                         } // if
    67                 } // if
     73                                return converter.get_cost() + Cost::zero;
     74                        } // if
     75                } // if
     76        }
     77
     78        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     79                // std::cerr << "convert to reference cost..." << std::endl;
     80                if ( diff > 0 ) {
     81                        // TODO: document this
     82                        Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
     83                        cost.incReference();
     84                        return cost;
     85                } else if ( diff < -1 ) {
     86                        // TODO: document this
     87                        Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
     88                        cost.incReference();
     89                        return cost;
     90                } else if ( diff == 0 ) {
     91                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
     92                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     93                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
     94                                // std::cerr << "converting between references" << std::endl;
     95                                if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
     96                                        return Cost::safe;
     97                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     98                                        int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
     99                                        if ( assignResult < 0 ) {
     100                                                return Cost::safe;
     101                                        } else if ( assignResult > 0 ) {
     102                                                return Cost::unsafe;
     103                                        } // if
     104                                } // if
     105                        } else {
     106                                // std::cerr << "reference to rvalue conversion" << std::endl;
     107                                ConversionCost converter( dest, indexer, env );
     108                                src->accept( converter );
     109                                return converter.get_cost();
     110                        } // if
     111                } else {
     112                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     113                        assert( diff == -1 && destAsRef );
     114                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     115                                // std::cerr << "converting compatible base type" << std::endl;
     116                                if ( src->get_lvalue() ) {
     117                                        // std::cerr << "lvalue to reference conversion" << std::endl;
     118                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
     119                                        if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     120                                                return Cost::reference; // cost needs to be non-zero to add cast
     121                                        } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     122                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
     123                                        } else {
     124                                                return Cost::unsafe;
     125                                        } // if
     126                                } else if ( destAsRef->get_base()->get_const() ) {
     127                                        // std::cerr << "rvalue to const ref conversion" << std::endl;
     128                                        // rvalue-to-const-reference conversion: T => const T &
     129                                        return Cost::safe;
     130                                } else {
     131                                        // std::cerr << "rvalue to non-const reference conversion" << std::endl;
     132                                        // rvalue-to-reference conversion: T => T &
     133                                        return Cost::unsafe;
     134                                } // if
     135                        } // if
     136                        // std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
     137                }
     138                return Cost::infinity;
     139        }
     140
     141        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     142                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
     143                return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
    68144        }
    69145
     
    157233                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
    158234                        if ( tableResult == -1 ) {
    159                                 cost = Cost( 1, 0, 0 );
    160                         } else {
    161                                 cost = Cost( 0, 0, tableResult );
     235                                cost = Cost::unsafe;
     236                        } else {
     237                                cost = Cost::zero;
     238                                cost.incSafe( tableResult );
    162239                        } // if
    163240                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
    164241                        // xxx - not positive this is correct, but appears to allow casting int => enum
    165                         cost = Cost( 1, 0, 0 );
     242                        cost = Cost::unsafe;
    166243                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    167                         cost = Cost( 1, 0, 0 );
     244                        cost = Cost::unsafe;
    168245                } // if
    169246        }
     
    171248        void ConversionCost::visit(PointerType *pointerType) {
    172249                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    173                         if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    174                                 cost = Cost( 0, 0, 1 );
    175                         } else {
     250                        // std::cerr << pointerType << " ===> " << destAsPtr;
     251                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
     252                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
     253                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     254                                if ( tq1 == tq2 ) {
     255                                        // types are the same
     256                                        cost = Cost::zero;
     257                                } else {
     258                                        // types are the same, except otherPointer has more qualifiers
     259                                        // std::cerr << " :: compatible and good qualifiers" << std::endl;
     260                                        cost = Cost::safe;
     261                                }
     262                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    176263                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
    177                                 if ( assignResult < 0 ) {
    178                                         cost = Cost( 0, 0, 1 );
     264                                // std::cerr << " :: " << assignResult << std::endl;
     265                                if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
     266                                        cost = Cost::safe;
    179267                                } else if ( assignResult > 0 ) {
    180                                         cost = Cost( 1, 0, 0 );
     268                                        cost = Cost::unsafe;
    181269                                } // if
     270                                // assignResult == 0 means Cost::Infinity
    182271                        } // if
    183272                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    184                         cost = Cost( 1, 0, 0 );
     273                        cost = Cost::unsafe;
    185274                } // if
    186275        }
    187276
    188277        void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
     278
     279        void ConversionCost::visit(ReferenceType *refType) {
     280                // Note: dest can never be a reference, since it would have been caught in an earlier check
     281                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     282                // convert reference to rvalue: cv T1 & => T2
     283                // recursively compute conversion cost from T1 to T2.
     284                // cv can be safely dropped because of 'implicit dereference' behavior.
     285                refType->get_base()->accept( *this );
     286                if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
     287                        cost.incReference();  // prefer exact qualifiers
     288                } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
     289                        cost.incSafe(); // then gaining qualifiers
     290                } else {
     291                        cost.incUnsafe(); // lose qualifiers as last resort
     292                }
     293                // std::cerr << refType << " ==> " << dest << " " << cost << std::endl;
     294        }
     295
    189296        void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
    190297
     
    208315                static Type::Qualifiers q;
    209316                static BasicType integer( q, BasicType::SignedInt );
    210                 integer.accept( *this );
    211                 if ( cost < Cost( 1, 0, 0 ) ) {
     317                integer.accept( *this );  // safe if dest >= int
     318                if ( cost < Cost::unsafe ) {
    212319                        cost.incSafe();
    213320                } // if
     
    231338                        assert( type );
    232339                        if ( type->get_base() ) {
    233                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
     340                                cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    234341                        } // if
    235342                } // if
     
    237344
    238345        void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
    239                 Cost c;
     346                Cost c = Cost::zero;
    240347                if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
    241348                        std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
     
    269376                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    270377                        if ( tableResult == -1 ) {
    271                                 cost = Cost( 1, 0, 0 );
    272                         } else {
    273                                 cost = Cost( 0, 0, tableResult + 1 );
     378                                cost = Cost::unsafe;
     379                        } else {
     380                                cost = Cost::zero;
     381                                cost.incSafe( tableResult + 1 );
    274382                        }
    275383                } else if ( dynamic_cast< PointerType* >( dest ) ) {
    276                         cost = Cost( 0, 0, 1 );
     384                        cost = Cost::safe;
    277385                }
    278386        }
     
    285393                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    286394                        if ( tableResult == -1 ) {
    287                                 cost = Cost( 1, 0, 0 );
    288                         } else {
    289                                 cost = Cost( 0, 0, tableResult + 1 );
     395                                cost = Cost::unsafe;
     396                        } else {
     397                                cost = Cost::zero;
     398                                cost.incSafe( tableResult + 1 );
    290399                        }
    291400                }
  • src/ResolvExpr/ConversionCost.h

    rbd46af4 r8217e8f  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ConversionCost.h -- 
     7// ConversionCost.h --
    88//
    99// Author           : Richard C. Bilson
     
    2525          public:
    2626                ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    27  
     27
    2828                Cost get_cost() const { return cost; }
    2929
     
    3232                virtual void visit(PointerType *pointerType);
    3333                virtual void visit(ArrayType *arrayType);
     34                virtual void visit(ReferenceType *refType);
    3435                virtual void visit(FunctionType *functionType);
    3536                virtual void visit(StructInstType *aggregateUseType);
     
    4849                const TypeEnvironment &env;
    4950        };
     51
     52        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    5053} // namespace ResolvExpr
    5154
  • src/ResolvExpr/Cost.h

    rbd46af4 r8217e8f  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Cost.h -- 
     7// Cost.h --
    88//
    99// Author           : Richard C. Bilson
     
    2020namespace ResolvExpr {
    2121        class Cost {
     22          private:
     23                Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     24
    2225          public:
    23                 Cost();
    24                 Cost( int unsafe, int poly, int safe );
    25  
    26                 void incUnsafe( int inc = 1 );
    27                 void incPoly( int inc = 1 );
    28                 void incSafe( int inc = 1 );
    29  
     26                Cost & incUnsafe( int inc = 1 );
     27                Cost & incPoly( int inc = 1 );
     28                Cost & incSafe( int inc = 1 );
     29                Cost & incReference( int inc = 1 );
     30
    3031                Cost operator+( const Cost &other ) const;
    3132                Cost operator-( const Cost &other ) const;
     
    3536                bool operator!=( const Cost &other ) const;
    3637                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    37  
     38
    3839                static const Cost zero;
    3940                static const Cost infinity;
     41
     42                static const Cost unsafe;
     43                static const Cost poly;
     44                static const Cost safe;
     45                static const Cost reference;
    4046          private:
    4147                int compare( const Cost &other ) const;
    4248
    43                 int unsafe;
    44                 int poly;
    45                 int safe;
     49                int unsafeCost;
     50                int polyCost;
     51                int safeCost;
     52                int referenceCost;
    4653        };
    4754
    48         inline Cost::Cost() : unsafe( 0 ), poly( 0 ), safe( 0 ) {}
     55        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
    4956
    50         inline Cost::Cost( int unsafe, int poly, int safe ) : unsafe( unsafe ), poly( poly ), safe( safe ) {}
    51 
    52         inline void Cost::incUnsafe( int inc ) {
    53                 unsafe += inc;
     57        inline Cost & Cost::incUnsafe( int inc ) {
     58                if ( *this == infinity ) return *this;
     59                unsafeCost += inc;
     60                return *this;
    5461        }
    5562
    56         inline void Cost::incPoly( int inc ) {
    57                 poly += inc;
     63        inline Cost & Cost::incPoly( int inc ) {
     64                if ( *this == infinity ) return *this;
     65                polyCost += inc;
     66                return *this;
    5867        }
    5968
    60         inline void Cost::incSafe( int inc ) {
    61                 safe += inc;
     69        inline Cost & Cost::incSafe( int inc ) {
     70                if ( *this == infinity ) return *this;
     71                safeCost += inc;
     72                return *this;
     73        }
     74
     75        inline Cost & Cost::incReference( int inc ) {
     76                if ( *this == infinity ) return *this;
     77                referenceCost += inc;
     78                return *this;
    6279        }
    6380
    6481        inline Cost Cost::operator+( const Cost &other ) const {
    65                 return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe );
     82                if ( *this == infinity || other == infinity ) return infinity;
     83                return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
    6684        }
    6785
    6886        inline Cost Cost::operator-( const Cost &other ) const {
    69                 return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe );
     87                if ( *this == infinity || other == infinity ) return infinity;
     88                return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
    7089        }
    7190
    7291        inline Cost &Cost::operator+=( const Cost &other ) {
    73                 unsafe += other.unsafe;
    74                 poly += other.poly;
    75                 safe += other.safe;
     92                if ( *this == infinity ) return *this;
     93                if ( other == infinity ) {
     94                        *this = infinity;
     95                        return *this;
     96                }
     97                unsafeCost += other.unsafeCost;
     98                polyCost += other.polyCost;
     99                safeCost += other.safeCost;
     100                referenceCost += other.referenceCost;
    76101                return *this;
    77102        }
    78103
    79104        inline bool Cost::operator<( const Cost &other ) const {
    80             if ( *this == infinity ) return false;
    81             if ( other == infinity ) return true;
    82             if ( unsafe > other.unsafe ) {
     105                if ( *this == infinity ) return false;
     106                if ( other == infinity ) return true;
     107
     108                if ( unsafeCost > other.unsafeCost ) {
    83109                        return false;
    84             } else if ( unsafe < other.unsafe ) {
     110                } else if ( unsafeCost < other.unsafeCost ) {
    85111                        return true;
    86             } else if ( poly > other.poly ) {
     112                } else if ( polyCost > other.polyCost ) {
    87113                        return false;
    88             } else if ( poly < other.poly ) {
     114                } else if ( polyCost < other.polyCost ) {
    89115                        return true;
    90             } else if ( safe > other.safe ) {
     116                } else if ( safeCost > other.safeCost ) {
    91117                        return false;
    92             } else if ( safe < other.safe ) {
     118                } else if ( safeCost < other.safeCost ) {
    93119                        return true;
    94             } else {
     120                } else if ( referenceCost > other.referenceCost ) {
    95121                        return false;
    96             } // if
     122                } else if ( referenceCost < other.referenceCost ) {
     123                        return true;
     124                } else {
     125                        return false;
     126                } // if
    97127        }
    98128
    99129        inline bool Cost::operator==( const Cost &other ) const {
    100                 return unsafe == other.unsafe
    101                         && poly == other.poly
    102                         && safe == other.safe;
     130                return unsafeCost == other.unsafeCost
     131                        && polyCost == other.polyCost
     132                        && safeCost == other.safeCost
     133                        && referenceCost == other.referenceCost;
    103134        }
    104135
     
    108139
    109140        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    110                 os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe << " )";
     141                os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    111142                return os;
    112143        }
  • src/ResolvExpr/Unify.cc

    rbd46af4 r8217e8f  
    4242                virtual void visit(PointerType *pointerType);
    4343                virtual void visit(ArrayType *arrayType);
     44                virtual void visit(ReferenceType *refType);
    4445                virtual void visit(FunctionType *functionType);
    4546                virtual void visit(StructInstType *aggregateUseType);
     
    142143
    143144        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     145                // remove references from other, so that type variables can only bind to value types
     146                other = other->stripReferences();
    144147                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    145148                assert( tyvar != openVars.end() );
     
    376379                                } // if
    377380                        } else {
     381                                common = type1->clone();
     382                                common->get_qualifiers() = tq1 | tq2;
    378383                                result = true;
    379384                        } // if
     
    425430                        markAssertions( haveAssertions, needAssertions, pointerType );
    426431                        markAssertions( haveAssertions, needAssertions, otherPointer );
     432                } // if
     433        }
     434
     435        void Unify::visit(ReferenceType *refType) {
     436                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     437                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     438                        markAssertions( haveAssertions, needAssertions, refType );
     439                        markAssertions( haveAssertions, needAssertions, otherRef );
    427440                } // if
    428441        }
  • src/ResolvExpr/typeops.h

    rbd46af4 r8217e8f  
    6666        Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    6767
    68         template< typename SrcIterator, typename DestIterator >
    69         Cost castCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    70                 Cost ret;
    71                 if ( destBegin == destEnd ) {
    72                         if ( srcBegin == srcEnd ) {
    73                                 return Cost::zero;
    74                         } else {
    75                                 return Cost( 0, 0, 1 );
    76                         } // if
    77                 } // if
    78                 while ( srcBegin != srcEnd && destBegin != destEnd ) {
    79                         Cost thisCost = castCost( *srcBegin++, *destBegin++, indexer, env );
    80                         if ( thisCost == Cost::infinity ) {
    81                                 return Cost::infinity;
    82                         } // if
    83                         ret += thisCost;
    84                 } // while
    85                 if ( srcBegin == srcEnd && destBegin == destEnd ) {
    86                         return ret;
    87                 } else {
    88                         return Cost::infinity;
    89                 } // if
    90         }
    91 
    9268        // in ConversionCost.cc
    9369        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    94 
    95         template< typename SrcIterator, typename DestIterator >
    96         Cost conversionCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    97                 Cost ret;
    98                 while ( srcBegin != srcEnd && destBegin != destEnd ) {
    99                         Cost thisCost = conversionCost( *srcBegin++, *destBegin++, indexer, env );
    100                         if ( thisCost == Cost::infinity ) {
    101                                 return Cost::infinity;
    102                         } // if
    103                         ret += thisCost;
    104                 } // while
    105                 if ( srcBegin == srcEnd && destBegin == destEnd ) {
    106                         return ret;
    107                 } else {
    108                         return Cost::infinity;
    109                 } // if
    110         }
    11170
    11271        // in PtrsAssignable.cc
  • src/SymTab/Autogen.cc

    rbd46af4 r8217e8f  
    1313// Update Count     : 62
    1414//
     15
    1516#include "Autogen.h"
    1617
     
    2324
    2425#include "AddVisit.h"              // for addVisit
     26#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2527#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
    2628#include "Common/utility.h"        // for cloneAll, operator+
     
    2830#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
    2931#include "SymTab/Mangler.h"        // for Mangler
     32#include "SynTree/Attribute.h"     // For Attribute
    3033#include "SynTree/Mutator.h"       // for maybeMutate
    3134#include "SynTree/Statement.h"     // for CompoundStmt, ReturnStmt, ExprStmt
     
    131134        FunctionType * genDefaultType( Type * paramType ) {
    132135                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    133                 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );
     136                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    134137                ftype->get_parameters().push_back( dstParam );
    135138
     
    151154                ftype->get_returnVals().push_back( returnVal );
    152155                return ftype;
    153         }
    154 
    155         /// true if the aggregate's layout is dynamic
    156         template< typename AggrDecl >
    157         bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
    158                 for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
    159                         if ( param->isComplete() ) return true;
    160                 }
    161                 return false;
    162156        }
    163157
     
    182176                        FunctionType * ftype = funcDecl->get_functionType();
    183177                        assert( ! ftype->get_parameters().empty() );
    184                         Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base();
     178                        Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );
     179                        assert( t );
    185180                        map.insert( Mangler::mangleType( t ), true );
    186181                }
     
    228223                        FunctionType * ftype = data.genType( refType );
    229224
    230                         if(concurrent_type && InitTweak::isDestructor( data.fname )) {
     225                        if(concurrent_type && CodeGen::isDestructor( data.fname )) {
    231226                                ftype->get_parameters().front()->get_type()->set_mutex( true );
    232227                        }
     
    280275                FunctionType *copyCtorType = genCopyType( refType->clone() );
    281276
     277                // add unused attribute to parameters of default constructor and destructor
     278                ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     279                dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     280
    282281                // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    283282                // right now these cases work, but that might change.
     
    302301
    303302        /// generates a single struct member operation (constructor call, destructor call, assignment call)
    304         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
    305                 ObjectDecl * returnVal = NULL;
    306                 if ( ! func->get_functionType()->get_returnVals().empty() ) {
    307                         returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
    308                 }
    309 
     303        void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) {
    310304                InitTweak::InitExpander srcParam( src );
    311305
    312                 // assign to destination (and return value if generic)
    313                 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) );
    314                 Expression *dstselect = new MemberExpr( field, derefExpr );
     306                // assign to destination
     307                Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), safe_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) );
    315308                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    316 
    317                 if ( isDynamicLayout && returnVal ) {
    318                         // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?
    319                         Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );
    320                         genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    321                 } // if
    322309        }
    323310
    324311        /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
    325312        template<typename Iterator>
    326         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
     313        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ) {
    327314                for ( ; member != end; ++member ) {
    328315                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    360347
    361348                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    362                                 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );
     349                                makeStructMemberOp( dstParam, srcselect, field, func, forward );
    363350                        } // if
    364351                } // for
     
    368355        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
    369356        template<typename Iterator>
    370         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {
     357        void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
    371358                FunctionType * ftype = func->get_functionType();
    372359                std::list<DeclarationWithType*> & params = ftype->get_parameters();
     
    394381                                        // matching parameter, initialize field with copy ctor
    395382                                        Expression *srcselect = new VariableExpr(*parameter);
    396                                         makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );
     383                                        makeStructMemberOp( dstParam, srcselect, field, func );
    397384                                        ++parameter;
    398385                                } else {
    399386                                        // no matching parameter, initialize field with default ctor
    400                                         makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );
     387                                        makeStructMemberOp( dstParam, NULL, field, func );
    401388                                }
    402389                        }
     
    414401                // Make function polymorphic in same parameters as generic struct, if applicable
    415402                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    416                 bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    417403
    418404                // generate each of the functions based on the supplied FuncData objects
     
    424410
    425411                // field ctors are only generated if default constructor and copy constructor are both generated
    426                 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );
     412                unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
    427413
    428414                if ( functionNesting == 0 ) {
     
    439425                        // generate appropriate calls to member ctor, assignment
    440426                        // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
    441                         if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {
    442                                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout );
     427                        if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {
     428                                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl );
    443429                        } else {
    444                                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false );
    445                         }
    446                         if ( InitTweak::isAssignment( dcl->get_name() ) ) {
     430                                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false );
     431                        }
     432                        if ( CodeGen::isAssignment( dcl->get_name() ) ) {
    447433                                // assignment needs to return a value
    448434                                FunctionType * assignType = dcl->get_functionType();
     
    473459                                        // our inheritance model. I think the correct way to handle this is to
    474460                                        // cast the structure to the type of the member and let the resolver
    475                                         // figure out whether it's valid and have a pass afterwards that fixes
    476                                         // the assignment to use pointer arithmetic with the offset of the
    477                                         // member, much like how generic type members are handled.
     461                                        // figure out whether it's valid/choose the correct unnamed member
    478462                                        continue;
    479463                                }
    480464                                memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    481465                                FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    482                                 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
     466                                makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor );
    483467                                declsToAdd.push_back( ctor );
    484468                        }
     
    491475        void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    492476                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    493                 copy->get_args().push_back( new VariableExpr( dstParam ) );
     477                copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
    494478                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    495479                copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     
    503487                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    504488                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    505                 ObjectDecl * returnVal = nullptr;
    506                 if ( ! ftype->get_returnVals().empty() ) {
    507                         returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );
    508                 }
    509489
    510490                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
    511                 if ( returnVal ) {
     491                if ( CodeGen::isAssignment( funcDecl->get_name() ) ) {
     492                        // also generate return statement in assignment
    512493                        funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    513494                }
     
    536517                cloneAll( typeParams, copyCtorType->get_forall() );
    537518                cloneAll( typeParams, assignType->get_forall() );
     519
     520                // add unused attribute to parameters of default constructor and destructor
     521                ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     522                dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    538523
    539524                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
  • src/SymTab/Autogen.h

    rbd46af4 r8217e8f  
    4343        extern Type * SizeType;
    4444
     45        /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
     46        /// Useful for creating dereference ApplicationExprs without a full resolver pass.
     47        extern FunctionDecl * dereferenceOperator;
     48
     49        // temporary
     50        FunctionType * genAssignType( Type * paramType );
     51
    4552        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    4653        template< typename OutputIterator >
     
    5158        template< typename OutputIterator >
    5259        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    53         // want to be able to generate assignment, ctor, and dtor generically,
    54         // so fname is either ?=?, ?{}, or ^?{}
    55         UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     60                // want to be able to generate assignment, ctor, and dtor generically,
     61                // so fname is either ?=?, ?{}, or ^?{}
     62                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    5663
    57         // do something special for unnamed members
    58         dstParam = new AddressExpr( dstParam );
    59         if ( addCast ) {
    60                 // cast to T* with qualifiers removed, so that qualified objects can be constructed
    61                 // and destructed with the same functions as non-qualified objects.
    62                 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    63                 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    64                 // remove lvalue as a qualifier, this can change to
    65                 //   type->get_qualifiers() = Type::Qualifiers();
    66                 assert( type );
    67                 Type * castType = type->clone();
    68                 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    69                 castType->set_lvalue( true ); // xxx - might not need this
    70                 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    71         }
    72         fExpr->get_args().push_back( dstParam );
     64                if ( addCast ) {
     65                        // cast to T& with qualifiers removed, so that qualified objects can be constructed
     66                        // and destructed with the same functions as non-qualified objects.
     67                        // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     68                        // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     69                        // remove lvalue as a qualifier, this can change to
     70                        //   type->get_qualifiers() = Type::Qualifiers();
     71                        assert( type );
     72                        Type * castType = type->clone();
     73                        castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     74                        // castType->set_lvalue( true ); // xxx - might not need this
     75                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
     76                }
     77                fExpr->get_args().push_back( dstParam );
    7378
    74         Statement * listInit = srcParam.buildListInit( fExpr );
     79                Statement * listInit = srcParam.buildListInit( fExpr );
    7580
    76         std::list< Expression * > args = *++srcParam;
    77         fExpr->get_args().splice( fExpr->get_args().end(), args );
     81                std::list< Expression * > args = *++srcParam;
     82                fExpr->get_args().splice( fExpr->get_args().end(), args );
    7883
    79         *out++ = new ExprStmt( noLabels, fExpr );
     84                *out++ = new ExprStmt( noLabels, fExpr );
    8085
    81         srcParam.clearArrayIndices();
     86                srcParam.clearArrayIndices();
    8287
    83         return listInit;
     88                return listInit;
    8489        }
    8590
     
    117122
    118123                UntypedExpr *inc = new UntypedExpr( update );
    119                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     124                inc->get_args().push_back( new VariableExpr( index ) );
    120125
    121126                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
  • src/SymTab/Indexer.cc

    rbd46af4 r8217e8f  
    2323#include <utility>                 // for pair, make_pair, move
    2424
     25#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2526#include "Common/SemanticError.h"  // for SemanticError
    2627#include "Common/utility.h"        // for cloneAll
     
    111112        void Indexer::removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const {
    112113                // only need to perform this step for constructors, destructors, and assignment functions
    113                 if ( ! InitTweak::isCtorDtorAssign( id ) ) return;
     114                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
    114115
    115116                // helpful data structure
     
    139140                                decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
    140141                                existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
    141                                 existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
     142                                existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
    142143                                existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
    143144                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
     
    157158                                assert( ! params.empty() );
    158159                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    159                                 Type * base = safe_dynamic_cast< PointerType * >( params.front()->get_type() )->get_base();
     160                                Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     161                                assert( base );
    160162                                funcMap[ Mangler::mangle( base ) ] += function;
    161163                        } else {
  • src/SymTab/Mangler.cc

    rbd46af4 r8217e8f  
    131131                mangleName << "A0";
    132132                maybeAccept( arrayType->get_base(), *this );
     133        }
     134
     135        void Mangler::visit( ReferenceType *refType ) {
     136                printQualifiers( refType );
     137                mangleName << "R";
     138                maybeAccept( refType->get_base(), *this );
    133139        }
    134140
     
    302308                // Removed due to restrict not affecting function compatibility in GCC
    303309//              if ( type->get_isRestrict() ) {
    304 //                      mangleName << "R";
     310//                      mangleName << "E";
    305311//              } // if
    306312                if ( type->get_lvalue() ) {
  • src/SymTab/Mangler.h

    rbd46af4 r8217e8f  
    4242                virtual void visit( PointerType *pointerType );
    4343                virtual void visit( ArrayType *arrayType );
     44                virtual void visit( ReferenceType *refType );
    4445                virtual void visit( FunctionType *functionType );
    4546                virtual void visit( StructInstType *aggregateUseType );
  • src/SymTab/Validate.cc

    rbd46af4 r8217e8f  
    5454#include "Autogen.h"                   // for SizeType, autogenerateRoutines
    5555#include "CodeGen/CodeGenerator.h"     // for genName
     56#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5657#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    5758#include "Common/ScopedMap.h"          // for ScopedMap<>::const_iterator
     
    239240        };
    240241
     242
     243        FunctionDecl * dereferenceOperator = nullptr;
     244        struct FindSpecialDeclarations final {
     245                void previsit( FunctionDecl * funcDecl );
     246        };
     247
    241248        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    242249                PassVisitor<EnumAndPointerDecay> epc;
     
    245252                PassVisitor<CompoundLiteral> compoundliteral;
    246253                PassVisitor<ValidateGenericParameters> genericParams;
     254                PassVisitor<FindSpecialDeclarations> finder;
    247255
    248256                EliminateTypedef::eliminateTypedef( translationUnit );
     
    261269                acceptAll( translationUnit, fpd );
    262270                ArrayLength::computeLength( translationUnit );
     271                acceptAll( translationUnit, finder );
    263272        }
    264273
     
    821830                std::list< DeclarationWithType * > &params = funcType->get_parameters();
    822831
    823                 if ( InitTweak::isCtorDtorAssign( funcDecl->get_name() ) ) {
     832                if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
    824833                        if ( params.size() == 0 ) {
    825834                                throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
    826835                        }
    827                         PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() );
    828                         if ( ! ptrType || ptrType->is_array() ) {
    829                                 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl );
     836                        ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
     837                        if ( ! refType ) {
     838                                throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl );
    830839                        }
    831                         if ( InitTweak::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
     840                        if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
    832841                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
    833842                        }
     
    945954                }
    946955        }
     956
     957        void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
     958                if ( ! dereferenceOperator ) {
     959                        if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) {
     960                                FunctionType * ftype = funcDecl->get_functionType();
     961                                if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) {
     962                                        dereferenceOperator = funcDecl;
     963                                }
     964                        }
     965                }
     966        }
    947967} // namespace SymTab
    948968
  • src/SynTree/AddressExpr.cc

    rbd46af4 r8217e8f  
    1818#include "Common/utility.h"
    1919
     20// Address expressions are typed based on the following inference rules:
     21//    E : lvalue T  &..& (n references)
     22//   &E :        T *&..& (n references)
     23//
     24//    E : T  &..&        (m references)
     25//   &E : T *&..&        (m-1 references)
     26//
     27// That is, lvalues becomes
     28
     29namespace {
     30        Type * addrType( Type * type ) {
     31                if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
     32                        return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) );
     33                } else {
     34                        return new PointerType( Type::Qualifiers(), type->clone() );
     35                }
     36        }
     37}
     38
    2039AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) {
    2140        if ( arg->has_result() ) {
    22                 set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) );
     41                if ( arg->get_result()->get_lvalue() ) {
     42                        // lvalue, retains all layers of reference and gains a pointer inside the references
     43                        set_result( addrType( arg->get_result() ) );
     44                } else {
     45                        // taking address of non-lvalue -- must be a reference, loses one layer of reference
     46                        ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() );
     47                        set_result( addrType( refType->get_base() ) );
     48                }
     49                // result of & is never an lvalue
     50                get_result()->set_lvalue( false );
    2351        }
    2452}
  • src/SynTree/ApplicationExpr.cc

    rbd46af4 r8217e8f  
    4444}
    4545
    46 ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list< Expression * > & argList ) : function( funcExpr ), args( argList ) {
     46ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list<Expression *> & args ) : function( funcExpr ), args( args ) {
    4747        PointerType *pointer = safe_dynamic_cast< PointerType* >( funcExpr->get_result() );
    4848        FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
  • src/SynTree/Expression.cc

    rbd46af4 r8217e8f  
    3434#include "InitTweak/InitTweak.h"
    3535
     36#include "GenPoly/Lvalue.h"
    3637
    3738Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
     
    9293}
    9394
     95VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) {
     96        VariableExpr * funcExpr = new VariableExpr( func );
     97        funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) );
     98        return funcExpr;
     99}
     100
    94101void VariableExpr::print( std::ostream &os, int indent ) const {
    95102        os << "Variable Expression: ";
     
    152159
    153160void AlignofExpr::print( std::ostream &os, int indent) const {
    154         os << std::string( indent, ' ' ) << "Alignof Expression on: ";
     161        os << "Alignof Expression on: ";
    155162
    156163        if (isType)
     
    261268
    262269void AttrExpr::print( std::ostream &os, int indent) const {
    263         os << std::string( indent, ' ' ) << "Attr ";
     270        os << "Attr ";
    264271        attr->print( os, indent + 2 );
    265272        if ( isType || expr ) {
     
    360367namespace {
    361368        TypeSubstitution makeSub( Type * t ) {
    362                 if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
     369                if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) {
     370                        return makeSub( refType->get_base() );
     371                } else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
    363372                        return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() );
    364373                } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
     
    425434        if ( Type * type = expr->get_result() ) {
    426435                Type * base = InitTweak::getPointerBase( type );
    427                 if ( ! base ) {
    428                         std::cerr << type << std::endl;
     436                assertf( base, "expected pointer type in dereference (type was %s)", toString( type ).c_str() );
     437                ret->set_result( base->clone() );
     438                if ( GenPoly::referencesPermissable() ) {
     439                        // if references are still allowed in the AST, dereference returns a reference
     440                        ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) );
     441                } else {
     442                        // references have been removed, in which case dereference returns an lvalue of the base type.
     443                        ret->get_result()->set_lvalue( true );
    429444                }
    430                 assertf( base, "expected pointer type in dereference\n" );
    431                 ret->set_result( maybeClone( base ) );
    432445        }
    433446        return ret;
     
    493506
    494507void LogicalExpr::print( std::ostream &os, int indent )const {
    495         os << std::string( indent, ' ' ) << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
     508        os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
    496509        arg1->print(os);
    497510        os << " and ";
  • src/SynTree/Expression.h

    rbd46af4 r8217e8f  
    280280        void set_var( DeclarationWithType * newValue ) { var = newValue; }
    281281
     282        static VariableExpr * functionPointer( FunctionDecl * decl );
     283
    282284        virtual VariableExpr * clone() const { return new VariableExpr( * this ); }
    283285        virtual void accept( Visitor & v ) { v.visit( this ); }
  • src/SynTree/Mutator.cc

    rbd46af4 r8217e8f  
    480480}
    481481
     482Type *Mutator::mutate( ReferenceType *refType ) {
     483        mutateAll( refType->get_forall(), *this );
     484        refType->set_base( maybeMutate( refType->get_base(), *this ) );
     485        return refType;
     486}
     487
    482488Type *Mutator::mutate( FunctionType *functionType ) {
    483489        mutateAll( functionType->get_forall(), *this );
  • src/SynTree/Mutator.h

    rbd46af4 r8217e8f  
    9292        virtual Type* mutate( PointerType *pointerType );
    9393        virtual Type* mutate( ArrayType *arrayType );
     94        virtual Type* mutate( ReferenceType *refType );
    9495        virtual Type* mutate( FunctionType *functionType );
    9596        virtual Type* mutate( StructInstType *aggregateUseType );
  • src/SynTree/SynTree.h

    rbd46af4 r8217e8f  
    101101class PointerType;
    102102class ArrayType;
     103class ReferenceType;
    103104class FunctionType;
    104105class ReferenceToType;
  • src/SynTree/Type.cc

    rbd46af4 r8217e8f  
    6565const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
    6666
    67 Type *Type::stripDeclarator() {
     67Type * Type::stripDeclarator() {
    6868        Type * type = this;
    6969        while ( Type * at = InitTweak::getPointerBase( type ) ) {
     
    7272        return type;
    7373}
     74
     75Type * Type::stripReferences() {
     76        Type * type = this;
     77        while ( ReferenceType * ref = dynamic_cast<ReferenceType *>( type ) ) {
     78                type = ref->get_base();
     79        }
     80        return type;
     81}
     82
     83int Type::referenceDepth() const { return 0; }
    7484
    7585void Type::print( std::ostream &os, int indent ) const {
  • src/SynTree/Type.h

    rbd46af4 r8217e8f  
    162162
    163163        /// return type without outer pointers and arrays
    164         Type *stripDeclarator();
     164        Type * stripDeclarator();
     165
     166        /// return type without outer references
     167        Type * stripReferences();
     168
     169        /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
     170        virtual int referenceDepth() const;
    165171
    166172        virtual bool isComplete() const { return true; }
     
    256262        bool is_array() const { return isStatic || isVarLen || dimension; }
    257263
     264        virtual bool isComplete() const { return ! isVarLen; }
     265
    258266        virtual PointerType *clone() const { return new PointerType( *this ); }
    259267        virtual void accept( Visitor & v ) { v.visit( this ); }
     
    290298};
    291299
     300class ReferenceType : public Type {
     301public:
     302        Type *base;
     303
     304        ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     305        ReferenceType( const ReferenceType & );
     306        virtual ~ReferenceType();
     307
     308        Type *get_base() { return base; }
     309        void set_base( Type *newValue ) { base = newValue; }
     310
     311        virtual int referenceDepth() const;
     312
     313        virtual ReferenceType *clone() const { return new ReferenceType( *this ); }
     314        virtual void accept( Visitor & v ) { v.visit( this ); }
     315        virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }
     316        virtual void print( std::ostream & os, int indent = 0 ) const;
     317};
     318
    292319class FunctionType : public Type {
    293320  public:
  • src/SynTree/TypeExpr.cc

    rbd46af4 r8217e8f  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // TypeExpr.cc -- 
     7// TypeExpr.cc --
    88//
    99// Author           : Richard C. Bilson
  • src/SynTree/Visitor.cc

    rbd46af4 r8217e8f  
    368368void Visitor::visit( PointerType *pointerType ) {
    369369        acceptAll( pointerType->get_forall(), *this );
     370        // xxx - should PointerType visit/mutate dimension?
    370371        maybeAccept( pointerType->get_base(), *this );
    371372}
     
    375376        maybeAccept( arrayType->get_dimension(), *this );
    376377        maybeAccept( arrayType->get_base(), *this );
     378}
     379
     380void Visitor::visit( ReferenceType *refType ) {
     381        acceptAll( refType->get_forall(), *this );
     382        maybeAccept( refType->get_base(), *this );
    377383}
    378384
  • src/SynTree/Visitor.h

    rbd46af4 r8217e8f  
    9595        virtual void visit( PointerType *pointerType );
    9696        virtual void visit( ArrayType *arrayType );
     97        virtual void visit( ReferenceType *refType );
    9798        virtual void visit( FunctionType *functionType );
    9899        virtual void visit( StructInstType *aggregateUseType );
  • src/SynTree/module.mk

    rbd46af4 r8217e8f  
    2020       SynTree/PointerType.cc \
    2121       SynTree/ArrayType.cc \
     22       SynTree/ReferenceType.cc \
    2223       SynTree/FunctionType.cc \
    2324       SynTree/ReferenceToType.cc \
  • src/Tuples/Explode.h

    rbd46af4 r8217e8f  
    2626
    2727namespace Tuples {
    28         /// helper function used by explode to properly distribute
    29         /// '&' across a tuple expression
    30         Expression * distributeAddr( Expression * expr );
    31 
    3228        /// helper function used by explode
    3329        template< typename OutputIterator >
    3430        void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) {
    35                 if ( isTupleAssign ) {
    36                         // tuple assignment needs AddressExprs to be recursively exploded to easily get at all of the components
    37                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
    38                                 ResolvExpr::AltList alts;
    39                                 explodeUnique( addrExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
    40                                 for ( ResolvExpr::Alternative & alt : alts ) {
    41                                         // distribute '&' over all components
    42                                         alt.expr = distributeAddr( alt.expr );
    43                                         *out++ = alt;
    44                                 }
    45                                 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
    46                                 return;
    47                         }
    48                 }
    49                 Type * res = expr->get_result();
     31                Type * res = expr->get_result()->stripReferences();
    5032                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
    5133                        if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {
     
    5537                                }
    5638                        } else {
    57                                 // tuple type, but not tuple expr - recursively index into its components
     39                                // tuple type, but not tuple expr - recursively index into its components.
     40                                // if expr type is reference, convert to value type
    5841                                Expression * arg = expr->clone();
     42
     43                                if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) {
     44                                        // TODO: does this go here (inside uniqueexpr) or outside uniqueexpr? I'm guessing probably should go after...
     45                                        arg = new CastExpr( arg, tupleType->clone() );
     46                                }
    5947                                if ( Tuples::maybeImpure( arg ) && ! dynamic_cast< UniqueExpr * >( arg ) ) {
    6048                                        // expressions which may contain side effects require a single unique instance of the expression.
  • src/Tuples/TupleAssignment.cc

    rbd46af4 r8217e8f  
    2222#include "Explode.h"
    2323#include "Common/SemanticError.h"
     24#include "CodeGen/OperatorTable.h"
    2425#include "InitTweak/InitTweak.h"
    2526#include "InitTweak/GenInit.h"
     
    7778                if ( ! expr ) return false;
    7879                assert( expr->has_result() );
    79                 return dynamic_cast< TupleType * >( expr->get_result() );
     80                return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    8081        }
    8182
     
    8990        }
    9091
    91         bool pointsToTuple( Expression *expr ) {
     92        bool refToTuple( Expression *expr ) {
     93                assert( expr->get_result() );
    9294                // also check for function returning tuple of reference types
    9395                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    94                         return pointsToTuple( castExpr->get_arg() );
    95                 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
    96                         return isTuple( addr->get_arg() );
     96                        return refToTuple( castExpr->get_arg() );
     97                } else {
     98                        return isTuple( expr );
    9799                }
    98100                return false;
     
    109111        void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
    110112                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    111                         if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
     113                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    112114                                fname = op->get_name();
    113115                                for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    114116                                        if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
    115                                         if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
     117                                        if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
    116118                                                // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
    117119                                                continue;
     
    122124                                        const ResolvExpr::Alternative & alt1 = ali->front();
    123125                                        auto begin = std::next(ali->begin(), 1), end = ali->end();
    124                                         if ( pointsToTuple(alt1.expr) ) {
     126                                        if ( refToTuple(alt1.expr) ) {
    125127                                                if ( isMultAssign( begin, end ) ) {
    126128                                                        matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
     
    196198                        for ( ResolvExpr::Alternative & alt : lhs ) {
    197199                                Expression *& expr = alt.expr;
    198                                 Type * castType = expr->get_result()->clone();
    199                                 Type * type = InitTweak::getPointerBase( castType );
    200                                 assert( type );
     200                                Type * type = expr->get_result()->clone();
    201201                                type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    202                                 type->set_lvalue( true ); // xxx - might not need this
    203                                 expr = new CastExpr( expr, castType );
     202                                expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), type ) );
     203                        }
     204                }
     205
     206                for ( ResolvExpr::Alternative & alt : lhs ) {
     207                        // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here.
     208                        // TODO: can this somehow be merge with the cast code directly above?
     209                        if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) {
     210                                alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) );
    204211                        }
    205212                }
     
    221228                assert( left );
    222229                std::list< Expression * > args;
    223                 args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) );
     230                args.push_back( new VariableExpr( left ) );
    224231                // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
    225232                if ( right ) args.push_back( new VariableExpr( right ) );
     
    241248                assert( expr->has_result() && ! expr->get_result()->isVoid() );
    242249                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
    243                 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
    244                 ret->set_init( ctorInit );
    245                 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    246                 EnvRemover rm; // remove environments from subexpressions of StmtExprs
    247                 ctorInit->accept( rm );
     250                // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
     251                if ( ! dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     252                        ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
     253                        ret->set_init( ctorInit );
     254                        ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
     255                        EnvRemover rm; // remove environments from subexpressions of StmtExprs
     256                        ctorInit->accept( rm );
     257                }
    248258                return ret;
    249259        }
  • src/libcfa/concurrency/alarm.c

    rbd46af4 r8217e8f  
    4040__cfa_time_t zero_time = { 0 };
    4141
    42 void ?{}( __cfa_time_t * this ) { this->val = 0; }
    43 void ?{}( __cfa_time_t * this, zero_t zero ) { this->val = 0; }
    44 
    45 void ?{}( itimerval * this, __cfa_time_t * alarm ) {
    46         this->it_value.tv_sec = alarm->val / one_second;                        // seconds
    47         this->it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds
    48         this->it_interval.tv_sec = 0;
    49         this->it_interval.tv_usec = 0;
    50 }
    51 
    52 
    53 void ?{}( __cfa_time_t * this, timespec * curr ) {
     42void ?{}( __cfa_time_t & this ) { this.val = 0; }
     43void ?{}( __cfa_time_t & this, zero_t zero ) { this.val = 0; }
     44
     45void ?{}( itimerval & this, __cfa_time_t * alarm ) {
     46        this.it_value.tv_sec = alarm->val / one_second;                 // seconds
     47        this.it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds
     48        this.it_interval.tv_sec = 0;
     49        this.it_interval.tv_usec = 0;
     50}
     51
     52
     53void ?{}( __cfa_time_t & this, timespec * curr ) {
    5454        uint64_t secs  = curr->tv_sec;
    5555        uint64_t nsecs = curr->tv_nsec;
    56         this->val = (secs * one_second) + nsecs;
    57 }
    58 
    59 __cfa_time_t ?=?( __cfa_time_t * this, zero_t rhs ) {
    60         this->val = 0;
    61         return *this;
     56        this.val = (secs * one_second) + nsecs;
     57}
     58
     59__cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ) {
     60        this.val = 0;
     61        return this;
    6262}
    6363
     
    8686//=============================================================================================
    8787
    88 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
    89         this->thrd = thrd;
    90         this->alarm = alarm;
    91         this->period = period;
    92         this->next = 0;
    93         this->set = false;
    94         this->kernel_alarm = false;
    95 }
    96 
    97 void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
    98         this->proc = proc;
    99         this->alarm = alarm;
    100         this->period = period;
    101         this->next = 0;
    102         this->set = false;
    103         this->kernel_alarm = true;
    104 }
    105 
    106 void ^?{}( alarm_node_t * this ) {
    107         if( this->set ) {
    108                 unregister_self( this );
     88void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
     89        this.thrd = thrd;
     90        this.alarm = alarm;
     91        this.period = period;
     92        this.next = 0;
     93        this.set = false;
     94        this.kernel_alarm = false;
     95}
     96
     97void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {
     98        this.proc = proc;
     99        this.alarm = alarm;
     100        this.period = period;
     101        this.next = 0;
     102        this.set = false;
     103        this.kernel_alarm = true;
     104}
     105
     106void ^?{}( alarm_node_t & this ) {
     107        if( this.set ) {
     108                unregister_self( &this );
    109109        }
    110110}
  • src/libcfa/concurrency/alarm.h

    rbd46af4 r8217e8f  
    3636
    3737// ctors
    38 void ?{}( __cfa_time_t * this );
    39 void ?{}( __cfa_time_t * this, zero_t zero );
    40 void ?{}( __cfa_time_t * this, timespec * curr );
    41 void ?{}( itimerval * this, __cfa_time_t * alarm );
     38void ?{}( __cfa_time_t & this );
     39void ?{}( __cfa_time_t & this, zero_t zero );
     40void ?{}( __cfa_time_t & this, timespec * curr );
     41void ?{}( itimerval & this, __cfa_time_t * alarm );
    4242
    43 __cfa_time_t ?=?( __cfa_time_t * this, zero_t rhs );
     43__cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs );
    4444
    4545// logical ops
     
    105105typedef alarm_node_t ** __alarm_it_t;
    106106
    107 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
    108 void ?{}( alarm_node_t * this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
    109 void ^?{}( alarm_node_t * this );
     107void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
     108void ?{}( alarm_node_t & this, processor   * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );
     109void ^?{}( alarm_node_t & this );
    110110
    111111struct alarm_list_t {
     
    114114};
    115115
    116 static inline void ?{}( alarm_list_t * this ) {
    117         this->head = 0;
    118         this->tail = &this->head;
     116static inline void ?{}( alarm_list_t & this ) {
     117        this.head = 0;
     118        this.tail = &this.head;
    119119}
    120120
  • src/libcfa/concurrency/coroutine

    rbd46af4 r8217e8f  
    2525// Anything that is resumed is a coroutine.
    2626trait is_coroutine(dtype T) {
    27       void main(T * this);
    28       coroutine_desc * get_coroutine(T * this);
     27      void main(T & this);
     28      coroutine_desc * get_coroutine(T & this);
    2929};
    3030
    31 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X* this) { return &this->__cor; } void main(X* this)
     31#define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X& this) { return &this.__cor; } void main(X& this)
    3232
    3333//-----------------------------------------------------------------------------
    3434// Ctors and dtors
    35 void ?{}(coStack_t * this);
    36 void ?{}(coroutine_desc * this);
    37 void ?{}(coroutine_desc * this, const char * name);
    38 void ^?{}(coStack_t * this);
    39 void ^?{}(coroutine_desc * this);
     35void ?{}(coStack_t & this);
     36void ?{}(coroutine_desc & this);
     37void ?{}(coroutine_desc & this, const char * name);
     38void ^?{}(coStack_t & this);
     39void ^?{}(coroutine_desc & this);
    4040
    4141//-----------------------------------------------------------------------------
     
    4444
    4545forall(dtype T | is_coroutine(T))
    46 static inline void resume(T * cor);
     46static inline void resume(T & cor);
    4747
    4848forall(dtype T | is_coroutine(T))
    49 void prime(T * cor);
     49void prime(T & cor);
    5050
    5151//-----------------------------------------------------------------------------
     
    8686// Resume implementation inlined for performance
    8787forall(dtype T | is_coroutine(T))
    88 static inline void resume(T * cor) {
     88static inline void resume(T & cor) {
    8989        coroutine_desc * src = this_coroutine;          // optimization
    9090        coroutine_desc * dst = get_coroutine(cor);
     
    9292        if( unlikely(!dst->stack.base) ) {
    9393                create_stack(&dst->stack, dst->stack.size);
    94                 CtxStart(cor, CtxInvokeCoroutine);
     94                CtxStart(&cor, CtxInvokeCoroutine);
    9595        }
    9696
  • src/libcfa/concurrency/coroutine.c

    rbd46af4 r8217e8f  
    4040//-----------------------------------------------------------------------------
    4141// Coroutine ctors and dtors
    42 void ?{}(coStack_t* this) {
    43         this->size              = 65000;        // size of stack
    44         this->storage   = NULL; // pointer to stack
    45         this->limit             = NULL; // stack grows towards stack limit
    46         this->base              = NULL; // base of stack
    47         this->context   = NULL; // address of cfa_context_t
    48         this->top               = NULL; // address of top of storage
    49         this->userStack = false;
     42void ?{}(coStack_t& this) {
     43        this.size               = 65000;        // size of stack
     44        this.storage    = NULL; // pointer to stack
     45        this.limit              = NULL; // stack grows towards stack limit
     46        this.base               = NULL; // base of stack
     47        this.context    = NULL; // address of cfa_context_t
     48        this.top                = NULL; // address of top of storage
     49        this.userStack  = false;
    5050}
    5151
    52 void ?{}(coStack_t* this, size_t size) {
     52void ?{}(coStack_t& this, size_t size) {
    5353        this{};
    54         this->size = size;
     54        this.size = size;
    5555
    56         create_stack(this, this->size);
     56        create_stack(&this, this.size);
    5757}
    5858
    59 void ?{}(coroutine_desc* this) {
     59void ?{}(coroutine_desc& this) {
    6060        this{ "Anonymous Coroutine" };
    6161}
    6262
    63 void ?{}(coroutine_desc* this, const char * name) {
    64         this->name = name;
    65         this->errno_ = 0;
    66         this->state = Start;
    67         this->starter = NULL;
    68         this->last = NULL;
     63void ?{}(coroutine_desc& this, const char * name) {
     64        this.name = name;
     65        this.errno_ = 0;
     66        this.state = Start;
     67        this.starter = NULL;
     68        this.last = NULL;
    6969}
    7070
    71 void ?{}(coroutine_desc* this, size_t size) {
     71void ?{}(coroutine_desc& this, size_t size) {
    7272        this{};
    73         (&this->stack){size};
     73        (this.stack){size};
    7474}
    7575
    76 void ^?{}(coStack_t* this) {
    77         if ( ! this->userStack ) {
     76void ^?{}(coStack_t& this) {
     77        if ( ! this.userStack ) {
    7878                LIB_DEBUG_DO(
    79                         if ( mprotect( this->storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
    80                                 abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", this, errno, strerror( errno ) );
     79                        if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
     80                                abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    8181                        }
    8282                );
    83                 free( this->storage );
     83                free( this.storage );
    8484        }
    8585}
    8686
    87 void ^?{}(coroutine_desc* this) {}
     87void ^?{}(coroutine_desc& this) {}
    8888
    8989// Part of the Public API
    9090// Not inline since only ever called once per coroutine
    9191forall(dtype T | is_coroutine(T))
    92 void prime(T* cor) {
     92void prime(T& cor) {
    9393        coroutine_desc* this = get_coroutine(cor);
    9494        assert(this->state == Start);
  • src/libcfa/concurrency/invoke.h

    rbd46af4 r8217e8f  
    4747      #ifdef __CFORALL__
    4848      extern "Cforall" {
    49             void ?{}( struct __thread_queue_t * );
     49            void ?{}( struct __thread_queue_t & );
    5050            void append( struct __thread_queue_t *, struct thread_desc * );
    5151            struct thread_desc * pop_head( struct __thread_queue_t * );
    5252
    53             void ?{}( struct __condition_stack_t * );
     53            void ?{}( struct __condition_stack_t & );
    5454            void push( struct __condition_stack_t *, struct __condition_criterion_t * );
    5555            struct __condition_criterion_t * pop( struct __condition_stack_t * );
    5656
    57             void ?{}(spinlock * this);
    58             void ^?{}(spinlock * this);
     57            void ?{}(spinlock & this);
     58            void ^?{}(spinlock & this);
    5959      }
    6060      #endif
  • src/libcfa/concurrency/kernel

    rbd46af4 r8217e8f  
    3737};
    3838
    39 void  ?{}(semaphore * this, int count = 1);
    40 void ^?{}(semaphore * this);
     39void  ?{}(semaphore & this, int count = 1);
     40void ^?{}(semaphore & this);