Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (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/PtrsAssignable.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 11:44:11 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:36:05 2016
    13 // Update Count     : 8
    14 //
    15 
     11// Last Modified By : Andrew
     12// Last Modified On : Mon Jun 24 15:29:00 2019
     13// Update Count     : 9
     14//
     15
     16#include "typeops.h"
     17
     18#include "AST/Pass.hpp"
     19#include "AST/Type.hpp"
     20#include "AST/TypeEnvironment.hpp"
    1621#include "Common/PassVisitor.h"
    1722#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2227namespace ResolvExpr {
    2328        struct PtrsAssignable : public WithShortCircuiting {
    24                 PtrsAssignable( Type *dest, const TypeEnvironment &env );
     29                PtrsAssignable( const Type * dest, const TypeEnvironment &env );
    2530
    2631                int get_result() const { return result; }
    2732
    28                 void previsit( Type * ) { visit_children = false; }
    29 
    30                 void postvisit( VoidType * voidType );
    31                 void postvisit( BasicType * basicType );
    32                 void postvisit( PointerType * pointerType );
    33                 void postvisit( ArrayType * arrayType );
    34                 void postvisit( FunctionType * functionType );
    35                 void postvisit( StructInstType * inst );
    36                 void postvisit( UnionInstType * inst );
    37                 void postvisit( EnumInstType * inst );
    38                 void postvisit( TraitInstType * inst );
    39                 void postvisit( TypeInstType * inst );
    40                 void postvisit( TupleType * tupleType );
    41                 void postvisit( VarArgsType * varArgsType );
    42                 void postvisit( ZeroType * zeroType );
    43                 void postvisit( OneType * oneType );
     33                void previsit( const Type * ) { visit_children = false; }
     34
     35                void postvisit( const VoidType * voidType );
     36                void postvisit( const BasicType * basicType );
     37                void postvisit( const PointerType * pointerType );
     38                void postvisit( const ArrayType * arrayType );
     39                void postvisit( const FunctionType * functionType );
     40                void postvisit( const StructInstType * inst );
     41                void postvisit( const UnionInstType * inst );
     42                void postvisit( const EnumInstType * inst );
     43                void postvisit( const TraitInstType * inst );
     44                void postvisit( const TypeInstType * inst );
     45                void postvisit( const TupleType * tupleType );
     46                void postvisit( const VarArgsType * varArgsType );
     47                void postvisit( const ZeroType * zeroType );
     48                void postvisit( const OneType * oneType );
    4449          private:
    45                 Type *dest;
     50                const Type * dest;
    4651                int result;
    4752                const TypeEnvironment &env;
    4853        };
    4954
    50         int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {
     55        int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
    5156                // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    52                 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    53                         if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     57                if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
     58                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    5459                                return ptrsAssignable( src, eqvClass->type, env );
    5560                        } // if
    5661                } // if
    57                 if ( dynamic_cast< VoidType* >( dest ) ) {
     62                if ( dynamic_cast< const VoidType* >( dest ) ) {
    5863                        // void * = T * for any T is unsafe
    5964                        // xxx - this should be safe, but that currently breaks the build
     
    6671        }
    6772
    68         PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    69 
    70         void PtrsAssignable::postvisit( VoidType * ) {
     73        PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
     74
     75        void PtrsAssignable::postvisit( const VoidType * ) {
    7176                // T * = void * is disallowed - this is a change from C, where any
    7277                // void * can be assigned or passed to a non-void pointer without a cast.
    7378        }
    7479
    75         void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {}
    76         void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {}
    77         void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {}
    78         void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {}
    79 
    80         void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
    81         void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
    82 
    83         void PtrsAssignable::postvisit( EnumInstType * ) {
    84                 if ( dynamic_cast< BasicType* >( dest ) ) {
     80        void PtrsAssignable::postvisit( const BasicType * ) {}
     81        void PtrsAssignable::postvisit( const PointerType * ) {}
     82        void PtrsAssignable::postvisit( const ArrayType * ) {}
     83        void PtrsAssignable::postvisit( const FunctionType * ) {}
     84
     85        void PtrsAssignable::postvisit( const StructInstType * ) {}
     86        void PtrsAssignable::postvisit( const UnionInstType * ) {}
     87
     88        void PtrsAssignable::postvisit( const EnumInstType * ) {
     89                if ( dynamic_cast< const BasicType* >( dest ) ) {
    8590                        // int * = E *, etc. is safe. This isn't technically correct, as each
    8691                        // enum has one basic type that it is compatible with, an that type can
     
    9297        }
    9398
    94         void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
    95         void PtrsAssignable::postvisit( TypeInstType *inst ) {
    96                 if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
     99        void PtrsAssignable::postvisit(  const TraitInstType * ) {}
     100        void PtrsAssignable::postvisit( const TypeInstType * inst ) {
     101                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    97102                        if ( eqvClass->type ) {
    98103                                // T * = S * for any S depends on the type bound to T
     
    102107        }
    103108
    104         void PtrsAssignable::postvisit(  __attribute__((unused)) TupleType *tupleType ) {}
    105         void PtrsAssignable::postvisit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
    106         void PtrsAssignable::postvisit(  __attribute__((unused)) ZeroType *zeroType ) {}
    107         void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
     109        void PtrsAssignable::postvisit( const TupleType * ) {}
     110        void PtrsAssignable::postvisit( const VarArgsType * ) {}
     111        void PtrsAssignable::postvisit( const ZeroType * ) {}
     112        void PtrsAssignable::postvisit( const OneType * ) {}
     113
     114// TODO: Get rid of the `_new` suffix when the old version is removed.
     115struct PtrsAssignable_new : public ast::WithShortCircuiting {
     116        const ast::Type * dst;
     117        const ast::TypeEnvironment & typeEnv;
     118        int result;
     119
     120        PtrsAssignable_new( const ast::Type * dst, const ast::TypeEnvironment & env ) :
     121                dst( dst ), typeEnv( env ), result( 0 ) {}
     122
     123        void previsit( Type * ) { visit_children = false; }
     124
     125        void postvisit( const ast::EnumInstType * ) {
     126                if ( dynamic_cast< const ast::BasicType * >( dst ) ) {
     127                        // int * = E *, etc. is safe. This isn't technically correct, as each
     128                        // enum has one basic type that it is compatible with, an that type can
     129                        // differ from enum to enum. Without replicating GCC's internal logic,
     130                        // there is no way to know which type this particular enum is compatible
     131                        // with, so punt on this for now.
     132                        result = 1;
     133                }
     134        }
     135        void postvisit( const ast::TypeInstType * inst ) {
     136                if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name ) ) {
     137                        if ( eqv->bound ) {
     138                                // T * = S * for any S depends on the type bound to T
     139                                result = ptrsAssignable( eqv->bound, dst, typeEnv );
     140                        }
     141                }
     142        }
     143};
     144
     145int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
     146                const ast::TypeEnvironment & env ) {
     147        if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     148                if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name ) ) {
     149                        return ptrsAssignable( src, eqv->bound, env );
     150                }
     151        }
     152        if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     153                return -1;
     154        } else {
     155                ast::Pass<PtrsAssignable_new> visitor( dst, env );
     156                src->accept( visitor );
     157                return visitor.pass.result;
     158        }
     159
     160// see ticket #136 (this should be able to replace the visitor).
     161#if 0
     162        if ( const ast::TypeInstType * dstAsTypeInst =
     163                        dynamic_cast< const ast::TypeInstType* >( dst ) ) {
     164                if ( const ast::EqvClass * eqv = env.lookup( dstAsTypeInst->get_name() ) ) {
     165                        return ptrsAssignable( src, eqv->type, env );
     166                } // if
     167        } // if
     168        if ( dynamic_cast< VoidType* >( dst ) ) {
     169                // void * = T * for any T is unsafe
     170                // xxx - this should be safe, but that currently breaks the build
     171                return -1;
     172        } else if ( dynamic_cast< EnumInstType * >( src ) ) {
     173                if ( dynamic_cast< BasicType * >( dst ) ) {
     174                        // int * = E *, etc. is safe. This isn't technically correct, as each
     175                        // enum has one basic type that it is compatible with, an that type can
     176                        // differ from enum to enum. Without replicating GCC's internal logic,
     177                        // there is no way to know which type this particular enum is compatible
     178                        // with, so punt on this for now.
     179                        return 1;
     180                }
     181        } else if ( const ast::TypeInstType * typeInstType =
     182                        dynamic_cast< const ast::TypeInstType * >( src ) ) {
     183                if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
     184                        if ( eqv->bound ) {
     185                                // T * = S * for any S depends on the type bound to T
     186                                return ptrsAssignable( eqv->bound, dst, env );
     187                        }
     188                }
     189        }
     190        return 0;
     191#endif
     192}
    108193
    109194} // namespace ResolvExpr
Note: See TracChangeset for help on using the changeset viewer.