Changeset 28e58fd


Ignore:
Timestamp:
Aug 25, 2017, 10:38:34 AM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
800d275
Parents:
af08051 (diff), 3eab308c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
4 added
147 edited
1 moved

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    raf08051 r28e58fd  
    192192                        genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
    193193                        output << ")" << endl;
     194                        output << indent;
    194195                }
    195196
     
    205206                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++ ) {
    206207                                updateLocation( *i );
     208                                output << indent;
    207209                                (*i)->accept( *this );
    208210                                output << ";" << endl;
     
    244246                                assert( obj );
    245247                                updateLocation( obj );
    246                                 output << mangleName( obj );
     248                                output << indent << mangleName( obj );
    247249                                if ( obj->get_init() ) {
    248250                                        output << " = ";
     
    332334        void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){
    333335                assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
    334                 // xxx - generate something reasonable for constructor/destructor pairs
    335                 output << "<ctorinit>";
     336                // pseudo-output for constructor/destructor pairs
     337                output << "<ctorinit>{" << std::endl << ++indent << "ctor: ";
     338                maybeAccept( init->get_ctor(), *this );
     339                output << ", " << std::endl << indent << "dtor: ";
     340                maybeAccept( init->get_dtor(), *this );
     341                output << std::endl << --indent << "}";
    336342        }
    337343
     
    347353                        if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) {
    348354                                std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
    349                                 switch ( opInfo.type ) {
    350                                   case OT_PREFIXASSIGN:
    351                                   case OT_POSTFIXASSIGN:
    352                                   case OT_INFIXASSIGN:
    353                                   case OT_CTOR:
    354                                   case OT_DTOR:
    355                                         {
    356                                                 assert( arg != applicationExpr->get_args().end() );
    357                                                 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
    358                                                         // remove & from first assignment/ctor argument
    359                                                         *arg = addrExpr->get_arg();
    360                                                 } else {
    361                                                         // no address-of operator, so must be a pointer - add dereference
    362                                                         // NOTE: if the assertion starts to trigger, check that the application expr isn't being shared.
    363                                                         // Since its arguments are modified here, this assertion most commonly triggers when the application
    364                                                         // is visited multiple times.
    365                                                         UntypedExpr * newExpr = new UntypedExpr( new NameExpr( "*?" ) );
    366                                                         newExpr->get_args().push_back( *arg );
    367                                                         Type * type = InitTweak::getPointerBase( (*arg)->get_result() );
    368                                                         assertf( type, "First argument to a derefence must be a pointer. Ensure that expressions are not being shared." );
    369                                                         newExpr->set_result( type->clone() );
    370                                                         *arg = newExpr;
    371                                                 } // if
    372                                                 break;
    373                                         }
    374 
    375                                   default:
    376                                         // do nothing
    377                                         ;
    378                                 } // switch
    379 
    380355                                switch ( opInfo.type ) {
    381356                                  case OT_INDEX:
     
    584559                if ( castExpr->get_result()->isVoid() ) {
    585560                        output << "(void)" ;
    586                 } else if ( ! castExpr->get_result()->get_lvalue() ) {
    587                         // at least one result type of cast, but not an lvalue
     561                } else {
     562                        // at least one result type of cast.
     563                        // Note: previously, lvalue casts were skipped. Since it's now impossible for the user to write
     564                        // an lvalue cast, this has been taken out.
    588565                        output << "(";
    589566                        output << genType( castExpr->get_result(), "", pretty, genC );
    590567                        output << ")";
    591                 } else {
    592                         // otherwise, the cast is to an lvalue type, so the cast should be dropped, since the result of a cast is
    593                         // never an lvalue in C
    594568                } // if
    595569                castExpr->get_arg()->accept( *this );
     
    706680                extension( commaExpr );
    707681                output << "(";
     682                if ( genC ) {
     683                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
     684                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     685                }
    708686                commaExpr->get_arg1()->accept( *this );
    709687                output << " , ";
    710688                commaExpr->get_arg2()->accept( *this );
    711689                output << ")";
     690        }
     691
     692        void CodeGenerator::visit( TupleAssignExpr * tupleExpr ) {
     693                assertf( ! genC, "TupleAssignExpr should not reach code generation." );
     694                tupleExpr->stmtExpr->accept( *this );
    712695        }
    713696
     
    759742                output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
    760743                compLitExpr->get_initializer()->accept( *this );
     744        }
     745
     746        void CodeGenerator::visit( UniqueExpr * unqExpr ) {
     747                assertf( ! genC, "Unique expressions should not reach code generation." );
     748                output << "unq<" << unqExpr->get_id() << ">{ ";
     749                unqExpr->get_expr()->accept( *this );
     750                output << " }";
    761751        }
    762752
     
    770760                for ( Statement * stmt : stmts ) {
    771761                        updateLocation( stmt );
    772             output << printLabels( stmt->get_labels() );
     762                        output << printLabels( stmt->get_labels() );
    773763                        if ( i+1 == numStmts ) {
    774764                                // last statement in a statement expression needs to be handled specially -
     
    815805        void CodeGenerator::visit( ExprStmt * exprStmt ) {
    816806                assert( exprStmt );
    817                 Expression * expr = exprStmt->get_expr();
    818807                if ( genC ) {
    819808                        // cast the top-level expression to void to reduce gcc warnings.
    820                         expr = new CastExpr( expr );
    821                 }
    822                 expr->accept( *this );
     809                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     810                }
     811                exprStmt->get_expr()->accept( *this );
    823812                output << ";";
    824813        }
  • src/CodeGen/CodeGenerator.h

    raf08051 r28e58fd  
    7474                virtual void visit( CommaExpr *commaExpr );
    7575                virtual void visit( CompoundLiteralExpr *compLitExpr );
     76                virtual void visit( UniqueExpr * );
     77                virtual void visit( TupleAssignExpr * tupleExpr );
    7678                virtual void visit( UntypedTupleExpr *tupleExpr );
    7779                virtual void visit( TupleExpr *tupleExpr );
  • src/CodeGen/GenType.cc

    raf08051 r28e58fd  
    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 );
     
    145146        void GenType::visit( ArrayType *arrayType ) {
    146147                genArray( arrayType->get_qualifiers(), arrayType->get_base(), arrayType->get_dimension(), arrayType->get_isVarLen(), arrayType->get_isStatic() );
     148        }
     149
     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 );
    147156        }
    148157
     
    278287                        typeString = "_Atomic " + typeString;
    279288                } // if
     289                if ( type->get_lvalue() && ! genC ) {
     290                        // when not generating C code, print lvalue for debugging.
     291                        typeString = "lvalue " + typeString;
     292                }
    280293        }
    281294} // namespace CodeGen
  • src/CodeGen/OperatorTable.cc

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    116116        virtual void visit( PointerType *pointerType ) override final;
    117117        virtual void visit( ArrayType *arrayType ) override final;
     118        virtual void visit( ReferenceType *referenceType ) override final;
    118119        virtual void visit( FunctionType *functionType ) override final;
    119120        virtual void visit( StructInstType *aggregateUseType ) override final;
     
    202203        virtual Type* mutate( PointerType *pointerType ) override final;
    203204        virtual Type* mutate( ArrayType *arrayType ) override final;
     205        virtual Type* mutate( ReferenceType *referenceType ) override final;
    204206        virtual Type* mutate( FunctionType *functionType ) override final;
    205207        virtual Type* mutate( StructInstType *aggregateUseType ) override final;
  • src/Common/PassVisitor.impl.h

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    310310template< typename T1, typename T2 >
    311311struct group_iterate_t {
    312         group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {
    313                 assertf(v1.size() == v2.size(), "group iteration requires containers of the same size.");
     312        group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) {
     313                assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%zd, %zd>.", v1.size(), v2.size());
    314314        };
    315315
     
    336336};
    337337
     338/// performs bounds check to ensure that all arguments are of the same length.
    338339template< typename... Args >
    339340group_iterate_t<Args...> group_iterate( Args &&... args ) {
    340         return group_iterate_t<Args...>(std::forward<Args>( args )...);
     341        return group_iterate_t<Args...>(false, std::forward<Args>( args )...);
     342}
     343
     344/// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
     345template< typename... Args >
     346group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
     347        return group_iterate_t<Args...>(true, std::forward<Args>( args )...);
    341348}
    342349
  • src/Concurrency/Keywords.cc

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    2525
    2626#include "Box.h"
     27
     28#include "CodeGen/OperatorTable.h"
    2729#include "Common/ScopedMap.h"            // for ScopedMap, ScopedMap<>::iter...
    2830#include "Common/SemanticError.h"        // for SemanticError
     
    564566                        // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
    565567                        if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
    566                                 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
     568                                if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
    567569                                        assert( assign->get_args().size() == 2 );
    568570                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
     
    604606                                                }
    605607                                        } else {
    606                                                 throw SemanticError( "Cannot pass non-struct type for generic struct" );
     608                                                throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
    607609                                        }
    608610                                }
     
    10191021                                                } // if
    10201022                                                if ( baseType1 || baseType2 ) {
     1023                                                        delete ret->get_result();
    10211024                                                        ret->set_result( appExpr->get_result()->clone() );
    10221025                                                        if ( appExpr->get_env() ) {
     
    10321035                                                assert( ! appExpr->get_args().empty() );
    10331036                                                if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
     1037                                                        // remove dereference from polymorphic types since they are boxed.
    10341038                                                        Expression *ret = appExpr->get_args().front();
     1039                                                        // fix expr type to remove pointer
    10351040                                                        delete ret->get_result();
    10361041                                                        ret->set_result( appExpr->get_result()->clone() );
     
    11221127
    11231128                        assert( appExpr->get_function()->has_result() );
    1124                         PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
    1125                         FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
     1129                        FunctionType * function = getFunctionType( appExpr->get_function()->get_result() );
     1130                        assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() );
    11261131
    11271132                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
     
    12001205                                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
    12011206                                                                assert( appExpr->get_function()->has_result() );
    1202                                                                 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
    1203                                                                 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
     1207                                                                FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
     1208                                                                assert( function );
    12041209                                                                needs = needsAdapter( function, scopeTyVars );
    12051210                                                        } // if
     
    12101215                        // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
    12111216                        // out of the if condition.
     1217                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
     1218                        // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
    12121219                        bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
    1213                         addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
    12141220                        if ( polytype || needs ) {
    12151221                                Expression *ret = addrExpr->get_arg();
     
    12781284                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    12791285                                        std::string adapterName = makeAdapterName( mangleName );
    1280                                         paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) );
     1286                                        // adapter may not be used in body, pass along with unused attribute.
     1287                                        paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
    12811288                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
    12821289                                }
     
    13841391                        std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
    13851392                        std::list< DeclarationWithType *> inferredParams;
    1386                         ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
     1393                        // size/align/offset parameters may not be used in body, pass along with unused attribute.
     1394                        ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0,
     1395                                           { new Attribute( "unused" ) } );
    13871396                        ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
    13881397                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
     
    14071416                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
    14081417//      *assert = (*assert)->acceptMutator( *this );
     1418                                        // assertion parameters may not be used in body, pass along with unused attribute.
     1419                                        (*assert)->get_attributes().push_back( new Attribute( "unused" ) );
    14091420                                        inferredParams.push_back( *assert );
    14101421                                }
  • src/GenPoly/InstantiateGeneric.cc

    raf08051 r28e58fd  
    162162                /// Should not make use of type environment to replace types of function parameter and return values.
    163163                bool inFunctionType = false;
     164                /// Index of current member, used to recreate MemberExprs with the member from an instantiation
     165                int memberIndex = -1;
    164166                GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {}
    165167
     
    167169                Type* postmutate( UnionInstType *inst );
    168170
    169                 void premutate( __attribute__((unused)) FunctionType * ftype ) {
     171                // fix MemberExprs to use the member from the instantiation
     172                void premutate( MemberExpr * memberExpr );
     173                Expression * postmutate( MemberExpr * memberExpr );
     174
     175                void premutate( FunctionType * ) {
    170176                        GuardValue( inFunctionType );
    171177                        inFunctionType = true;
     
    414420        }
    415421
     422        namespace {
     423                bool isGenericType( Type * t ) {
     424                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     425                                return ! inst->parameters.empty();
     426                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     427                                return ! inst->parameters.empty();
     428                        }
     429                        return false;
     430                }
     431
     432                AggregateDecl * getAggr( Type * t ) {
     433                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     434                                return inst->baseStruct;
     435                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     436                                return inst->baseUnion;
     437                        }
     438                        assertf( false, "Non-aggregate type: %s", toString( t ).c_str() );
     439                }
     440        }
     441
     442        void GenericInstantiator::premutate( MemberExpr * memberExpr ) {
     443                GuardValue( memberIndex );
     444                memberIndex = -1;
     445                if ( isGenericType( memberExpr->aggregate->result ) ) {
     446                        // find the location of the member
     447                        AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     448                        std::list< Declaration * > & members = aggr->members;
     449                        memberIndex = std::distance( members.begin(), std::find( members.begin(), members.end(), memberExpr->member ) );
     450                        assertf( memberIndex < (int)members.size(), "Could not find member %s in generic type %s", toString( memberExpr->member ).c_str(), toString( memberExpr->aggregate ).c_str() );
     451                }
     452        }
     453
     454        Expression * GenericInstantiator::postmutate( MemberExpr * memberExpr ) {
     455                if ( memberIndex != -1 ) {
     456                        // using the location from the generic type, find the member in the instantiation and rebuild the member expression
     457                        AggregateDecl * aggr = getAggr( memberExpr->aggregate->result );
     458                        assertf( memberIndex < (int)aggr->members.size(), "Instantiation somehow has fewer members than the generic type." );
     459                        Declaration * member = *std::next( aggr->members.begin(), memberIndex );
     460                        assertf( member->name == memberExpr->member->name, "Instantiation has different member order than the generic type. %s / %s", toString( member ).c_str(), toString( memberExpr->member ).c_str() );
     461                        DeclarationWithType * field = safe_dynamic_cast< DeclarationWithType * >( member );
     462                        MemberExpr * ret = new MemberExpr( field, memberExpr->aggregate->clone() );
     463                        std::swap( ret->env, memberExpr->env );
     464                        delete memberExpr;
     465                        return ret;
     466                }
     467                return memberExpr;
     468        }
     469
    416470        void GenericInstantiator::beginScope() {
    417471                instantiations.beginScope();
  • src/GenPoly/Lvalue.cc

    raf08051 r28e58fd  
    1717#include <string>                        // for string
    1818
     19#include "Common/PassVisitor.h"
    1920#include "Common/SemanticError.h"        // for SemanticError
    2021#include "GenPoly.h"                     // for isPolyType
    2122#include "Lvalue.h"
     23
    2224#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2325#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2426#include "ResolvExpr/Unify.h"            // for unify
     27#include "ResolvExpr/typeops.h"
     28#include "SymTab/Autogen.h"
    2529#include "SymTab/Indexer.h"              // for Indexer
    2630#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
     
    3135#include "SynTree/Visitor.h"             // for Visitor, acceptAll
    3236
     37#if 0
     38#define PRINT(x) x
     39#else
     40#define PRINT(x)
     41#endif
     42
    3343namespace GenPoly {
    3444        namespace {
    35                 /// Replace uses of lvalue returns with appropriate pointers
    36                 class Pass1 : public Mutator {
    37                   public:
    38                         Pass1();
    39 
    40                         virtual Expression *mutate( ApplicationExpr *appExpr );
    41                         virtual Statement *mutate( ReturnStmt *appExpr );
    42                         virtual DeclarationWithType *mutate( FunctionDecl *funDecl );
    43                   private:
    44                         DeclarationWithType* retval;
    45                 };
    46 
    47                 /// Replace declarations of lvalue returns with appropriate pointers
    48                 class Pass2 : public Visitor {
    49                   public:
    50                         virtual void visit( FunctionType *funType );
    51                   private:
     45                // TODO: fold this into the general createDeref function??
     46                Expression * mkDeref( Expression * arg ) {
     47                        if ( SymTab::dereferenceOperator ) {
     48                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     49                                deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
     50                                Type * base = InitTweak::getPointerBase( arg->get_result() );
     51                                assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
     52                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
     53                                delete ret->get_result();
     54                                ret->set_result( base->clone() );
     55                                ret->get_result()->set_lvalue( true );
     56                                return ret;
     57                        } else {
     58                                return UntypedExpr::createDeref( arg );
     59                        }
     60                }
     61
     62                struct ReferenceConversions final {
     63                        Expression * postmutate( CastExpr * castExpr );
     64                        Expression * postmutate( AddressExpr * addrExpr );
     65                };
     66
     67                /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
     68                struct FixIntrinsicArgs final {
     69                        Expression * postmutate( ApplicationExpr * appExpr );
     70                };
     71
     72                struct FixIntrinsicResult final : public WithGuards {
     73                        Expression * postmutate( ApplicationExpr * appExpr );
     74                        void premutate( FunctionDecl * funcDecl );
     75                        bool inIntrinsic = false;
     76                };
     77
     78                /// Replace reference types with pointer types
     79                struct ReferenceTypeElimination final {
     80                        Type * postmutate( ReferenceType * refType );
    5281                };
    5382
     
    5584                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    5685                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    57                 class GeneralizedLvalue : public Mutator {
    58                         typedef Mutator Parent;
    59 
    60                         virtual Expression * mutate( MemberExpr * memExpr );
    61                         virtual Expression * mutate( AddressExpr * addressExpr );
     86                struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
     87                        Expression * postmutate( AddressExpr * addressExpr );
     88                        Expression * postmutate( MemberExpr * memExpr );
    6289
    6390                        template<typename Func>
    6491                        Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
    6592                };
     93
     94                /// Removes redundant &*/*& pattern that this pass can generate
     95                struct CollapseAddrDeref final {
     96                        Expression * postmutate( AddressExpr * addressExpr );
     97                        Expression * postmutate( ApplicationExpr * appExpr );
     98                };
     99
     100                struct AddrRef final : public WithGuards {
     101                        void premutate( AddressExpr * addrExpr );
     102                        Expression * postmutate( AddressExpr * addrExpr );
     103                        void premutate( Expression * expr );
     104
     105                        bool first = true;
     106                        bool current = false;
     107                        int refDepth = 0;
     108                };
    66109        } // namespace
    67110
     111        static bool referencesEliminated = false;
     112        // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
     113        bool referencesPermissable() {
     114                return ! referencesEliminated;
     115        }
     116
    68117        void convertLvalue( std::list< Declaration* >& translationUnit ) {
    69                 Pass1 p1;
    70                 Pass2 p2;
    71                 GeneralizedLvalue genLval;
    72                 mutateAll( translationUnit, p1 );
    73                 acceptAll( translationUnit, p2 );
     118                PassVisitor<ReferenceConversions> refCvt;
     119                PassVisitor<ReferenceTypeElimination> elim;
     120                PassVisitor<GeneralizedLvalue> genLval;
     121                PassVisitor<FixIntrinsicArgs> fixer;
     122                PassVisitor<CollapseAddrDeref> collapser;
     123                PassVisitor<AddrRef> addrRef;
     124                PassVisitor<FixIntrinsicResult> intrinsicResults;
     125                mutateAll( translationUnit, intrinsicResults );
     126                mutateAll( translationUnit, addrRef );
     127                mutateAll( translationUnit, refCvt );
     128                mutateAll( translationUnit, fixer );
     129                mutateAll( translationUnit, collapser );
    74130                mutateAll( translationUnit, genLval );
     131                mutateAll( translationUnit, elim );  // last because other passes need reference types to work
     132
     133                // from this point forward, no other pass should create reference types.
     134                referencesEliminated = true;
    75135        }
    76136
    77137        Expression * generalizedLvalue( Expression * expr ) {
    78                 GeneralizedLvalue genLval;
     138                PassVisitor<GeneralizedLvalue> genLval;
    79139                return expr->acceptMutator( genLval );
    80140        }
    81141
    82142        namespace {
    83                 Type* isLvalueRet( FunctionType *function ) {
    84                         if ( function->get_returnVals().empty() ) return 0;
    85                         Type *ty = function->get_returnVals().front()->get_type();
    86                         return ty->get_lvalue() ? ty : 0;
    87                 }
    88 
    89                 bool isIntrinsicApp( ApplicationExpr *appExpr ) {
    90                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
    91                                 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
    92                         } else {
    93                                 return false;
    94                         } // if
    95                 }
    96 
    97                 Pass1::Pass1() {
    98                 }
    99 
    100                 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) {
    101                         if ( funcDecl->get_statements() ) {
    102                                 DeclarationWithType* oldRetval = retval;
    103                                 retval = 0;
    104                                 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) {
    105                                         retval = funcDecl->get_functionType()->get_returnVals().front();
    106                                 }
    107                                 // fix expressions and return statements in this function
    108                                 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) );
    109                                 retval = oldRetval;
    110                         } // if
    111                         return funcDecl;
    112                 }
    113 
    114                 Expression * Pass1::mutate( ApplicationExpr *appExpr ) {
    115                         appExpr->get_function()->acceptMutator( *this );
    116                         mutateAll( appExpr->get_args(), *this );
    117 
    118                         PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    119                         FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    120 
    121                         Type *funType = isLvalueRet( function );
    122                         if ( funType && ! isIntrinsicApp( appExpr ) ) {
    123                                 Expression *expr = appExpr;
    124                                 Type *appType = appExpr->get_result();
    125                                 if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
    126                                         // make sure cast for polymorphic type is inside dereference
    127                                         expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
    128                                 }
    129                                 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    130                                 deref->set_result( appType->clone() );
    131                                 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
    132                                 deref->get_args().push_back( expr );
    133                                 return deref;
    134                         } else {
    135                                 return appExpr;
    136                         } // if
    137                 }
    138 
    139                 Statement * Pass1::mutate(ReturnStmt *retStmt) {
    140                         if ( retval && retStmt->get_expr() ) {
    141                                 if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
    142                                         // ***** Code Removal ***** because casts may be stripped already
    143 
    144                                         // strip casts because not allowed to take address of cast
    145                                         // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) {
    146                                         //      retStmt->set_expr( castExpr->get_arg() );
    147                                         //      retStmt->get_expr()->set_env( castExpr->get_env() );
    148                                         //      castExpr->set_env( 0 );
    149                                         //      castExpr->set_arg( 0 );
    150                                         //      delete castExpr;
    151                                         // } // while
    152                                         retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) );
     143                // true for intrinsic function calls that return a reference
     144                bool isIntrinsicReference( Expression * expr ) {
     145                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
     146                                std::string fname = InitTweak::getFunctionName( untyped );
     147                                // known intrinsic-reference prelude functions
     148                                return fname == "*?" || fname == "?[?]";
     149                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
     150                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
     151                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     152                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     153                                        Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
     154                                        return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
     155                                }
     156                        }
     157                        return false;
     158                }
     159
     160                Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
     161                        if ( isIntrinsicReference( appExpr ) ) {
     162                                // eliminate reference types from intrinsic applications - now they return lvalues
     163                                Type * result = appExpr->get_result();
     164                                appExpr->set_result( result->stripReferences()->clone() );
     165                                appExpr->get_result()->set_lvalue( true );
     166                                if ( ! inIntrinsic ) {
     167                                        // when not in an intrinsic function, add a cast to
     168                                        // don't add cast when in an intrinsic function, since they already have the cast
     169                                        Expression * ret = new CastExpr( appExpr, result );
     170                                        ret->set_env( appExpr->get_env() );
     171                                        appExpr->set_env( nullptr );
     172                                        return ret;
     173                                }
     174                                delete result;
     175                        }
     176                        return appExpr;
     177                }
     178
     179                void FixIntrinsicResult::premutate( FunctionDecl * funcDecl ) {
     180                        GuardValue( inIntrinsic );
     181                        inIntrinsic =  funcDecl->linkage == LinkageSpec::Intrinsic;
     182                }
     183
     184                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
     185                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
     186                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     187                                FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
     188                                assertf( ftype, "Function declaration does not have function type." );
     189                                // can be of differing lengths only when function is variadic
     190                                assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
     191
     192
     193                                unsigned int i = 0;
     194                                const unsigned int end = ftype->get_parameters().size();
     195                                for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
     196                                        if (i == end) break;
     197                                        Expression *& arg = std::get<0>( p );
     198                                        Type * formal = std::get<1>( p )->get_type();
     199                                        PRINT(
     200                                                std::cerr << "pair<0>: " << arg << std::endl;
     201                                                std::cerr << "pair<1>: " << formal << std::endl;
     202                                        )
     203                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
     204                                                if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
     205                                                        if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
     206                                                                // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
     207                                                                PRINT(
     208                                                                        std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     209                                                                )
     210                                                                arg = new AddressExpr( arg );
     211                                                        }
     212                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     213                                                        // std::cerr << "===adding deref to arg" << std::endl;
     214                                                        // if the parameter is a reference, add a dereference to the reference-typed argument.
     215                                                        Type * baseType = InitTweak::getPointerBase( arg->get_result() );
     216                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
     217                                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
     218                                                        delete arg->get_result();
     219                                                        arg->set_result( ptrType );
     220                                                        arg = mkDeref( arg );
     221                                                }
     222                                        }
     223                                        ++i;
     224                                }
     225                        }
     226                        return appExpr;
     227                }
     228
     229                // idea: &&&E: get outer &, inner &
     230                // at inner &, record depth D of reference type
     231                // at outer &, add D derefs.
     232                void AddrRef::premutate( Expression * ) {
     233                        GuardValue( current );
     234                        GuardValue( first );
     235                        current = false;
     236                        first = true;
     237                }
     238
     239                void AddrRef::premutate( AddressExpr * ) {
     240                        GuardValue( current );
     241                        GuardValue( first );
     242                        current = first;
     243                        first = false;
     244                        if ( current ) {
     245                                GuardValue( refDepth );
     246                                refDepth = 0;
     247                        }
     248                }
     249
     250                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
     251                        if ( refDepth == 0 ) {
     252                                if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
     253                                        // try to avoid ?[?]
     254                                        refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
     255                                }
     256                        }
     257                        if ( current ) {
     258                                Expression * ret = addrExpr;
     259                                while ( refDepth ) {
     260                                        ret = mkDeref( ret );
     261                                        refDepth--;
     262                                }
     263                                return ret;
     264                        }
     265                        return addrExpr;
     266                }
     267
     268                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
     269                        // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
     270                        // In this case, remove the outer address expression and return the argument.
     271                        // TODO: It's possible that this might catch too much and require a more sophisticated check.
     272                        return addrExpr;
     273                }
     274
     275                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
     276                        // xxx - is it possible to convert directly between reference types with a different base? E.g.,
     277                        //   int x;
     278                        //   (double&)x;
     279                        // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
     280                        // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
     281                        // pointer casts in the right places.
     282
     283                        // conversion to reference type
     284                        if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
     285                                (void)refType;
     286                                if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     287                                        // nothing to do if casting from reference to reference.
     288                                        (void)otherRef;
     289                                        PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
     290                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
     291                                                Expression * callExpr = castExpr->get_arg();
     292                                                PRINT(
     293                                                        std::cerr << "but arg is deref -- &" << std::endl;
     294                                                        std::cerr << callExpr << std::endl;
     295                                                )
     296                                                callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
     297                                                delete callExpr->get_result();
     298                                                callExpr->set_result( refType->clone() );
     299                                                // move environment out to new top-level
     300                                                callExpr->set_env( castExpr->get_env() );
     301                                                castExpr->set_arg( nullptr );
     302                                                castExpr->set_env( nullptr );
     303                                                delete castExpr;
     304                                                return callExpr;
     305                                        }
     306                                        int depth1 = refType->referenceDepth();
     307                                        int depth2 = otherRef->referenceDepth();
     308                                        int diff = depth1-depth2;
     309                                        if ( diff == 0 ) {
     310                                                assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
     311                                                PRINT( std::cerr << castExpr << std::endl; )
     312                                                return castExpr;
     313                                        } else if ( diff < 0 ) {
     314                                                Expression * ret = castExpr->get_arg();
     315                                                for ( int i = 0; i < diff; ++i ) {
     316                                                        ret = mkDeref( ret );
     317                                                }
     318                                                ret->set_env( castExpr->get_env() );
     319                                                delete ret->get_result();
     320                                                ret->set_result( castExpr->get_result() );
     321                                                castExpr->set_env( nullptr );
     322                                                castExpr->set_arg( nullptr );
     323                                                castExpr->set_result( nullptr );
     324                                                delete castExpr;
     325                                                return ret;
     326                                        } else if ( diff > 0 ) {
     327                                                Expression * ret = castExpr->get_arg();
     328                                                for ( int i = 0; i < diff; ++i ) {
     329                                                        ret = new AddressExpr( ret );
     330                                                }
     331                                                ret->set_env( castExpr->get_env() );
     332                                                delete ret->get_result();
     333                                                ret->set_result( castExpr->get_result() );
     334                                                castExpr->set_env( nullptr );
     335                                                castExpr->set_arg( nullptr );
     336                                                castExpr->set_result( nullptr );
     337                                                delete castExpr;
     338                                                return ret;
     339                                        }
     340
     341                                        assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
     342                                        PRINT( std::cerr << castExpr << std::endl; )
     343                                        return castExpr;
     344                                } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
     345                                        // conversion from lvalue to reference
     346                                        // xxx - keep cast, but turn into pointer cast??
     347                                        // xxx - memory
     348                                        PRINT(
     349                                                std::cerr << "convert lvalue to reference -- &" << std::endl;
     350                                                std::cerr << castExpr->get_arg() << std::endl;
     351                                        )
     352                                        AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
     353                                        if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
     354                                                // must keep cast if cast-to type is different from the actual type
     355                                                castExpr->set_arg( ret );
     356                                                return castExpr;
     357                                        }
     358                                        ret->set_env( castExpr->get_env() );
     359                                        delete ret->get_result();
     360                                        ret->set_result( castExpr->get_result() );
     361                                        castExpr->set_env( nullptr );
     362                                        castExpr->set_arg( nullptr );
     363                                        castExpr->set_result( nullptr );
     364                                        delete castExpr;
     365                                        return ret;
    153366                                } else {
    154                                         throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" );
    155                                 } // if
    156                         } // if
    157                         return retStmt;
    158                 }
    159 
    160                 void Pass2::visit( FunctionType *funType ) {
    161                         std::string typeName;
    162                         if ( isLvalueRet( funType ) ) {
    163                                 DeclarationWithType *retParm = funType->get_returnVals().front();
    164 
    165                                 // make a new parameter that is a pointer to the type of the old return value
    166                                 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
    167                         } // if
    168 
    169                         Visitor::visit( funType );
     367                                        // rvalue to reference conversion -- introduce temporary
     368                                }
     369                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
     370                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     371                                (void)refType;
     372                                // conversion from reference to rvalue
     373                                PRINT(
     374                                        std::cerr << "convert reference to rvalue -- *" << std::endl;
     375                                        std::cerr << "was = " << castExpr << std::endl;
     376                                )
     377                                Expression * ret = castExpr->get_arg();
     378                                TypeSubstitution * env = castExpr->get_env();
     379                                castExpr->set_env( nullptr );
     380                                if ( ! isIntrinsicReference( ret ) ) {
     381                                        // dereference if not already dereferenced
     382                                        ret = mkDeref( ret );
     383                                }
     384                                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
     385                                        // can remove cast if types are compatible, changing expression type to value type
     386                                        ret->set_result( castExpr->get_result()->clone() );
     387                                        castExpr->set_arg( nullptr );
     388                                        delete castExpr;
     389                                } else {
     390                                        // must keep cast if types are different
     391                                        castExpr->set_arg( ret );
     392                                        ret = castExpr;
     393                                }
     394                                ret->set_env( env );
     395                                PRINT( std::cerr << "now: " << ret << std::endl; )
     396                                return ret;
     397                        }
     398                        return castExpr;
     399                }
     400
     401                Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
     402                        Type * base = refType->get_base();
     403                        Type::Qualifiers qualifiers = refType->get_qualifiers();
     404                        refType->set_base( nullptr );
     405                        delete refType;
     406                        return new PointerType( qualifiers, base );
    170407                }
    171408
     
    175412                                Expression * arg1 = commaExpr->get_arg1()->clone();
    176413                                Expression * arg2 = commaExpr->get_arg2()->clone();
    177                                 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );
     414                                Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
    178415                                ret->set_env( expr->get_env() );
    179416                                expr->set_env( nullptr );
    180417                                delete expr;
    181                                 return ret->acceptMutator( *this );
     418                                return ret;
    182419                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
    183420                                Expression * arg1 = condExpr->get_arg1()->clone();
    184421                                Expression * arg2 = condExpr->get_arg2()->clone();
    185422                                Expression * arg3 = condExpr->get_arg3()->clone();
    186                                 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ), mkExpr( arg3 ) );
     423                                ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
    187424                                ret->set_env( expr->get_env() );
    188425                                expr->set_env( nullptr );
     
    197434                                unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
    198435                                ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
    199                                 return ret->acceptMutator( *this );
     436                                return ret;
    200437                        }
    201438                        return expr;
    202439                }
    203440
    204                 Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) {
    205                         Parent::mutate( memExpr );
     441                Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
    206442                        return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
    207443                }
    208444
    209                 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
    210                         addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
     445                Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
    211446                        return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
     447                }
     448
     449                Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
     450                        Expression * arg = addrExpr->get_arg();
     451                        if ( isIntrinsicReference( arg ) ) {
     452                                std::string fname = InitTweak::getFunctionName( arg );
     453                                if ( fname == "*?" ) {
     454                                        Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
     455                                        Expression * ret = arg0;
     456                                        ret->set_env( addrExpr->get_env() );
     457                                        arg0 = nullptr;
     458                                        addrExpr->set_env( nullptr );
     459                                        delete addrExpr;
     460                                        return ret;
     461                                }
     462                        }
     463                        return addrExpr;
     464                }
     465
     466                Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
     467                        if ( isIntrinsicReference( appExpr ) ) {
     468                                std::string fname = InitTweak::getFunctionName( appExpr );
     469                                if ( fname == "*?" ) {
     470                                        Expression * arg = InitTweak::getCallArg( appExpr, 0 );
     471                                        // xxx - this isn't right, because it can remove casts that should be there...
     472                                        // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
     473                                        //      arg = castExpr->get_arg();
     474                                        // }
     475                                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
     476                                                Expression * ret = addrExpr->get_arg();
     477                                                ret->set_env( appExpr->get_env() );
     478                                                addrExpr->set_arg( nullptr );
     479                                                appExpr->set_env( nullptr );
     480                                                delete appExpr;
     481                                                return ret;
     482                                        }
     483                                }
     484                        }
     485                        return appExpr;
    212486                }
    213487        } // namespace
  • src/GenPoly/Lvalue.h

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

    raf08051 r28e58fd  
    131131                        // conversion of 0 (null) to function type does not require tuple specialization
    132132                        if ( dynamic_cast< ZeroType * >( actualType ) ) return false;
    133                         FunctionType * aftype = getFunctionType( actualType );
    134                         assertf( aftype, "formal type is a function type, but actual type is not." );
     133                        FunctionType * aftype = getFunctionType( actualType->stripReferences() );
     134                        assertf( aftype, "formal type is a function type, but actual type is not: %s", toString( actualType ).c_str() );
    135135                        // Can't tuple specialize if parameter sizes deeply-differ.
    136136                        if ( functionParameterSize( fftype ) != functionParameterSize( aftype ) ) return false;
  • src/InitTweak/FixInit.cc

    raf08051 r28e58fd  
    2929
    3030#include "CodeGen/GenType.h"           // for genPrettyType
     31#include "CodeGen/OperatorTable.h"
    3132#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    3233#include "Common/SemanticError.h"      // for SemanticError
     
    254255                        SemanticError errors;
    255256                  private:
    256                         void handleFirstParam( Expression * firstParam );
    257257                        template< typename... Params >
    258258                        void emit( CodeLocation, const Params &... params );
     
    379379                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    380380                                        assert( ftype );
    381                                         if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    382                                                 Type * t1 = ftype->get_parameters().front()->get_type();
     381                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
     382                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    383383                                                Type * t2 = ftype->get_parameters().back()->get_type();
    384                                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
    385 
    386                                                 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     384                                                assert( t1 );
     385
     386                                                if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) {
    387387                                                        // optimization: don't need to copy construct in order to call a copy constructor
    388388                                                        return appExpr;
    389389                                                } // if
    390                                         } else if ( isDestructor( funcDecl->get_name() ) ) {
     390                                        } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
    391391                                                // correctness: never copy construct arguments to a destructor
    392392                                                return appExpr;
     
    417417
    418418                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    419                         return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     419                        return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    420420                }
    421421
     
    505505                                impCpCtorExpr->get_returnDecls().push_back( ret );
    506506                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    507                                 if ( ! result->get_lvalue() ) {
     507                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    508508                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    509509                                        destructRet( ret, impCpCtorExpr );
     
    607607
    608608                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    609                                 if ( callExpr->get_result()->get_lvalue() ) {
    610                                         // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    611                                         // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
    612                                         // type of the return temporary from T to T* to properly capture the return value. Then dereference
    613                                         // the result of the comma expression, since the lvalue returning call was originally wrapped with
    614                                         // an AddressExpr.  Effectively, this turns
    615                                         //   lvalue T f();
    616                                         //   &*f();
    617                                         // into
    618                                         //   T * f();
    619                                         //   T * tmp_cp_retN;
    620                                         //   &*(tmp_cp_retN = &*f(), tmp_cp_retN);              // the first * and second & are generated here
    621                                         // which work out in terms of types, but is pretty messy. It would be nice to find a better way.
    622                                         assign->get_args().back() = new AddressExpr( assign->get_args().back() );
    623 
    624                                         returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
    625                                         retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
    626                                         retExpr = UntypedExpr::createDeref( retExpr );
    627                                 } // if
    628609                                // move env from callExpr to retExpr
    629610                                retExpr->set_env( callExpr->get_env() );
     
    991972                        if ( ! funcDecl ) return false;
    992973                        if ( ! funcDecl->get_statements() ) return false;
    993                         return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     974                        return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
    994975                }
    995976
     
    1008989
    1009990                        function = funcDecl;
    1010                         isCtor = isConstructor( function->get_name() );
     991                        isCtor = CodeGen::isConstructor( function->get_name() );
    1011992                        if ( checkWarnings( function ) ) {
    1012993                                FunctionType * type = function->get_functionType();
    1013994                                assert( ! type->get_parameters().empty() );
    1014995                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
    1015                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
    1016                                 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
     996                                Type * thisType = getPointerBase( thisParam->get_type() );
     997                                StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
    1017998                                if ( structType ) {
    1018999                                        structDecl = structType->get_baseStruct();
     
    10471028
    10481029                        if ( ! unhandled.empty() ) {
    1049                                 // need to explicitly re-add function parameters in order to resolve copy constructors
     1030                                // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
    10501031                                enterScope();
    10511032                                maybeAccept( function->get_functionType(), *this );
     
    10621043                                        // insert and resolve default/copy constructor call for each field that's unhandled
    10631044                                        std::list< Statement * > stmt;
    1064                                         UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );
    1065 
    10661045                                        Expression * arg2 = 0;
    10671046                                        if ( isCopyConstructor( function ) ) {
     
    10721051                                        }
    10731052                                        InitExpander srcParam( arg2 );
    1074                                         SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
     1053                                        // cast away reference type and construct field.
     1054                                        Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
     1055                                        Expression * memberDest = new MemberExpr( field, thisExpr );
     1056                                        SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor );
    10751057
    10761058                                        assert( stmt.size() <= 1 );
     
    10991081                }
    11001082
     1083                /// true if expr is effectively just the 'this' parameter
     1084                bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) {
     1085                        // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc.
     1086                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
     1087                                return varExpr->get_var() == thisParam;
     1088                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
     1089                                return isThisExpression( castExpr->get_arg(), thisParam );
     1090                        }
     1091                        return false;
     1092                }
     1093
     1094                /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr
     1095                MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) {
     1096                        if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
     1097                                if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1098                                        return memberExpr;
     1099                                }
     1100                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     1101                                return isThisMemberExpr( castExpr->get_arg(), thisParam );
     1102                        }
     1103                        return nullptr;
     1104                }
     1105
    11011106                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    11021107                        if ( ! checkWarnings( function ) ) return;
     
    11071112                                Expression * firstParam = appExpr->get_args().front();
    11081113
    1109                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
     1114                                if ( isThisExpression( firstParam, thisParam ) ) {
    11101115                                        // if calling another constructor on thisParam, assume that function handles
    11111116                                        // all members - if it doesn't a warning will appear in that function.
    1112                                         if ( varExpr->get_var() == thisParam ) {
    1113                                                 unhandled.clear();
    1114                                         }
    1115                                 } else {
    1116                                         // if first parameter is a member expression then
    1117                                         // remove the member from unhandled set.
    1118                                         handleFirstParam( firstParam );
    1119                                 }
    1120                         }
    1121 
    1122                         Parent::visit( appExpr );
    1123                 }
    1124 
    1125                 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
    1126                         using namespace std;
    1127                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
    1128                                 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) {
    1129                                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1130                                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1131                                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1132                                                                 if ( varExpr->get_var() == thisParam ) {
    1133                                                                         unhandled.erase( memberExpr->get_member() );
    1134                                                                 }
    1135                                                         }
    1136                                                 }
     1117                                        unhandled.clear();
     1118                                } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
     1119                                        // if first parameter is a member expression on the this parameter,
     1120                                        // then remove the member from unhandled set.
     1121                                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1122                                                unhandled.erase( memberExpr->get_member() );
    11371123                                        }
    11381124                                }
    11391125                        }
     1126                        Parent::visit( appExpr );
    11401127                }
    11411128
     
    11441131                        if ( ! isCtor ) return;
    11451132
    1146                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1147                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1148                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1149                                                 if ( varExpr->get_var() == thisParam ) {
    1150                                                         if ( unhandled.count( memberExpr->get_member() ) ) {
    1151                                                                 // emit a warning because a member was used before it was constructed
    1152                                                                 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
    1153                                                         }
    1154                                                 }
    1155                                         }
     1133                        if ( isThisExpression( memberExpr->get_aggregate(), 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 } );
    11561137                                }
    11571138                        }
     
    11991180                        ctorExpr->set_callExpr( nullptr );
    12001181                        ctorExpr->set_env( nullptr );
     1182                        delete ctorExpr;
    12011183
    12021184                        Expression *& firstArg = callExpr->get_args().front();
    1203                         UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
    1204                         assign->get_args().push_back( new VariableExpr( tmp ) );
    1205                         assign->get_args().push_back( firstArg );
    1206                         assign->set_result( ctorExpr->get_result()->clone() );
    1207                         firstArg = assign;
    1208 
    1209                         CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) );
     1185
     1186                        // 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.
     1187
     1188                        // generate the type of assignment operator using the type of tmp minus any reference types
     1189                        Type * type = tmp->get_type()->stripReferences();
     1190                        FunctionType * ftype = SymTab::genAssignType( type );
     1191
     1192                        // generate fake assignment decl and call it using &tmp and &firstArg
     1193                        // since tmp is guaranteed to be a reference and we want to assign pointers
     1194                        FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
     1195                        ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
     1196                        assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
     1197                        Expression * addrArg = new AddressExpr( firstArg );
     1198                        // if firstArg has type T&&, then &firstArg has type T*&.
     1199                        // Cast away the reference to a value type so that the argument
     1200                        // matches the assignment's parameter types
     1201                        if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
     1202                                addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
     1203                        }
     1204                        assign->get_args().push_back( addrArg );
     1205                        firstArg = new VariableExpr( tmp );
     1206
     1207                        // for constructor expr:
     1208                        //   T x;
     1209                        //   x{};
     1210                        // results in:
     1211                        //   T x;
     1212                        //   T & tmp;
     1213                        //   &tmp = &x, ?{}(tmp), tmp
     1214                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    12101215                        commaExpr->set_env( env );
    1211                         delete ctorExpr;
    12121216                        return commaExpr;
    12131217                }
  • src/InitTweak/GenInit.cc

    raf08051 r28e58fd  
    2121#include <list>                    // for _List_iterator, list
    2222
     23#include "CodeGen/OperatorTable.h"
    2324#include "Common/PassVisitor.h"    // for PassVisitor, WithGuards, WithShort...
    2425#include "Common/SemanticError.h"  // for SemanticError
     
    5758
    5859          protected:
    59                 FunctionType * ftype;
     60                FunctionType * ftype = nullptr;
    6061                std::string funcName;
    6162        };
     
    140141                std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    141142                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    142                 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     143                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    143144                // is being returned
    144                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {
     145                if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
    145146                        // explicitly construct the return value using the return expression and the retVal object
    146147                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    147                         UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
    148                         construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
    149                         construct->get_args().push_back( returnStmt->get_expr() );
    150                         stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct));
     148
     149                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
    151150
    152151                        // return the retVal object
     
    215214
    216215        bool CtorDtor::isManaged( Type * type ) const {
     216                // at least for now, references are never constructed
     217                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    217218                // need to clear and reset qualifiers when determining if a type is managed
    218219                ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     
    238239        void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
    239240                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    240                 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
     241                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
    241242                        std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
    242243                        assert( ! params.empty() );
    243                         PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
    244                         managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
     244                        Type * type = InitTweak::getPointerBase( params.front()->get_type() );
     245                        assert( type );
     246                        managedTypes.insert( SymTab::Mangler::mangle( type ) );
    245247                }
    246248        }
  • src/InitTweak/InitTweak.cc

    raf08051 r28e58fd  
    187187
    188188                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    189                         increment->get_args().push_back( new AddressExpr( index->clone() ) );
     189                        increment->get_args().push_back( index->clone() );
    190190                        *out++ = new ExprStmt( noLabels, increment );
    191191                }
     
    397397                template<typename CallExpr>
    398398                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
    399                         if ( pos >= callExpr->get_args().size() ) assertf( false, "asking for argument that doesn't exist. Return NULL/throw exception?" );
     399                        if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
    400400                        for ( Expression *& arg : callExpr->get_args() ) {
    401401                                if ( pos == 0 ) return arg;
     
    475475                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    476476                        return arrayType->get_base();
     477                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
     478                        return refType->get_base();
    477479                } else {
    478480                        return NULL;
     
    560562                if ( ftype->get_parameters().size() != 2 ) return 0;
    561563
    562                 Type * t1 = ftype->get_parameters().front()->get_type();
     564                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    563565                Type * t2 = ftype->get_parameters().back()->get_type();
    564                 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
    565                 assert( ptrType );
    566 
    567                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     566                assert( t1 );
     567
     568                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
    568569                        return function;
    569570                } else {
  • src/InitTweak/InitTweak.h

    raf08051 r28e58fd  
    2424// helper functions for initialization
    2525namespace InitTweak {
    26         bool isConstructor( const std::string & );
    27         bool isDestructor( const std::string & );
    28         bool isAssignment( const std::string & );
    29         bool isCtorDtor( const std::string & );
    30         bool isCtorDtorAssign( const std::string & );
    31 
    3226        FunctionDecl * isAssignment( Declaration * decl );
    3327        FunctionDecl * isDestructor( Declaration * decl );
  • src/MakeLibCfa.cc

    raf08051 r28e58fd  
    1616#include "MakeLibCfa.h"
    1717
    18 #include <cassert>                 // for assert
     18#include <cassert>                  // for assert
    1919#include <string>                   // for operator==, string
    2020
    2121#include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup, Ope...
     22#include "Common/PassVisitor.h"     // for PassVisitor
    2223#include "Common/SemanticError.h"   // for SemanticError
    2324#include "Common/UniqueName.h"      // for UniqueName
     
    3233
    3334namespace LibCfa {
    34         class MakeLibCfa : public Visitor {
    35           public:
    36                 void visit( FunctionDecl* funcDecl );
    37                 void visit( ObjectDecl* objDecl );
     35        namespace {
     36                struct MakeLibCfa {
     37                  public:
     38                        void postvisit( FunctionDecl* funcDecl );
    3839
    39                 std::list< Declaration* > &get_newDecls() { return newDecls; }
    40           private:
    41                 std::list< Declaration* > newDecls;
    42         };
     40                        std::list< Declaration* > newDecls;
     41                };
     42        }
    4343
    4444        void makeLibCfa( std::list< Declaration* > &prelude ) {
    45                 MakeLibCfa maker;
     45                PassVisitor<MakeLibCfa> maker;
    4646                acceptAll( prelude, maker );
    47                 prelude.splice( prelude.end(), maker.get_newDecls() );
     47                prelude.splice( prelude.end(), maker.pass.newDecls );
    4848        }
    4949
    50         void MakeLibCfa::visit( FunctionDecl* origFuncDecl ) {
    51                 if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
    52                 if ( origFuncDecl->get_statements() ) return;
     50        namespace {
     51                struct TypeFinder       {
     52                        void postvisit( TypeInstType * inst ) {
     53                                // if a type variable is seen, assume all zero_t/one_t in the parameter list
     54                                //  can be replaced with the equivalent 'general' pointer.
     55                                if ( type ) return;
     56                                if ( inst->isFtype ) {
     57                                        type = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), false ) );
     58                                } else {
     59                                        type = new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) );
     60                                }
     61                        }
     62                        Type * type = nullptr;
     63                };
    5364
    54                 FunctionDecl *funcDecl = origFuncDecl->clone();
    55                 CodeGen::OperatorInfo opInfo;
    56                 bool lookResult = CodeGen::operatorLookup( funcDecl->get_name(), opInfo );
    57                 assert( lookResult );
    58                 assert( ! funcDecl->get_statements() );
    59                 UntypedExpr *newExpr = new UntypedExpr( new NameExpr( funcDecl->get_name() ) );
    60                 UniqueName paramNamer( "_p" );
    61                 std::list< DeclarationWithType* >::iterator param = funcDecl->get_functionType()->get_parameters().begin();
    62                 assert( param != funcDecl->get_functionType()->get_parameters().end() );
     65                struct ZeroOneReplacer {
     66                        ZeroOneReplacer( Type * t ) : type( t ) {}
     67                        ~ZeroOneReplacer() { delete type; }
     68                        Type * type = nullptr;
    6369
    64                 for ( ; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
    65                         if ( (*param)->get_name() == "" ) {
    66                                 (*param)->set_name( paramNamer.newName() );
    67                                 (*param)->set_linkage( LinkageSpec::C );
     70                        Type * common( Type * t ) {
     71                                if ( ! type ) return t;
     72                                delete t;
     73                                return type->clone();
    6874                        }
    69                         newExpr->get_args().push_back( new VariableExpr( *param ) );
    70                 } // for
    7175
    72                 funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
    73                 newDecls.push_back( funcDecl );
     76                        Type * postmutate( OneType * t ) { return common( t ); }
     77                        Type * postmutate( ZeroType * t ) { return common( t ); }
     78                };
    7479
    75                 switch ( opInfo.type ) {
    76                   case CodeGen::OT_INDEX:
    77                   case CodeGen::OT_CALL:
    78                   case CodeGen::OT_PREFIX:
    79                   case CodeGen::OT_POSTFIX:
    80                   case CodeGen::OT_INFIX:
    81                   case CodeGen::OT_PREFIXASSIGN:
    82                   case CodeGen::OT_POSTFIXASSIGN:
    83                   case CodeGen::OT_INFIXASSIGN:
    84                   case CodeGen::OT_CTOR:
    85                   case CodeGen::OT_DTOR:
    86                                 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
    87                                 break;
    88                   case CodeGen::OT_CONSTANT:
    89                   case CodeGen::OT_LABELADDRESS:
    90                         // there are no intrinsic definitions of 0/1 or label addresses as functions
    91                         assert( false );
    92                 } // switch
    93         }
     80                void fixZeroOneType( FunctionDecl * origFuncDecl ) {
     81                        // find appropriate type to replace zero_t/one_t with
     82                        PassVisitor<TypeFinder> finder;
     83                        origFuncDecl->type->accept( finder );
     84                        // replace zero_t/one_t in function type
     85                        PassVisitor<ZeroOneReplacer> replacer( finder.pass.type );
     86                        origFuncDecl->type->acceptMutator( replacer );
     87                }
    9488
    95         void MakeLibCfa::visit( ObjectDecl* origObjDecl ) {
    96                 if ( origObjDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
     89                void MakeLibCfa::postvisit( FunctionDecl* origFuncDecl ) {
     90                        // don't change non-intrinsic functions
     91                        if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
     92                        // replace zero_t/one_t with void */void (*)(void)
     93                        fixZeroOneType( origFuncDecl );
     94                        // skip functions already defined
     95                        if ( origFuncDecl->get_statements() ) return;
    9796
    98                 ObjectDecl *objDecl = origObjDecl->clone();
    99                 assert( ! objDecl->get_init() );
    100                 std::list< Expression* > noDesignators;
    101                 objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), false ) ); // cannot be constructed
    102                 newDecls.push_back( objDecl );
    103         }
     97                        FunctionDecl *funcDecl = origFuncDecl->clone();
     98                        CodeGen::OperatorInfo opInfo;
     99                        bool lookResult = CodeGen::operatorLookup( funcDecl->get_name(), opInfo );
     100                        assert( lookResult );
     101                        assert( ! funcDecl->get_statements() );
     102                        // build a recursive call - this is okay, as the call will actually be codegen'd using operator syntax
     103                        UntypedExpr *newExpr = new UntypedExpr( new NameExpr( funcDecl->get_name() ) );
     104                        UniqueName paramNamer( "_p" );
     105                        std::list< DeclarationWithType* >::iterator param = funcDecl->get_functionType()->get_parameters().begin();
     106                        assert( param != funcDecl->get_functionType()->get_parameters().end() );
     107
     108                        for ( ; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
     109                                // name each unnamed parameter
     110                                if ( (*param)->get_name() == "" ) {
     111                                        (*param)->set_name( paramNamer.newName() );
     112                                        (*param)->set_linkage( LinkageSpec::C );
     113                                }
     114                                // add parameter to the expression
     115                                newExpr->get_args().push_back( new VariableExpr( *param ) );
     116                        } // for
     117
     118                        funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
     119                        newDecls.push_back( funcDecl );
     120
     121                        switch ( opInfo.type ) {
     122                          case CodeGen::OT_INDEX:
     123                          case CodeGen::OT_CALL:
     124                          case CodeGen::OT_PREFIX:
     125                          case CodeGen::OT_POSTFIX:
     126                          case CodeGen::OT_INFIX:
     127                          case CodeGen::OT_PREFIXASSIGN:
     128                          case CodeGen::OT_POSTFIXASSIGN:
     129                          case CodeGen::OT_INFIXASSIGN:
     130                          case CodeGen::OT_CTOR:
     131                          case CodeGen::OT_DTOR:
     132                                // return the recursive call
     133                                        funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
     134                                        break;
     135                          case CodeGen::OT_CONSTANT:
     136                          case CodeGen::OT_LABELADDRESS:
     137                                // there are no intrinsic definitions of 0/1 or label addresses as functions
     138                                assert( false );
     139                        } // switch
     140                }
     141        } // namespace
    104142} // namespace LibCfa
  • src/Makefile.in

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    340340} // DeclarationNode::newTypeDecl
    341341
    342 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers ) {
    343         DeclarationNode * newnode = new DeclarationNode;
    344         newnode->type = new TypeData( TypeData::Pointer );
     342DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) {
     343        DeclarationNode * newnode = new DeclarationNode;
     344        newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference );
    345345        if ( qualifiers ) {
    346346                return newnode->addQualifiers( qualifiers );
     
    759759DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) {
    760760        if ( p ) {
    761                 assert( p->type->kind == TypeData::Pointer );
     761                assert( p->type->kind == TypeData::Pointer || TypeData::Reference );
    762762                setBase( p->type );
    763763                p->type = nullptr;
     
    781781DeclarationNode * DeclarationNode::addNewPointer( DeclarationNode * p ) {
    782782        if ( p ) {
    783                 assert( p->type->kind == TypeData::Pointer );
     783                assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference );
    784784                if ( type ) {
    785785                        switch ( type->kind ) {
  • src/Parser/ExpressionNode.cc

    raf08051 r28e58fd  
    314314Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
    315315        std::list< Expression * > args;
    316         args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node) ) );
     316        args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx
    317317        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    318318} // build_unary_ptr
     
    327327Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
    328328        std::list< Expression * > args;
    329         args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node1) ) );
     329        args.push_back( maybeMoveBuild< Expression >(expr_node1) );
    330330        args.push_back( maybeMoveBuild< Expression >(expr_node2) );
    331331        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
  • src/Parser/ParseNode.h

    raf08051 r28e58fd  
    243243        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    244244        static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams );
    245         static DeclarationNode * newPointer( DeclarationNode * qualifiers );
     245        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    246246        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
    247247        static DeclarationNode * newVarArray( DeclarationNode * qualifiers );
  • src/Parser/TypeData.cc

    raf08051 r28e58fd  
    3535          case Unknown:
    3636          case Pointer:
     37          case Reference:
    3738          case EnumConstant:
    3839                // nothing else to initialize
     
    104105          case Unknown:
    105106          case Pointer:
     107          case Reference:
    106108          case EnumConstant:
    107109                // nothing to destroy
     
    170172          case EnumConstant:
    171173          case Pointer:
     174          case Reference:
    172175                // nothing else to copy
    173176                break;
     
    405408                        // add dtor:  void ^?{}(T *)
    406409                        FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
    407                         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 ) );
     410                        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 ) );
    408411                        td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) );
    409412
    410413                        // add copy ctor:  void ?{}(T *, T)
    411414                        FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
    412                         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 ) );
     415                        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 ) );
    413416                        copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    414417                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) );
     
    416419                        // add default ctor:  void ?{}(T *)
    417420                        FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
    418                         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 ) );
     421                        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 ) );
    419422                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) );
    420423
    421424                        // add assignment operator:  T * ?=?(T *, T)
    422425                        FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
    423                         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 ) );
     426                        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 ) );
    424427                        assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    425428                        assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
     
    441444          case TypeData::Array:
    442445                return buildArray( td );
     446          case TypeData::Reference:
     447                return buildReference( td );
    443448          case TypeData::Function:
    444449                return buildFunction( td );
     
    619624        buildForall( td->forall, at->get_forall() );
    620625        return at;
    621 } // buildPointer
     626} // buildArray
     627
     628ReferenceType * buildReference( const TypeData * td ) {
     629        ReferenceType * rt;
     630        if ( td->base ) {
     631                rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
     632        } else {
     633                rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     634        } // if
     635        buildForall( td->forall, rt->get_forall() );
     636        return rt;
     637} // buildReference
    622638
    623639AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
  • src/Parser/TypeData.h

    raf08051 r28e58fd  
    2626
    2727struct TypeData {
    28         enum Kind { Basic, Pointer, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
     28        enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    2929                                SymbolicInst, Tuple, Typeof, Builtin, Unknown };
    3030
     
    109109PointerType * buildPointer( const TypeData * );
    110110ArrayType * buildArray( const TypeData * );
     111ReferenceType * buildReference( const TypeData * );
    111112AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
    112113ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
  • src/Parser/lex.ll

    raf08051 r28e58fd  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu Jul 27 21:46:06 2017
    13  * Update Count     : 550
     12 * Last Modified On : Tue Aug 22 22:43:39 2017
     13 * Update Count     : 558
    1414 */
    1515
     
    4545#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL( x ) // numeric constant
    4646#define KEYWORD_RETURN(x)       RETURN_CHAR( x )                        // keyword
     47#define QKEYWORD_RETURN(x)      typedefTable.isKind( yytext ); RETURN_VAL(x); // quasi-keyword
    4748#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    4849#define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
     
    236237__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    237238long                    { KEYWORD_RETURN(LONG); }
    238 lvalue                  { KEYWORD_RETURN(LVALUE); }                             // CFA
    239239monitor                 { KEYWORD_RETURN(MONITOR); }                    // CFA
    240240mutex                   { KEYWORD_RETURN(MUTEX); }                              // CFA
     
    261261throw                   { KEYWORD_RETURN(THROW); }                              // CFA
    262262throwResume             { KEYWORD_RETURN(THROWRESUME); }                // CFA
     263timeout                 { QKEYWORD_RETURN(TIMEOUT); }                   // CFA
    263264trait                   { KEYWORD_RETURN(TRAIT); }                              // CFA
    264265try                             { KEYWORD_RETURN(TRY); }                                // CFA
     
    277278__volatile              { KEYWORD_RETURN(VOLATILE); }                   // GCC
    278279__volatile__    { KEYWORD_RETURN(VOLATILE); }                   // GCC
     280waitfor                 { KEYWORD_RETURN(WAITFOR); }
     281or                              { QKEYWORD_RETURN(WOR); }                               // CFA
     282when                    { KEYWORD_RETURN(WHEN); }
    279283while                   { KEYWORD_RETURN(WHILE); }
    280284with                    { KEYWORD_RETURN(WITH); }                               // CFA
  • src/Parser/parser.yy

    raf08051 r28e58fd  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug 20 09:21:54 2017
    13 // Update Count     : 2573
     12// Last Modified On : Wed Aug 23 21:08:08 2017
     13// Update Count     : 2704
    1414//
    1515
     
    119119%token RESTRICT                                                                                 // C99
    120120%token ATOMIC                                                                                   // C11
    121 %token FORALL LVALUE MUTEX VIRTUAL                                              // CFA
     121%token FORALL MUTEX VIRTUAL                                             // CFA
    122122%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    123123%token BOOL COMPLEX IMAGINARY                                                   // C99
     
    131131%token ATTRIBUTE EXTENSION                                                              // GCC
    132132%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
    133 %token CHOOSE DISABLE ENABLE FALLTHRU TRY CATCH CATCHRESUME FINALLY THROW THROWRESUME AT WITH // CFA
     133%token CHOOSE DISABLE ENABLE FALLTHRU TRY CATCH CATCHRESUME FINALLY THROW THROWRESUME AT WITH WHEN WAITFOR // CFA
    134134%token ASM                                                                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
    135135%token ALIGNAS ALIGNOF GENERIC STATICASSERT                             // C11
     
    137137// names and constants: lexer differentiates between identifier and typedef names
    138138%token<tok> IDENTIFIER                  QUOTED_IDENTIFIER               TYPEDEFname                             TYPEGENname
     139%token<tok> TIMEOUT                             WOR
    139140%token<tok> ATTR_IDENTIFIER             ATTR_TYPEDEFname                ATTR_TYPEGENname
    140141%token<tok> INTEGERconstant             CHARACTERconstant               STRINGliteral
     
    161162%type<tok> identifier  no_attr_identifier
    162163%type<tok> identifier_or_type_name  no_attr_identifier_or_type_name  attr_name
     164%type<tok> quasi_keyword
    163165%type<constant> string_literal
    164166%type<str> string_literal_list
     
    190192%type<sn> iteration_statement                   jump_statement
    191193%type<sn> with_statement                                exception_statement                     asm_statement
     194%type<sn> when_clause_opt                               waitfor_statement                       waitfor_clause                          waitfor                         timeout
    192195%type<sn> fall_through_opt                              fall_through
    193196%type<sn> statement                                             statement_list
     
    197200%type<sn> case_clause                                   case_value_list                         case_label                                      case_label_list
    198201%type<sn> switch_clause_list_opt                switch_clause_list                      choose_clause_list_opt          choose_clause_list
    199 %type<sn> /* handler_list */                    handler_clause                          finally_clause
     202%type<sn> handler_clause                                finally_clause
    200203%type<catch_kind> handler_key
    201204
     
    295298// Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string
    296299// is ambiguous:
    297 // .---------.                          matches IF '(' comma_expression ')' statement
     300// .---------.                          matches IF '(' comma_expression ')' statement . (reduce)
    298301// if ( C ) S1 else S2
    299 // `-----------------'          matches IF '(' comma_expression ')' statement ELSE statement */
    300 
    301 %nonassoc THEN  // rule precedence for IF '(' comma_expression ')' statement
    302 %nonassoc ELSE  // token precedence for start of else clause in IF statement
     302// `-----------------'          matches IF '(' comma_expression ')' statement . (shift) ELSE statement */
     303// Similar issues exit with the waitfor statement.
     304
     305// Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left
     306// associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
     307%precedence THEN        // rule precedence for IF/WAITFOR statement
     308%precedence WOR         // token precedence for start of WOR in WAITFOR statement
     309%precedence TIMEOUT     // token precedence for start of TIMEOUT in WAITFOR statement
     310%precedence ELSE        // token precedence for start of else clause in IF/WAITFOR statement
    303311
    304312%start translation_unit                                                                 // parse-tree root
     
    353361        ;
    354362
     363quasi_keyword:                                                                                  // CFA
     364        TIMEOUT
     365        | WOR
     366        ;
     367
    355368identifier:
    356369        IDENTIFIER
    357370        | ATTR_IDENTIFIER                                                                       // CFA
     371        | quasi_keyword
    358372        ;
    359373
    360374no_attr_identifier:
    361375        IDENTIFIER
     376        | quasi_keyword
    362377        ;
    363378
     
    380395primary_expression:
    381396        IDENTIFIER                                                                                      // typedef name cannot be used as a variable name
     397                { $$ = new ExpressionNode( build_varref( $1 ) ); }
     398        | quasi_keyword
    382399                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    383400        | tuple
     
    548565        | '&'                                                                           { $$ = OperKinds::AddressOf; }
    549566                // GCC, address of label must be handled by semantic check for ref,ref,label
    550 //      | ANDAND                                                                        { $$ = OperKinds::And; }
     567        | ANDAND                                                                        { $$ = OperKinds::And; }
    551568        ;
    552569
     
    670687        conditional_expression
    671688        | unary_expression assignment_operator assignment_expression
    672                 { $$ = new ExpressionNode( build_binary_ptr( $2, $1, $3 ) ); }
     689                { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); }
    673690        ;
    674691
     
    736753        | jump_statement
    737754        | with_statement
     755        | waitfor_statement
    738756        | exception_statement
    739757        | asm_statement
     
    955973
    956974with_statement:
    957         WITH '(' tuple_expression_list ')' compound_statement
    958                 { $$ = (StatementNode *)0; }                                    // FIX ME
     975        WITH '(' tuple_expression_list ')' statement
     976                { $$ = nullptr; }                                                               // FIX ME
     977        ;
     978
     979when_clause_opt:
     980        // empty
     981                { $$ = nullptr; }                                                               // FIX ME
     982        | WHEN '(' comma_expression ')'
     983                { $$ = nullptr; }                                                               // FIX ME
     984        ;
     985
     986waitfor:
     987        WAITFOR '(' identifier ')'
     988                { $$ = nullptr; }                                                               // FIX ME
     989        | WAITFOR '(' identifier ',' argument_expression_list ')'
     990                { $$ = nullptr; }                                                               // FIX ME
     991        ;
     992
     993timeout:
     994        TIMEOUT '(' comma_expression ')'
     995                { $$ = nullptr; }                                                               // FIX ME
     996        ;
     997
     998waitfor_clause:
     999        when_clause_opt waitfor statement %prec THEN
     1000                { $$ = nullptr; }                                                               // FIX ME
     1001        | when_clause_opt waitfor statement WOR waitfor_clause
     1002                { $$ = nullptr; }                                                               // FIX ME
     1003        | when_clause_opt timeout statement %prec THEN
     1004                { $$ = nullptr; }                                                               // FIX ME
     1005        | when_clause_opt ELSE statement
     1006                { $$ = nullptr; }                                                               // FIX ME
     1007        | when_clause_opt timeout statement WOR when_clause_opt ELSE statement
     1008                { $$ = nullptr; }                                                               // FIX ME
     1009        ;
     1010
     1011waitfor_statement:
     1012        when_clause_opt waitfor statement %prec THEN
     1013                { $$ = nullptr; }                                                               // FIX ME
     1014        | when_clause_opt waitfor statement WOR waitfor_clause
     1015                { $$ = nullptr; }                                                               // FIX ME
    9591016        ;
    9601017
     
    9671024                { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
    9681025        ;
    969 
    970 //handler_list:
    971 //      handler_clause
    972 //              // ISO/IEC 9899:1999 Section 15.3(6 ) If present, a "..." handler shall be the last handler for its try block.
    973 //      | CATCH '(' ELLIPSIS ')' compound_statement
    974 //              { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
    975 //      | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
    976 //              { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
    977 //      | CATCHRESUME '(' ELLIPSIS ')' compound_statement
    978 //              { $$ = new StatementNode( build_catch( 0, $5, true ) ); }
    979 //      | handler_clause CATCHRESUME '(' ELLIPSIS ')' compound_statement
    980 //              { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( 0, $6, true ) ) ); }
    981 //      ;
    9821026
    9831027handler_clause:
     
    14391483        | VOLATILE
    14401484                { $$ = DeclarationNode::newTypeQualifier( Type::Volatile ); }
    1441         | LVALUE                                                                                        // CFA
    1442                 { $$ = DeclarationNode::newTypeQualifier( Type::Lvalue ); }
    14431485        | MUTEX
    14441486                { $$ = DeclarationNode::newTypeQualifier( Type::Mutex ); }
     
    22412283with_clause_opt:
    22422284        // empty
    2243                 { $$ = (StatementNode *)0; }                                    // FIX ME
     2285                { $$ = nullptr; }                                                               // FIX ME
    22442286        | WITH '(' tuple_expression_list ')'
    2245                 { $$ = (StatementNode *)0; }                                    // FIX ME
     2287                { $$ = nullptr; }                                                               // FIX ME
    22462288        ;
    22472289
     
    23632405attr_name:                                                                                              // GCC
    23642406        IDENTIFIER
     2407        | quasi_keyword
    23652408        | TYPEDEFname
    23662409        | TYPEGENname
     
    24212464variable_ptr:
    24222465        ptrref_operator variable_declarator
    2423                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2466                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    24242467        | ptrref_operator type_qualifier_list variable_declarator
    2425                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2468                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    24262469        | '(' variable_ptr ')' attribute_list_opt
    24272470                { $$ = $2->addQualifiers( $4 ); }                               // redundant parenthesis
     
    24692512function_ptr:
    24702513        ptrref_operator function_declarator
    2471                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2514                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    24722515        | ptrref_operator type_qualifier_list function_declarator
    2473                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2516                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    24742517        | '(' function_ptr ')'
    24752518                { $$ = $2; }
     
    25092552KR_function_ptr:
    25102553        ptrref_operator KR_function_declarator
    2511                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2554                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    25122555        | ptrref_operator type_qualifier_list KR_function_declarator
    2513                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2556                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    25142557        | '(' KR_function_ptr ')'
    25152558                { $$ = $2; }
     
    25532596type_ptr:
    25542597        ptrref_operator variable_type_redeclarator
    2555                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2598                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    25562599        | ptrref_operator type_qualifier_list variable_type_redeclarator
    2557                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2600                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    25582601        | '(' type_ptr ')' attribute_list_opt
    25592602                { $$ = $2->addQualifiers( $4 ); }
     
    25972640identifier_parameter_ptr:
    25982641        ptrref_operator identifier_parameter_declarator
    2599                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2642                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    26002643        | ptrref_operator type_qualifier_list identifier_parameter_declarator
    2601                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2644                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    26022645        | '(' identifier_parameter_ptr ')' attribute_list_opt
    26032646                { $$ = $2->addQualifiers( $4 ); }
     
    26572700type_parameter_ptr:
    26582701        ptrref_operator type_parameter_redeclarator
    2659                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2702                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    26602703        | ptrref_operator type_qualifier_list type_parameter_redeclarator
    2661                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2704                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    26622705        | '(' type_parameter_ptr ')' attribute_list_opt
    26632706                { $$ = $2->addQualifiers( $4 ); }
     
    27002743abstract_ptr:
    27012744        ptrref_operator
    2702                 { $$ = DeclarationNode::newPointer( 0 ); }
     2745                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    27032746        | ptrref_operator type_qualifier_list
    2704                 { $$ = DeclarationNode::newPointer( $2 ); }
     2747                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    27052748        | ptrref_operator abstract_declarator
    2706                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2749                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    27072750        | ptrref_operator type_qualifier_list abstract_declarator
    2708                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2751                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    27092752        | '(' abstract_ptr ')' attribute_list_opt
    27102753                { $$ = $2->addQualifiers( $4 ); }
     
    27892832abstract_parameter_ptr:
    27902833        ptrref_operator
    2791                 { $$ = DeclarationNode::newPointer( nullptr ); }
     2834                { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
    27922835        | ptrref_operator type_qualifier_list
    2793                 { $$ = DeclarationNode::newPointer( $2 ); }
     2836                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    27942837        | ptrref_operator abstract_parameter_declarator
    2795                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr ) ); }
     2838                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    27962839        | ptrref_operator type_qualifier_list abstract_parameter_declarator
    2797                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2840                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    27982841        | '(' abstract_parameter_ptr ')' attribute_list_opt
    27992842                { $$ = $2->addQualifiers( $4 ); }
     
    28682911variable_abstract_ptr:
    28692912        ptrref_operator
    2870                 { $$ = DeclarationNode::newPointer( 0 ); }
     2913                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    28712914        | ptrref_operator type_qualifier_list
    2872                 { $$ = DeclarationNode::newPointer( $2 ); }
     2915                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    28732916        | ptrref_operator variable_abstract_declarator
    2874                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2917                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    28752918        | ptrref_operator type_qualifier_list variable_abstract_declarator
    2876                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2919                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    28772920        | '(' variable_abstract_ptr ')' attribute_list_opt
    28782921                { $$ = $2->addQualifiers( $4 ); }
     
    29142957                // No SUE declaration in parameter list.
    29152958        ptrref_operator type_specifier_nobody
    2916                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2959                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29172960        | type_qualifier_list ptrref_operator type_specifier_nobody
    2918                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2961                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29192962        | ptrref_operator cfa_abstract_function
    2920                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2963                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29212964        | type_qualifier_list ptrref_operator cfa_abstract_function
    2922                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2965                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29232966        | ptrref_operator cfa_identifier_parameter_declarator_tuple
    2924                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2967                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    29252968        | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
    2926                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2969                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    29272970        ;
    29282971
     
    30023045cfa_abstract_ptr:                                                                               // CFA
    30033046        ptrref_operator type_specifier
    3004                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     3047                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    30053048        | type_qualifier_list ptrref_operator type_specifier
    3006                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     3049                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    30073050        | ptrref_operator cfa_abstract_function
    3008                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     3051                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    30093052        | type_qualifier_list ptrref_operator cfa_abstract_function
    3010                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     3053                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    30113054        | ptrref_operator cfa_abstract_declarator_tuple
    3012                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     3055                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    30133056        | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
    3014                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     3057                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    30153058        ;
    30163059
  • src/ResolvExpr/Alternative.cc

    raf08051 r28e58fd  
    3434                : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
    3535
    36         Alternative::Alternative( const Alternative &other ) {
    37                 initialize( other, *this );
     36        Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    3837        }
    3938
    4039        Alternative &Alternative::operator=( const Alternative &other ) {
    4140                if ( &other == this ) return *this;
    42                 initialize( other, *this );
     41                delete expr;
     42                cost = other.cost;
     43                cvtCost = other.cvtCost;
     44                expr = maybeClone( other.expr );
     45                env = other.env;
    4346                return *this;
    4447        }
     
    5760                other.expr = nullptr;
    5861                return *this;
    59         }
    60 
    61         void Alternative::initialize( const Alternative &src, Alternative &dest ) {
    62                 dest.cost = src.cost;
    63                 dest.cvtCost = src.cvtCost;
    64                 dest.expr = maybeClone( src.expr );
    65                 dest.env = src.env;
    6662        }
    6763
  • src/ResolvExpr/Alternative.h

    raf08051 r28e58fd  
    3939                ~Alternative();
    4040
    41                 void initialize( const Alternative &src, Alternative &dest );
    42 
    4341                void print( std::ostream &os, int indent = 0 ) const;
    4442
  • src/ResolvExpr/AlternativeFinder.cc

    raf08051 r28e58fd  
    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 >
     
    186193                        if ( alternatives.begin() == oldBegin ) {
    187194                                std::ostringstream stream;
    188                                 stream << "Can't choose between " << alternatives.size() << " alternatives for expression ";
     195                                AltList winners;
     196                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
     197                                stream << "Can't choose between " << winners.size() << " alternatives for expression ";
    189198                                expr->print( stream );
    190199                                stream << "Alternatives are:";
    191                                 AltList winners;
    192                                 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    193200                                printAlts( winners, stream, 8 );
    194201                                throw SemanticError( stream.str() );
     
    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        }
     
    228241        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    229242                // by this point, member must be a name expr
    230                 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
     243                NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
     244                if ( ! nameExpr ) return;
    231245                const std::string & name = nameExpr->get_name();
    232246                std::list< Declaration* > members;
     
    250264                        // during parsing and reusing that information here.
    251265                        std::stringstream ss( constantExpr->get_constant()->get_value() );
    252                         int val;
     266                        int val = 0;
    253267                        std::string tmp;
    254268                        if ( ss >> val && ! (ss >> tmp) ) {
     
    277291                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    278292
    279                 Cost convCost( 0, 0, 0 );
     293                Cost convCost = Cost::zero;
    280294                std::list< DeclarationWithType* >& formals = function->get_parameters();
    281295                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     
    290304                                actualType->print( std::cerr, 8 );
    291305                        )
    292                         Cost actualCost;
     306                        Cost actualCost = Cost::zero;
    293307                        if ( formal == formals.end() ) {
    294308                                if ( function->get_isVarArgs() ) {
    295                                         convCost += Cost( 1, 0, 0 );
     309                                        convCost.incUnsafe();
     310                                        // convert reference-typed expressions to value-typed expressions
     311                                        referenceToRvalueConversion( *actualExpr );
    296312                                        continue;
    297313                                } else {
     
    305321                                std::cerr << std::endl << " to ";
    306322                                formalType->print( std::cerr, 8 );
     323                                std::cerr << std::endl << "environment is: ";
     324                                alt.env.print( std::cerr, 8 );
     325                                std::cerr << std::endl;
    307326                        )
    308327                        Cost newCost = conversionCost( actualType, formalType, indexer, alt.env );
     
    316335                        convCost += newCost;
    317336                        actualCost += newCost;
    318                         if ( actualCost != Cost( 0, 0, 0 ) ) {
     337                        if ( actualCost != Cost::zero ) {
    319338                                Type *newType = formalType->clone();
    320339                                alt.env.apply( newType );
    321340                                *actualExpr = new CastExpr( *actualExpr, newType );
    322341                        }
    323                         convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 );
     342                        convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
    324343                        ++formal; // can't be in for-loop update because of the continue
    325344                }
     
    343362                        }
    344363                        convCost += newCost;
    345                         convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
     364                        convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
    346365                }
    347366
     
    400419                        Expression * actual = actualIt->expr;
    401420                        Type * actualType = actual->get_result();
     421
    402422                        PRINT(
    403423                                std::cerr << "formal type is ";
     
    408428                        )
    409429                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     430                                // std::cerr << "unify failed" << std::endl;
    410431                                return false;
    411432                        }
     
    452473                        // match flattened actuals with formal parameters - actuals will be grouped to match
    453474                        // with formals as appropriate
    454                         Cost cost;
     475                        Cost cost = Cost::zero;
    455476                        std::list< Expression * > newExprs;
    456477                        ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
     
    613634                AssertionSet newNeed;
    614635                //AssertionParentSet needParents;
     636                PRINT(
     637                        std::cerr << "env is: " << std::endl;
     638                        newAlt.env.print( std::cerr, 0 );
     639                        std::cerr << std::endl;
     640                )
     641
    615642                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
    616643//      PRINT(
     
    643670                        makeExprList( instantiatedActuals, appExpr->get_args() );
    644671                        PRINT(
     672                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    645673                                std::cerr << "need assertions:" << std::endl;
    646674                                printAssertionSet( resultNeed, std::cerr, 8 );
     
    663691                                UntypedExpr *vexpr = untypedExpr->clone();
    664692                                vexpr->set_result( pt.clone() );
    665                                 alternatives.push_back( Alternative( vexpr, env, Cost()) );
     693                                alternatives.push_back( Alternative( vexpr, env, Cost::zero) );
    666694                                return;
    667695                        }
     
    681709                AltList candidates;
    682710                SemanticError errors;
    683                 for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
     711                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    684712                        try {
    685713                                PRINT(
     
    688716                                )
    689717                                // check if the type is pointer to function
    690                                 PointerType *pointer;
    691                                 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
     718                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    692719                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     720                                                referenceToRvalueConversion( func->expr );
    693721                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    694722                                                        // XXX
     
    696724                                                        makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    697725                                                }
    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
     726                                        }
     727                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     728                                        referenceToRvalueConversion( func->expr );
     729                                        EqvClass eqvClass;
     730                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
     731                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     732                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     733                                                                makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     734                                                        } // for
    706735                                                } // if
    707736                                        } // if
     
    722751                                        }
    723752
    724                                         for ( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     753                                        for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    725754                                                // check if the type is pointer to function
    726                                                 PointerType *pointer;
    727                                                 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
     755                                                if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    728756                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     757                                                                referenceToRvalueConversion( funcOp->expr );
    729758                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    730759                                                                        AltList currentAlt;
     
    753782                                PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    754783                                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    755                                 std::cerr << "Case +++++++++++++" << std::endl;
     784                                std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
    756785                                std::cerr << "formals are:" << std::endl;
    757786                                printAll( function->get_parameters(), std::cerr, 8 );
     
    796825        bool isLvalue( Expression *expr ) {
    797826                // xxx - recurse into tuples?
    798                 return expr->has_result() && expr->get_result()->get_lvalue();
     827                return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    799828        }
    800829
     
    810839
    811840        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).
    817                         if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     841                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
     842                        // Argument expression is a tuple and the target type is not void and not a reference type.
     843                        // Cast each member of the tuple to its corresponding target type, producing the tuple of those
     844                        // cast expressions. If there are more components of the tuple than components in the target type,
     845                        // then excess components do not come out in the result expression (but UniqueExprs ensure that
     846                        // side effects will still be done).
     847                        if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) {
    818848                                // expressions which may contain side effects require a single unique instance of the expression.
    819849                                argExpr = new UniqueExpr( argExpr );
     
    855885                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    856886                        // to.
    857                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     887                        int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size();
    858888                        if ( discardedValues < 0 ) continue;
    859889                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    860890                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    861891                        // 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 );
     892                        unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
     893                        Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env );
    864894                        if ( thisCost != Cost::infinity ) {
    865895                                // count one safe conversion for each value that is thrown away
    866                                 thisCost += Cost( 0, 0, discardedValues );
     896                                thisCost.incSafe( discardedValues );
    867897
    868898                                candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     
    895925                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    896926                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() );
     927                        // 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
     928                        std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
     929                        Type * aggrType = aggrExpr->get_result();
     930                        if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     931                                aggrType = aggrType->stripReferences();
     932                                aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     933                        }
     934                        // find member of the given type
     935                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
     936                                addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     937                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
     938                                addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     939                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
     940                                addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
    903941                        } // if
    904942                } // for
     
    915953                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    916954                        VariableExpr newExpr( *i, nameExpr->get_argName() );
    917                         alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     955                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    918956                        PRINT(
    919957                                std::cerr << "decl is ";
     
    955993                        // return the lowest cost alternative for the argument
    956994                        Alternative &choice = winners.front();
     995                        referenceToRvalueConversion( choice.expr );
    957996                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    958997                } // if
     
    9751014                        // return the lowest cost alternative for the argument
    9761015                        Alternative &choice = winners.front();
     1016                        referenceToRvalueConversion( choice.expr );
    9771017                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    9781018                } // if
     
    10591099                        for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    10601100                                VariableExpr newExpr( *i );
    1061                                 alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     1101                                alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    10621102                                renameTypes( alternatives.back().expr );
    10631103                        } // for
     
    12321272                                if ( thisCost != Cost::infinity ) {
    12331273                                        // count one safe conversion for each value that is thrown away
    1234                                         thisCost += Cost( 0, 0, discardedValues );
     1274                                        thisCost.incSafe( discardedValues );
    12351275                                        candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    12361276                                }
  • src/ResolvExpr/CastCost.cc

    raf08051 r28e58fd  
    4949                                assert( type );
    5050                                if ( type->get_base() ) {
    51                                         return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     51                                        return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
    5252                                } // if
    5353                        } // if
    5454                } // if
    5555                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    56                         return Cost( 0, 0, 0 );
     56                        return Cost::zero;
    5757                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    58                         return Cost( 0, 0, 1 );
     58                        return Cost::safe;
     59                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     60                        return convertToReferenceCost( src, refType, indexer, env );
    5961                } else {
    6062                        CastCost converter( dest, indexer, env );
     
    6466                        } else {
    6567                                // xxx - why are we adding cost 0 here?
    66                                 return converter.get_cost() + Cost( 0, 0, 0 );
     68                                return converter.get_cost() + Cost::zero;
    6769                        } // if
    6870                } // if
     
    7779                if ( destAsPointer && basicType->isInteger() ) {
    7880                        // necessary for, e.g. unsigned long => void*
    79                         cost = Cost( 1, 0, 0 );
     81                        cost = Cost::unsafe;
    8082                } else {
    81                         ConversionCost::visit( basicType );
     83                        cost = conversionCost( basicType, dest, indexer, env );
    8284                } // if
    8385        }
     
    8688                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    8789                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    88                                 cost = Cost( 0, 0, 1 );
     90                                cost = Cost::safe;
    8991                        } else {
    9092                                TypeEnvironment newEnv( env );
     
    9395                                int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
    9496                                if ( castResult > 0 ) {
    95                                         cost = Cost( 0, 0, 1 );
     97                                        cost = Cost::safe;
    9698                                } else if ( castResult < 0 ) {
    9799                                        cost = Cost::infinity;
     
    101103                        if ( destAsBasic->isInteger() ) {
    102104                                // necessary for, e.g. void* => unsigned long
    103                                 cost = Cost( 1, 0, 0 );
     105                                cost = Cost::unsafe;
    104106                        } // if
    105107                }
  • src/ResolvExpr/CommonType.cc

    raf08051 r28e58fd  
    2626#include "typeops.h"                     // for isFtype
    2727
    28 
    29 /// #define DEBUG
     28// #define DEBUG
    3029
    3130namespace ResolvExpr {
     
    3938                virtual void visit( PointerType *pointerType );
    4039                virtual void visit( ArrayType *arrayType );
     40                virtual void visit( ReferenceType *refType );
    4141                virtual void visit( FunctionType *functionType );
    4242                virtual void visit( StructInstType *aggregateUseType );
     
    5050                virtual void visit( OneType *oneType );
    5151
    52                 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer );
     52                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
     53                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    5354
    5455                Type *result;
     
    6061        };
    6162
     63        Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
     64                Type * result = nullptr, * common = nullptr;
     65                AssertionSet have, need;
     66                OpenVarSet newOpen( openVars );
     67                // need unify to bind type variables
     68                if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
     69                        // std::cerr << "unify success" << std::endl;
     70                        if ( widenSecond ) {
     71                                // std::cerr << "widen second" << std::endl;
     72                                if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
     73                                        result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
     74                                        result->get_qualifiers() |= other->get_qualifiers();
     75                                }
     76                        } else if ( widenFirst ) {
     77                                // std::cerr << "widen first" << std::endl;
     78                                if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
     79                                        result = common;
     80                                        result->get_qualifiers() |= refType->get_qualifiers();
     81                                }
     82                        }
     83                } else {
     84                        // std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
     85                }
     86                // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
     87                return result;
     88        }
     89
    6290        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    6391                CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     92
     93                int depth1 = type1->referenceDepth();
     94                int depth2 = type2->referenceDepth();
     95                if ( depth1 > 0 || depth2 > 0 ) {
     96                        int diff = depth1-depth2;
     97                        // 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.
     98                        if ( diff > 1 || diff < -1 ) return nullptr;
     99
     100                        // special case where one type has a reference depth of 1 larger than the other
     101                        if ( diff > 0 ) {
     102                                return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars );
     103                        } else if ( diff < 0 ) {
     104                                return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars );
     105                        }
     106                        // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
     107                }
     108
    64109                type1->accept( visitor );
    65110                Type *result = visitor.get_result();
     
    88133                } // if
    89134#ifdef DEBUG
    90                 std::cout << "============= commonType" << std::endl << "type1 is ";
    91                 type1->print( std::cout );
    92                 std::cout << " type2 is ";
    93                 type2->print( std::cout );
     135                std::cerr << "============= commonType" << std::endl << "type1 is ";
     136                type1->print( std::cerr );
     137                std::cerr << " type2 is ";
     138                type2->print( std::cerr );
    94139                if ( result ) {
    95                         std::cout << " common type is ";
    96                         result->print( std::cout );
     140                        std::cerr << " common type is ";
     141                        result->print( std::cerr );
    97142                } else {
    98                         std::cout << " no common type";
    99                 } // if
    100                 std::cout << std::endl;
     143                        std::cerr << " no common type";
     144                } // if
     145                std::cerr << std::endl;
    101146#endif
    102147                return result;
     
    150195        }
    151196
    152         void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) {
     197        template< typename Pointer >
     198        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    153199                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    154200                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    165211        void CommonType::visit( PointerType *pointerType ) {
    166212                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
     213                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    167214                        if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    168215                                getCommonWithVoidPointer( otherPointer, pointerType );
     
    171218                        } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst )
    172219                                           && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) {
     220                                // std::cerr << "middle case" << std::endl;
    173221                                Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers();
    174222                                pointerType->get_base()->get_qualifiers() = Type::Qualifiers();
     
    177225                                OpenVarSet newOpen( openVars );
    178226                                if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
     227                                        // std::cerr << "unifyExact success" << std::endl;
    179228                                        if ( tq1 < tq2 ) {
    180229                                                result = pointerType->clone();
     
    184233                                        result->get_qualifiers() = tq1 | tq2;
    185234                                } else {
    186                                         /// std::cout << "place for ptr-to-type" << std::endl;
     235                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    187236                                } // if
    188237                                pointerType->get_base()->get_qualifiers() = tq1;
     
    196245
    197246        void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
     247
     248        void CommonType::visit( ReferenceType *refType ) {
     249                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     250                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     251                        // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl;
     252                        if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
     253                                getCommonWithVoidPointer( otherRef, refType );
     254                        } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     255                                getCommonWithVoidPointer( refType, otherRef );
     256                        } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
     257                                           && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
     258                                // std::cerr << "middle case" << std::endl;
     259                                Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
     260                                refType->get_base()->get_qualifiers() = Type::Qualifiers();
     261                                otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
     262                                AssertionSet have, need;
     263                                OpenVarSet newOpen( openVars );
     264                                if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
     265                                        if ( tq1 < tq2 ) {
     266                                                result = refType->clone();
     267                                        } else {
     268                                                result = otherRef->clone();
     269                                        } // if
     270                                        result->get_qualifiers() = tq1 | tq2;
     271                                } else {
     272                                        /// std::cerr << "place for ptr-to-type" << std::endl;
     273                                } // if
     274                                refType->get_base()->get_qualifiers() = tq1;
     275                                otherRef->get_base()->get_qualifiers() = tq2;
     276                        } // if
     277                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     278                        result = refType->clone();
     279                        result->get_qualifiers() |= type2->get_qualifiers();
     280                } // if
     281        }
     282
    198283        void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    199284        void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
     
    203288                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    204289                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    205                         Type * temp = type2;
     290                        ValueGuard< Type * > temp( type2 );
    206291                        type2 = enumInstType;
    207                         temp->accept( *this );
    208                         type2 = temp;
     292                        temp.old->accept( *this );
    209293                } // if
    210294        }
  • src/ResolvExpr/ConversionCost.cc

    raf08051 r28e58fd  
    2828
    2929namespace ResolvExpr {
    30         const Cost Cost::zero = Cost( 0, 0, 0 );
    31         const Cost Cost::infinity = Cost( -1, -1, -1 );
     30        const Cost Cost::zero = Cost( 0, 0, 0, 0 );
     31        const Cost Cost::infinity = Cost( -1, -1, -1, -1 );
     32        const Cost Cost::unsafe = Cost( 1, 0, 0, 0 );
     33        const Cost Cost::poly = Cost( 0, 1, 0, 0 );
     34        const Cost Cost::safe = Cost( 0, 0, 1, 0 );
     35        const Cost Cost::reference = Cost( 0, 0, 0, 1 );
     36
     37#if 0
     38#define PRINT(x) x
     39#else
     40#define PRINT(x)
     41#endif
    3242
    3343        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     
    3545                        EqvClass eqvClass;
    3646                        NamedTypeDecl *namedType;
    37 ///     std::cout << "type inst " << destAsTypeInst->get_name();
     47                        PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
    3848                        if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    3949                                if ( eqvClass.type ) {
     
    4353                                }
    4454                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
    45 ///       std::cout << " found" << std::endl;
     55                                PRINT( std::cerr << " found" << std::endl; )
    4656                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    4757                                // all typedefs should be gone by this point
    4858                                assert( type );
    4959                                if ( type->get_base() ) {
    50                                         return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
     60                                        return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
    5161                                } // if
    5262                        } // if
    53 ///     std::cout << " not found" << std::endl;
    54                 } // if
    55 ///   std::cout << "src is ";
    56 ///   src->print( std::cout );
    57 ///   std::cout << std::endl << "dest is ";
    58 ///   dest->print( std::cout );
    59 ///   std::cout << std::endl << "env is" << std::endl;
    60 ///   env.print( std::cout, 8 );
     63                        PRINT( std::cerr << " not found" << std::endl; )
     64                } // if
     65                PRINT(
     66                        std::cerr << "src is ";
     67                        src->print( std::cerr );
     68                        std::cerr << std::endl << "dest is ";
     69                        dest->print( std::cerr );
     70                        std::cerr << std::endl << "env is" << std::endl;
     71                        env.print( std::cerr, 8 );
     72                )
    6173                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    62 ///     std::cout << "compatible!" << std::endl;
    63                         return Cost( 0, 0, 0 );
     74                        PRINT( std::cerr << "compatible!" << std::endl; )
     75                        return Cost::zero;
    6476                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    65                         return Cost( 0, 0, 1 );
     77                        return Cost::safe;
     78                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     79                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     80                        return convertToReferenceCost( src, refType, indexer, env );
    6681                } else {
    6782                        ConversionCost converter( dest, indexer, env );
     
    7085                                return Cost::infinity;
    7186                        } else {
    72                                 return converter.get_cost() + Cost( 0, 0, 0 );
    73                         } // if
    74                 } // if
     87                                return converter.get_cost() + Cost::zero;
     88                        } // if
     89                } // if
     90        }
     91
     92        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     93                PRINT( std::cerr << "convert to reference cost..." << std::endl; )
     94                if ( diff > 0 ) {
     95                        // TODO: document this
     96                        Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
     97                        cost.incReference();
     98                        return cost;
     99                } else if ( diff < -1 ) {
     100                        // TODO: document this
     101                        Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
     102                        cost.incReference();
     103                        return cost;
     104                } else if ( diff == 0 ) {
     105                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
     106                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     107                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
     108                                PRINT( std::cerr << "converting between references" << std::endl; )
     109                                if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
     110                                        return Cost::safe;
     111                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     112                                        int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
     113                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
     114                                        if ( assignResult < 0 ) {
     115                                                return Cost::safe;
     116                                        } else if ( assignResult > 0 ) {
     117                                                return Cost::unsafe;
     118                                        } // if
     119                                } // if
     120                        } else {
     121                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
     122                                ConversionCost converter( dest, indexer, env );
     123                                src->accept( converter );
     124                                return converter.get_cost();
     125                        } // if
     126                } else {
     127                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     128                        assert( diff == -1 && destAsRef );
     129                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     130                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
     131                                if ( src->get_lvalue() ) {
     132                                        PRINT(
     133                                                std::cerr << "lvalue to reference conversion" << std::endl;
     134                                                std::cerr << src << " => " << destAsRef << std::endl;
     135                                        )
     136                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
     137                                        if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     138                                                return Cost::reference; // cost needs to be non-zero to add cast
     139                                        } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     140                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
     141                                        } else {
     142                                                return Cost::unsafe;
     143                                        } // if
     144                                } else if ( destAsRef->get_base()->get_const() ) {
     145                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
     146                                        // rvalue-to-const-reference conversion: T => const T &
     147                                        return Cost::safe;
     148                                } else {
     149                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
     150                                        // rvalue-to-reference conversion: T => T &
     151                                        return Cost::unsafe;
     152                                } // if
     153                        } // if
     154                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
     155                }
     156                return Cost::infinity;
     157        }
     158
     159        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     160                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
     161                return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
    75162        }
    76163
     
    164251                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
    165252                        if ( tableResult == -1 ) {
    166                                 cost = Cost( 1, 0, 0 );
    167                         } else {
    168                                 cost = Cost( 0, 0, tableResult );
     253                                cost = Cost::unsafe;
     254                        } else {
     255                                cost = Cost::zero;
     256                                cost.incSafe( tableResult );
    169257                        } // if
    170258                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
    171259                        // xxx - not positive this is correct, but appears to allow casting int => enum
    172                         cost = Cost( 1, 0, 0 );
     260                        cost = Cost::unsafe;
    173261                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    174                         cost = Cost( 1, 0, 0 );
     262                        cost = Cost::unsafe;
    175263                } // if
    176264        }
     
    178266        void ConversionCost::visit(PointerType *pointerType) {
    179267                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    180                         if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    181                                 cost = Cost( 0, 0, 1 );
    182                         } else {
     268                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
     269                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
     270                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
     271                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     272                                if ( tq1 == tq2 ) {
     273                                        // types are the same
     274                                        cost = Cost::zero;
     275                                } else {
     276                                        // types are the same, except otherPointer has more qualifiers
     277                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     278                                        cost = Cost::safe;
     279                                }
     280                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    183281                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
    184                                 if ( assignResult < 0 ) {
    185                                         cost = Cost( 0, 0, 1 );
     282                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
     283                                if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
     284                                        cost = Cost::safe;
    186285                                } else if ( assignResult > 0 ) {
    187                                         cost = Cost( 1, 0, 0 );
     286                                        cost = Cost::unsafe;
    188287                                } // if
     288                                // assignResult == 0 means Cost::Infinity
    189289                        } // if
    190290                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    191                         cost = Cost( 1, 0, 0 );
     291                        cost = Cost::unsafe;
    192292                } // if
    193293        }
    194294
    195295        void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
     296
     297        void ConversionCost::visit(ReferenceType *refType) {
     298                // Note: dest can never be a reference, since it would have been caught in an earlier check
     299                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     300                // convert reference to rvalue: cv T1 & => T2
     301                // recursively compute conversion cost from T1 to T2.
     302                // cv can be safely dropped because of 'implicit dereference' behavior.
     303                refType->get_base()->accept( *this );
     304                if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
     305                        cost.incReference();  // prefer exact qualifiers
     306                } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
     307                        cost.incSafe(); // then gaining qualifiers
     308                } else {
     309                        cost.incUnsafe(); // lose qualifiers as last resort
     310                }
     311                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
     312        }
     313
    196314        void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
    197315
     
    215333                static Type::Qualifiers q;
    216334                static BasicType integer( q, BasicType::SignedInt );
    217                 integer.accept( *this );
    218                 if ( cost < Cost( 1, 0, 0 ) ) {
     335                integer.accept( *this );  // safe if dest >= int
     336                if ( cost < Cost::unsafe ) {
    219337                        cost.incSafe();
    220338                } // if
     
    238356                        assert( type );
    239357                        if ( type->get_base() ) {
    240                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
     358                                cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    241359                        } // if
    242360                } // if
     
    244362
    245363        void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
    246                 Cost c;
     364                Cost c = Cost::zero;
    247365                if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
    248366                        std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
     
    276394                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    277395                        if ( tableResult == -1 ) {
    278                                 cost = Cost( 1, 0, 0 );
    279                         } else {
    280                                 cost = Cost( 0, 0, tableResult + 1 );
     396                                cost = Cost::unsafe;
     397                        } else {
     398                                cost = Cost::zero;
     399                                cost.incSafe( tableResult + 1 );
    281400                        }
    282401                } else if ( dynamic_cast< PointerType* >( dest ) ) {
    283                         cost = Cost( 0, 0, 1 );
     402                        cost = Cost::safe;
    284403                }
    285404        }
     
    292411                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    293412                        if ( tableResult == -1 ) {
    294                                 cost = Cost( 1, 0, 0 );
    295                         } else {
    296                                 cost = Cost( 0, 0, tableResult + 1 );
     413                                cost = Cost::unsafe;
     414                        } else {
     415                                cost = Cost::zero;
     416                                cost.incSafe( tableResult + 1 );
    297417                        }
    298418                }
  • src/ResolvExpr/ConversionCost.h

    raf08051 r28e58fd  
    3737                virtual void visit(PointerType *pointerType);
    3838                virtual void visit(ArrayType *arrayType);
     39                virtual void visit(ReferenceType *refType);
    3940                virtual void visit(FunctionType *functionType);
    4041                virtual void visit(StructInstType *aggregateUseType);
     
    5354                const TypeEnvironment &env;
    5455        };
     56
     57        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    5558} // namespace ResolvExpr
    5659
  • src/ResolvExpr/Cost.h

    raf08051 r28e58fd  
    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/PtrsAssignable.cc

    raf08051 r28e58fd  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // PtrsAssignable.cc -- 
     7// PtrsAssignable.cc --
    88//
    99// Author           : Richard C. Bilson
     
    8282        void PtrsAssignable::visit(  __attribute__((unused)) UnionInstType *inst ) {}
    8383
    84         void PtrsAssignable::visit( EnumInstType *inst ) {
    85                 if ( dynamic_cast< EnumInstType* >( inst ) ) {
     84        void PtrsAssignable::visit( EnumInstType * ) {
     85                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    8686                        result = 1;
    87                 } else if ( BasicType *bt = dynamic_cast< BasicType* >( inst ) ) {
     87                } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
    8888                        result = bt->get_kind() == BasicType::SignedInt;
    8989                }
     
    104104        void PtrsAssignable::visit(  __attribute__((unused)) ZeroType *zeroType ) {}
    105105        void PtrsAssignable::visit(  __attribute__((unused)) OneType *oneType ) {}
    106        
     106
    107107} // namespace ResolvExpr
    108108
  • src/ResolvExpr/ResolveTypeof.cc

    raf08051 r28e58fd  
    6565                        assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
    6666                        Type *newType = newExpr->get_result();
     67                        newExpr->set_result( nullptr );
    6768                        delete typeofType;
     69                        delete newExpr;
    6870                        return newType;
    6971                } // if
  • src/ResolvExpr/Unify.cc

    raf08051 r28e58fd  
    5353                virtual void visit(PointerType *pointerType);
    5454                virtual void visit(ArrayType *arrayType);
     55                virtual void visit(ReferenceType *refType);
    5556                virtual void visit(FunctionType *functionType);
    5657                virtual void visit(StructInstType *aggregateUseType);
     
    153154
    154155        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 ) {
     156                // remove references from other, so that type variables can only bind to value types
     157                other = other->stripReferences();
    155158                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    156159                assert( tyvar != openVars.end() );
     
    387390                                } // if
    388391                        } else {
     392                                common = type1->clone();
     393                                common->get_qualifiers() = tq1 | tq2;
    389394                                result = true;
    390395                        } // if
     
    436441                        markAssertions( haveAssertions, needAssertions, pointerType );
    437442                        markAssertions( haveAssertions, needAssertions, otherPointer );
     443                } // if
     444        }
     445
     446        void Unify::visit(ReferenceType *refType) {
     447                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     448                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     449                        markAssertions( haveAssertions, needAssertions, refType );
     450                        markAssertions( haveAssertions, needAssertions, otherRef );
    438451                } // if
    439452        }
  • src/ResolvExpr/typeops.h

    raf08051 r28e58fd  
    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

    raf08051 r28e58fd  
    1313// Update Count     : 62
    1414//
     15
    1516#include "Autogen.h"
    1617
     
    2425#include <vector>                  // for vector
    2526
    26 #include "AddVisit.h"             // for addVisit
    27 #include "Common/ScopedMap.h"     // for ScopedMap
    28 #include "GenPoly/DeclMutator.h"  // for DeclMutator
    29 #include "GenPoly/ScopedSet.h"    // for ScopedSet
    30 #include "Parser/LinkageSpec.h"   // for AutoGen, Intrinsic, Spec
    31 #include "SymTab/Mangler.h"       // for mangleType
    32 #include "SynTree/Statement.h"    // for SwitchStmt (ptr only), CompoundStmt
    33 #include "SynTree/Type.h"         // for Type, ArrayType, Type::StorageClasses
    34 #include "SynTree/Visitor.h"      // for Visitor
     27#include "AddVisit.h"              // for addVisit
     28#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
     29#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
     30#include "Common/utility.h"        // for cloneAll, operator+
     31#include "GenPoly/DeclMutator.h"   // for DeclMutator
     32#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
     33#include "SymTab/Mangler.h"        // for Mangler
     34#include "SynTree/Attribute.h"     // For Attribute
     35#include "SynTree/Mutator.h"       // for maybeMutate
     36#include "SynTree/Statement.h"     // for CompoundStmt, ReturnStmt, ExprStmt
     37#include "SynTree/Type.h"          // for FunctionType, Type, TypeInstType
     38#include "SynTree/Visitor.h"       // for maybeAccept, Visitor, acceptAll
     39
     40class Attribute;
    3541
    3642namespace SymTab {
     
    130136        FunctionType * genDefaultType( Type * paramType ) {
    131137                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    132                 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );
     138                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    133139                ftype->get_parameters().push_back( dstParam );
    134140
     
    150156                ftype->get_returnVals().push_back( returnVal );
    151157                return ftype;
    152         }
    153 
    154         /// true if the aggregate's layout is dynamic
    155         template< typename AggrDecl >
    156         bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
    157                 for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
    158                         if ( param->isComplete() ) return true;
    159                 }
    160                 return false;
    161158        }
    162159
     
    181178                        FunctionType * ftype = funcDecl->get_functionType();
    182179                        assert( ! ftype->get_parameters().empty() );
    183                         Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base();
     180                        Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );
     181                        assert( t );
    184182                        map.insert( Mangler::mangleType( t ), true );
    185183                }
     
    227225                        FunctionType * ftype = data.genType( refType );
    228226
    229                         if(concurrent_type && InitTweak::isDestructor( data.fname )) {
     227                        if(concurrent_type && CodeGen::isDestructor( data.fname )) {
    230228                                ftype->get_parameters().front()->get_type()->set_mutex( true );
    231229                        }
     
    279277                FunctionType *copyCtorType = genCopyType( refType->clone() );
    280278
     279                // add unused attribute to parameters of default constructor and destructor
     280                ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     281                dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     282
    281283                // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    282284                // right now these cases work, but that might change.
     
    301303
    302304        /// generates a single struct member operation (constructor call, destructor call, assignment call)
    303         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
    304                 ObjectDecl * returnVal = NULL;
    305                 if ( ! func->get_functionType()->get_returnVals().empty() ) {
    306                         returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
    307                 }
    308 
     305        void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) {
    309306                InitTweak::InitExpander srcParam( src );
    310307
    311                 // assign to destination (and return value if generic)
    312                 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) );
    313                 Expression *dstselect = new MemberExpr( field, derefExpr );
     308                // assign to destination
     309                Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), safe_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) );
    314310                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    315 
    316                 if ( isDynamicLayout && returnVal ) {
    317                         // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?
    318                         Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );
    319                         genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    320                 } // if
    321311        }
    322312
    323313        /// 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
    324314        template<typename Iterator>
    325         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
     315        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ) {
    326316                for ( ; member != end; ++member ) {
    327317                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    359349
    360350                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    361                                 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );
     351                                makeStructMemberOp( dstParam, srcselect, field, func, forward );
    362352                        } // if
    363353                } // for
     
    367357        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
    368358        template<typename Iterator>
    369         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {
     359        void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
    370360                FunctionType * ftype = func->get_functionType();
    371361                std::list<DeclarationWithType*> & params = ftype->get_parameters();
     
    393383                                        // matching parameter, initialize field with copy ctor
    394384                                        Expression *srcselect = new VariableExpr(*parameter);
    395                                         makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );
     385                                        makeStructMemberOp( dstParam, srcselect, field, func );
    396386                                        ++parameter;
    397387                                } else {
    398388                                        // no matching parameter, initialize field with default ctor
    399                                         makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );
     389                                        makeStructMemberOp( dstParam, NULL, field, func );
    400390                                }
    401391                        }
     
    413403                // Make function polymorphic in same parameters as generic struct, if applicable
    414404                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    415                 bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    416405
    417406                // generate each of the functions based on the supplied FuncData objects
     
    423412
    424413                // field ctors are only generated if default constructor and copy constructor are both generated
    425                 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );
     414                unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
    426415
    427416                if ( functionNesting == 0 ) {
     
    438427                        // generate appropriate calls to member ctor, assignment
    439428                        // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
    440                         if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {
    441                                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout );
     429                        if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {
     430                                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl );
    442431                        } else {
    443                                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false );
    444                         }
    445                         if ( InitTweak::isAssignment( dcl->get_name() ) ) {
     432                                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false );
     433                        }
     434                        if ( CodeGen::isAssignment( dcl->get_name() ) ) {
    446435                                // assignment needs to return a value
    447436                                FunctionType * assignType = dcl->get_functionType();
     
    472461                                        // our inheritance model. I think the correct way to handle this is to
    473462                                        // cast the structure to the type of the member and let the resolver
    474                                         // figure out whether it's valid and have a pass afterwards that fixes
    475                                         // the assignment to use pointer arithmetic with the offset of the
    476                                         // member, much like how generic type members are handled.
     463                                        // figure out whether it's valid/choose the correct unnamed member
    477464                                        continue;
    478465                                }
    479466                                memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    480467                                FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    481                                 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
     468                                makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor );
    482469                                declsToAdd.push_back( ctor );
    483470                        }
     
    490477        void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    491478                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    492                 copy->get_args().push_back( new VariableExpr( dstParam ) );
     479                copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
    493480                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    494481                copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     
    502489                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    503490                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    504                 ObjectDecl * returnVal = nullptr;
    505                 if ( ! ftype->get_returnVals().empty() ) {
    506                         returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );
    507                 }
    508491
    509492                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
    510                 if ( returnVal ) {
     493                if ( CodeGen::isAssignment( funcDecl->get_name() ) ) {
     494                        // also generate return statement in assignment
    511495                        funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    512496                }
     
    535519                cloneAll( typeParams, copyCtorType->get_forall() );
    536520                cloneAll( typeParams, assignType->get_forall() );
     521
     522                // add unused attribute to parameters of default constructor and destructor
     523                ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
     524                dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    537525
    538526                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
  • src/SymTab/Autogen.h

    raf08051 r28e58fd  
    4040        extern Type * SizeType;
    4141
     42        /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
     43        /// Useful for creating dereference ApplicationExprs without a full resolver pass.
     44        extern FunctionDecl * dereferenceOperator;
     45
     46        // temporary
     47        FunctionType * genAssignType( Type * paramType );
     48
    4249        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    4350        template< typename OutputIterator >
     
    4855        template< typename OutputIterator >
    4956        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    50         // want to be able to generate assignment, ctor, and dtor generically,
    51         // so fname is either ?=?, ?{}, or ^?{}
    52         UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     57                // want to be able to generate assignment, ctor, and dtor generically,
     58                // so fname is either ?=?, ?{}, or ^?{}
     59                UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    5360
    54         // do something special for unnamed members
    55         dstParam = new AddressExpr( dstParam );
    56         if ( addCast ) {
    57                 // cast to T* with qualifiers removed, so that qualified objects can be constructed
    58                 // and destructed with the same functions as non-qualified objects.
    59                 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    60                 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever