Ignore:
Timestamp:
Aug 25, 2017, 12:11:53 PM (8 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
bf7b9da7
Parents:
135b431 (diff), f676b84 (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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CommonType.cc

    r135b431 r6b224a52  
    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        }
Note: See TracChangeset for help on using the changeset viewer.