Changeset 65cec25


Ignore:
Timestamp:
Jul 13, 2017, 3:06:29 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
6b9b047
Parents:
2463d0e
Message:

Compute common type when reference types are involved

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CommonType.cc

    r2463d0e r65cec25  
    1717#include "SynTree/Type.h"
    1818#include "Unify.h"
    19 
    2019
    2120/// #define DEBUG
     
    3130                virtual void visit( PointerType *pointerType );
    3231                virtual void visit( ArrayType *arrayType );
     32                virtual void visit( ReferenceType *refType );
    3333                virtual void visit( FunctionType *functionType );
    3434                virtual void visit( StructInstType *aggregateUseType );
     
    4242                virtual void visit( OneType *oneType );
    4343
    44                 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer );
     44                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
     45                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    4546
    4647                Type *result;
     
    5253        };
    5354
     55        Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
     56                Type * result = nullptr, * common = nullptr;
     57                AssertionSet have, need;
     58                OpenVarSet newOpen( openVars );
     59                // need unify to bind type variables
     60                if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
     61                        // std::cerr << "unify success" << std::endl;
     62                        if ( widenSecond ) {
     63                                if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
     64                                        result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
     65                                        result->get_qualifiers() |= other->get_qualifiers();
     66                                }
     67                        } else if ( widenFirst ) {
     68                                if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
     69                                        result = common;
     70                                        result->get_qualifiers() |= refType->get_qualifiers();
     71                                }
     72                        }
     73                } else {
     74                        // std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
     75                }
     76                // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
     77                return result;
     78        }
     79
    5480        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    5581                CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     82
     83                ReferenceType * refType1 = dynamic_cast< ReferenceType * >( type1 );
     84                ReferenceType * refType2 = dynamic_cast< ReferenceType * >( type2 );
     85                if ( (refType1 || refType2) && (! refType1 || ! refType2) ) {
     86                        // handle the case where exactly one of the types is a reference type specially
     87                        if ( refType1 ) {
     88                                return handleReference( refType1, type2, widenFirst, widenSecond, indexer, env, openVars );
     89                        } else if ( refType2 ) {
     90                                return handleReference( refType2, type1, widenSecond, widenFirst, indexer, env, openVars );
     91                        }
     92                }
     93
    5694                type1->accept( visitor );
    5795                Type *result = visitor.get_result();
     
    142180        }
    143181
    144         void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) {
     182        template< typename Pointer >
     183        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    145184                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    146185                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
     
    188227
    189228        void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
     229
     230        void CommonType::visit( ReferenceType *refType ) {
     231                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     232                        if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
     233                                getCommonWithVoidPointer( otherRef, refType );
     234                        } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     235                                getCommonWithVoidPointer( refType, otherRef );
     236                        } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
     237                                           && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
     238                                Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
     239                                refType->get_base()->get_qualifiers() = Type::Qualifiers();
     240                                otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
     241                                AssertionSet have, need;
     242                                OpenVarSet newOpen( openVars );
     243                                if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
     244                                        if ( tq1 < tq2 ) {
     245                                                result = refType->clone();
     246                                        } else {
     247                                                result = otherRef->clone();
     248                                        } // if
     249                                        result->get_qualifiers() = tq1 | tq2;
     250                                } else {
     251                                        /// std::cout << "place for ptr-to-type" << std::endl;
     252                                } // if
     253                                refType->get_base()->get_qualifiers() = tq1;
     254                                otherRef->get_base()->get_qualifiers() = tq2;
     255                        } // if
     256                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     257                        result = refType->clone();
     258                        result->get_qualifiers() |= type2->get_qualifiers();
     259                } // if
     260        }
     261
    190262        void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    191263        void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
     
    195267                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    196268                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    197                         Type * temp = type2;
     269                        ValueGuard< Type * > temp( type2 );
    198270                        type2 = enumInstType;
    199                         temp->accept( *this );
    200                         type2 = temp;
     271                        temp.old->accept( *this );
    201272                } // if
    202273        }
Note: See TracChangeset for help on using the changeset viewer.