Changeset 3e2f5e3 for src


Ignore:
Timestamp:
Jun 24, 2019, 4:11:41 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation
Children:
2856438, 6c55a3d
Parents:
3623f9d (diff), 1335e6f (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:
8 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Type.hpp

    r3623f9d r3e2f5e3  
    164164        static const char *typeNames[];
    165165
    166         BasicType( Kind k, CV::Qualifiers q = {} ) : Type(q), kind(k) {}
     166        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     167        : Type(q, std::move(as)), kind(k) {}
    167168
    168169        /// Check if this type represents an integer type
  • src/ResolvExpr/CastCost.cc

    r3623f9d r3e2f5e3  
    1616#include <cassert>                       // for assert
    1717
     18#include "AST/Print.hpp"
     19#include "AST/SymbolTable.hpp"
     20#include "AST/Type.hpp"
     21#include "AST/TypeEnvironment.hpp"
    1822#include "ConversionCost.h"              // for ConversionCost
    1923#include "Cost.h"                        // for Cost, Cost::infinity
     
    3135
    3236namespace ResolvExpr {
    33         struct CastCost : public ConversionCost {
     37        struct CastCost_old : public ConversionCost {
    3438          public:
    35                 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
     39                CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3640
    3741                using ConversionCost::previsit;
     
    7882                        });
    7983                } else {
    80                         #warning cast on castCost artifact of having two functions, remove when port done
    81                         PassVisitor<CastCost> converter(
     84                        PassVisitor<CastCost_old> converter(
    8285                                dest, indexer, env,
    8386                                (Cost (*)( Type *, Type *, const SymTab::Indexer &, const TypeEnvironment & ))
     
    9396        }
    9497
    95         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     98        CastCost_old::CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    9699                : ConversionCost( dest, indexer, env, costFunc ) {
    97100        }
    98101
    99         void CastCost::postvisit( BasicType *basicType ) {
     102        void CastCost_old::postvisit( BasicType *basicType ) {
    100103                PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
    101104                if ( destAsPointer && basicType->isInteger() ) {
     
    107110        }
    108111
    109         void CastCost::postvisit( PointerType *pointerType ) {
     112        void CastCost_old::postvisit( PointerType *pointerType ) {
    110113                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    111114                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     
    130133        }
    131134
    132         Cost castCost(
    133                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    134                 const ast::TypeEnvironment & env
    135         ) {
    136                 #warning unimplmented
    137                 (void)src; (void)dst; (void)symtab; (void)env;
    138                 assert(false);
     135namespace {
     136        struct CastCost_new : public ConversionCost_new {
     137                using ConversionCost_new::previsit;
     138                using ConversionCost_new::postvisit;
     139
     140                CastCost_new(
     141                        const ast::Type * dst, const ast::SymbolTable & symtab,
     142                        const ast::TypeEnvironment & env, CostCalculation costFunc )
     143                : ConversionCost_new( dst, symtab, env, costFunc ) {}
     144
     145                void postvisit( const ast::BasicType * basicType ) {
     146                        auto ptr = dynamic_cast< const ast::PointerType * >( dst );
     147                        if ( ptr && basicType->isInteger() ) {
     148                                // needed for, e.g. unsigned long => void *
     149                                cost = Cost::unsafe;
     150                        } else {
     151                                cost = conversionCost( basicType, dst, symtab, env );
     152                        }
     153                }
     154
     155                void postvisit( const ast::PointerType * pointerType ) {
     156                        if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
     157                                if (
     158                                        pointerType->qualifiers <= ptr->qualifiers
     159                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
     160                                ) {
     161                                        cost = Cost::safe;
     162                                } else {
     163                                        ast::TypeEnvironment newEnv{ env };
     164                                        if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
     165                                                newEnv.add( wParams->forall );
     166                                        }
     167                                        int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
     168                                        if ( castResult > 0 ) {
     169                                                cost = Cost::safe;
     170                                        } else if ( castResult < 0 ) {
     171                                                cost = Cost::infinity;
     172                                        }
     173                                }
     174                        } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
     175                                if ( basic->isInteger() ) {
     176                                        // necessary for, e.g. void * => unsigned long
     177                                        cost = Cost::unsafe;
     178                                }
     179                        }
     180                }
     181        };
     182} // anonymous namespace
     183
     184Cost castCost(
     185        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     186        const ast::TypeEnvironment & env
     187) {
     188        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     189                if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
     190                        // check cast cost against bound type, if present
     191                        if ( eqvClass->bound ) {
     192                                return castCost( src, eqvClass->bound, symtab, env );
     193                        } else {
     194                                return Cost::infinity;
     195                        }
     196                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
     197                        // all typedefs should be gone by now
     198                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
     199                        if ( type->base ) {
     200                                return castCost( src, type->base, symtab, env ) + Cost::safe;
     201                        }
     202                }
     203        }
     204
     205        PRINT(
     206                std::cerr << "castCost ::: src is ";
     207                ast::print( std::cerr, src );
     208                std::cerr << std::endl << "dest is ";
     209                ast::print( std::cerr, dst );
     210                std::cerr << std::endl << "env is" << std::endl;
     211                ast::print( std::cerr, env, 2 );
     212        )
     213
     214        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     215                PRINT( std::cerr << "compatible!" << std::endl; )
    139216                return Cost::zero;
    140         }
     217        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     218                return Cost::safe;
     219        } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
     220                PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     221                #warning cast on ptrsCastable artifact of having two functions, remove when port done
     222                return convertToReferenceCost(
     223                        src, refType, symtab, env,
     224                        ( int (*)(
     225                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     226                                const ast::TypeEnvironment & )
     227                        ) ptrsCastable );
     228        } else {
     229                #warning cast on castCost artifact of having two functions, remove when port done
     230                ast::Pass< CastCost_new > converter{
     231                        dst, symtab, env,
     232                        ( Cost (*)(
     233                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     234                                const ast::TypeEnvironment & )
     235                        ) castCost };
     236                src->accept( converter );
     237                return converter.pass.cost;
     238        }
     239}
     240
    141241} // namespace ResolvExpr
    142242
  • src/ResolvExpr/ConversionCost.h

    r3623f9d r3e2f5e3  
    7474        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    7575
    76 // TODO: When the old ConversionCost is removed, get ride of the _new suffix.
     76#warning when the old ConversionCost is removed, get ride of the _new suffix.
    7777class ConversionCost_new : public ast::WithShortCircuiting {
     78protected:
    7879        const ast::Type * dst;
    7980        const ast::SymbolTable & symtab;
  • src/ResolvExpr/PtrsAssignable.cc

    r3623f9d r3e2f5e3  
    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 
    16 #include "AST/Fwd.hpp"
     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"
    1721#include "Common/PassVisitor.h"
    1822#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    108112        void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
    109113
     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
    110145int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
    111146                const ast::TypeEnvironment & env ) {
    112         #warning unimplemented
    113         (void)src;
    114         (void)dst;
    115         (void)env;
    116         assert(0);
     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        }
    117190        return 0;
     191#endif
    118192}
    119193
  • src/ResolvExpr/PtrsCastable.cc

    r3623f9d r3e2f5e3  
    1414//
    1515
     16#include "AST/Decl.hpp"
     17#include "AST/Pass.hpp"
     18#include "AST/Type.hpp"
     19#include "AST/TypeEnvironment.hpp"
    1620#include "Common/PassVisitor.h"
    1721#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2327
    2428namespace ResolvExpr {
    25         struct PtrsCastable : public WithShortCircuiting  {
     29        struct PtrsCastable_old : public WithShortCircuiting  {
    2630          public:
    27                 PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     31                PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    2832
    2933                int get_result() const { return result; }
     
    8690                        return objectCast( src, env, indexer );
    8791                } else {
    88                         PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
     92                        PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
    8993                        src->accept( ptrs );
    9094                        return ptrs.pass.get_result();
     
    9296        }
    9397
    94         PtrsCastable::PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
     98        PtrsCastable_old::PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    9599                : dest( dest ), result( 0 ), env( env ), indexer( indexer )     {
    96100        }
    97101
    98         void PtrsCastable::postvisit( VoidType * ) {
    99                 result = objectCast( dest, env, indexer );
    100         }
    101 
    102         void PtrsCastable::postvisit( BasicType * ) {
    103                 result = objectCast( dest, env, indexer );
    104         }
    105 
    106         void PtrsCastable::postvisit( PointerType * ) {
    107                 result = objectCast( dest, env, indexer );
    108         }
    109 
    110         void PtrsCastable::postvisit( ArrayType * ) {
    111                 result = objectCast( dest, env, indexer );
    112         }
    113 
    114         void PtrsCastable::postvisit( FunctionType * ) {
     102        void PtrsCastable_old::postvisit( VoidType * ) {
     103                result = objectCast( dest, env, indexer );
     104        }
     105
     106        void PtrsCastable_old::postvisit( BasicType * ) {
     107                result = objectCast( dest, env, indexer );
     108        }
     109
     110        void PtrsCastable_old::postvisit( PointerType * ) {
     111                result = objectCast( dest, env, indexer );
     112        }
     113
     114        void PtrsCastable_old::postvisit( ArrayType * ) {
     115                result = objectCast( dest, env, indexer );
     116        }
     117
     118        void PtrsCastable_old::postvisit( FunctionType * ) {
    115119                // result = -1;
    116120                result = functionCast( dest, env, indexer );
    117121        }
    118122
    119         void PtrsCastable::postvisit( StructInstType * ) {
    120                 result = objectCast( dest, env, indexer );
    121         }
    122 
    123         void PtrsCastable::postvisit( UnionInstType * ) {
    124                 result = objectCast( dest, env, indexer );
    125         }
    126 
    127         void PtrsCastable::postvisit( EnumInstType * ) {
     123        void PtrsCastable_old::postvisit( StructInstType * ) {
     124                result = objectCast( dest, env, indexer );
     125        }
     126
     127        void PtrsCastable_old::postvisit( UnionInstType * ) {
     128                result = objectCast( dest, env, indexer );
     129        }
     130
     131        void PtrsCastable_old::postvisit( EnumInstType * ) {
    128132                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    129133                        result = 1;
     
    139143        }
    140144
    141         void PtrsCastable::postvisit( TraitInstType * ) {}
    142 
    143         void PtrsCastable::postvisit(TypeInstType *inst) {
     145        void PtrsCastable_old::postvisit( TraitInstType * ) {}
     146
     147        void PtrsCastable_old::postvisit(TypeInstType *inst ) {
    144148                //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    145149                result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    146150        }
    147151
    148         void PtrsCastable::postvisit( TupleType * ) {
    149                 result = objectCast( dest, env, indexer );
    150         }
    151 
    152         void PtrsCastable::postvisit( VarArgsType * ) {
    153                 result = objectCast( dest, env, indexer );
    154         }
    155 
    156         void PtrsCastable::postvisit( ZeroType * ) {
    157                 result = objectCast( dest, env, indexer );
    158         }
    159 
    160         void PtrsCastable::postvisit( OneType * ) {
    161                 result = objectCast( dest, env, indexer );
    162         }
     152        void PtrsCastable_old::postvisit( TupleType * ) {
     153                result = objectCast( dest, env, indexer );
     154        }
     155
     156        void PtrsCastable_old::postvisit( VarArgsType * ) {
     157                result = objectCast( dest, env, indexer );
     158        }
     159
     160        void PtrsCastable_old::postvisit( ZeroType * ) {
     161                result = objectCast( dest, env, indexer );
     162        }
     163
     164        void PtrsCastable_old::postvisit( OneType * ) {
     165                result = objectCast( dest, env, indexer );
     166        }
     167
     168namespace {
     169        // can this type be cast to an object (1 for yes, -1 for no)
     170        int objectCast(
     171                const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
     172        ) {
     173                if ( dynamic_cast< const ast::FunctionType * >( src ) ) {
     174                        return -1;
     175                } else if ( auto inst = dynamic_cast< const ast::TypeInstType * >( src ) ) {
     176                        if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
     177                                if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( named ) ) {
     178                                        if ( tyDecl->kind == ast::TypeVar::Ftype ) {
     179                                                return -1;
     180                                        }
     181                                }
     182                        } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     183                                if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
     184                                        return -1;
     185                                }
     186                        }
     187                }
     188
     189                return 1;
     190        }
     191
     192        // can this type be cast to a function (inverse of objectCast)
     193        int functionCast(
     194                const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
     195        ) {
     196                return -1 * objectCast( src, env, symtab );
     197        }
     198
     199        class PtrsCastable_new : public ast::WithShortCircuiting {
     200                const ast::Type * dst;
     201                const ast::TypeEnvironment & env;
     202                const ast::SymbolTable & symtab;
     203        public:
     204                int result;
     205
     206                PtrsCastable_new(
     207                        const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
     208                : dst( d ), env( e ), symtab( syms ), result( 0 ) {}
     209
     210                void previsit( const ast::Type * ) { visit_children = false; }
     211
     212                void postvisit( const ast::VoidType * ) {
     213                        result = objectCast( dst, env, symtab );
     214                }
     215
     216                void postvisit( const ast::BasicType * ) {
     217                        result = objectCast( dst, env, symtab );
     218                }
     219
     220                void postvisit( const ast::PointerType * ) {
     221                        result = objectCast( dst, env, symtab );
     222                }
     223
     224                void postvisit( const ast::ArrayType * ) {
     225                        result = objectCast( dst, env, symtab );
     226                }
     227
     228                void postvisit( const ast::FunctionType * ) {
     229                        result = functionCast( dst, env, symtab );
     230                }
     231
     232                void postvisit( const ast::StructInstType * ) {
     233                        result = objectCast( dst, env, symtab );
     234                }
     235
     236                void postvisit( const ast::UnionInstType * ) {
     237                        result = objectCast( dst, env, symtab );
     238                }
     239
     240                void postvisit( const ast::EnumInstType * ) {
     241                        if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     242                                result = 1;
     243                        } else if ( auto bt = dynamic_cast< const ast::BasicType * >( dst ) ) {
     244                                if ( bt->kind == ast::BasicType::SignedInt ) {
     245                                        result = 0;
     246                                } else {
     247                                        result = 1;
     248                                }
     249                        } else {
     250                                result = objectCast( dst, env, symtab );
     251                        }
     252                }
     253
     254                void postvisit( const ast::TraitInstType * ) {}
     255
     256                void postvisit( const ast::TypeInstType * inst ) {
     257                        // check trait and destination type are both object or both function
     258                        result = objectCast( inst, env, symtab ) == objectCast( dst, env, symtab ) ? 1 : -1;
     259                }
     260
     261                void postvisit( const ast::TupleType * ) {
     262                        result = objectCast( dst, env, symtab );
     263                }
     264
     265                void postvisit( const ast::VarArgsType * ) {
     266                        result = objectCast( dst, env, symtab );
     267                }
     268
     269                void postvisit( const ast::ZeroType * ) {
     270                        result = objectCast( dst, env, symtab );
     271                }
     272
     273                void postvisit( const ast::OneType * ) {
     274                        result = objectCast( dst, env, symtab );
     275                }
     276
     277        };
     278} // anonymous namespace
     279
     280int ptrsCastable(
     281        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     282        const ast::TypeEnvironment & env
     283) {
     284        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     285                if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     286                        return ptrsAssignable( src, eqvClass->bound, env );
     287                }
     288        }
     289
     290        if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     291                return objectCast( src, env, symtab );
     292        } else {
     293                ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
     294                src->accept( ptrs );
     295                return ptrs.pass.result;
     296        }
     297}
     298
    163299} // namespace ResolvExpr
    164300
  • src/ResolvExpr/ResolveTypeof.cc

    r3623f9d r3e2f5e3  
    1818#include <cassert>               // for assert
    1919
     20#include "AST/CVQualifiers.hpp"
     21#include "AST/Node.hpp"
     22#include "AST/Pass.hpp"
     23#include "AST/Type.hpp"
     24#include "AST/TypeEnvironment.hpp"
    2025#include "Common/PassVisitor.h"  // for PassVisitor
     26#include "Common/utility.h"      // for copy
    2127#include "Resolver.h"            // for resolveInVoidContext
    2228#include "SynTree/Expression.h"  // for Expression
     
    4248        }
    4349
    44         class ResolveTypeof : public WithShortCircuiting {
     50        class ResolveTypeof_old : public WithShortCircuiting {
    4551          public:
    46                 ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
     52                ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    4753                void premutate( TypeofType *typeofType );
    4854                Type * postmutate( TypeofType *typeofType );
     
    5359
    5460        Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    55                 PassVisitor<ResolveTypeof> mutator( indexer );
     61                PassVisitor<ResolveTypeof_old> mutator( indexer );
    5662                return type->acceptMutator( mutator );
    5763        }
    5864
    59         void ResolveTypeof::premutate( TypeofType * ) {
     65        void ResolveTypeof_old::premutate( TypeofType * ) {
    6066                visit_children = false;
    6167        }
    6268
    63         Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
     69        Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
    6470#if 0
    6571                std::cerr << "resolving typeof: ";
     
    108114        }
    109115
    110         const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
    111                 #warning unimplemented
    112                 (void)type; (void)symtab;
    113                 assert(false);
    114                 return nullptr;
    115         }
     116namespace {
     117        struct ResolveTypeof_new : public ast::WithShortCircuiting {
     118                const ast::SymbolTable & localSymtab;
     119
     120                ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
     121
     122                void premutate( const ast::TypeofType * ) { visit_children = false; }
     123
     124                const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
     125                        // pass on null expression
     126                        if ( ! typeofType->expr ) return typeofType;
     127
     128                        ast::ptr< ast::Type > newType;
     129                        if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
     130                                // typeof wrapping type
     131                                newType = tyExpr->type;
     132                        } else {
     133                                // typeof wrapping expression
     134                                ast::TypeEnvironment dummy;
     135                                ast::ptr< ast::Expr > newExpr =
     136                                        resolveInVoidContext( typeofType->expr, localSymtab, dummy );
     137                                assert( newExpr->result && ! newExpr->result->isVoid() );
     138                                newType = newExpr->result;
     139                        }
     140
     141                        // clear qualifiers for base, combine with typeoftype quals regardless
     142                        if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
     143                                // replace basetypeof(<enum>) by int
     144                                if ( newType.as< ast::EnumInstType >() ) {
     145                                        newType = new ast::BasicType{
     146                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
     147                                }
     148                                reset_qualifiers(
     149                                        newType,
     150                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
     151                        } else {
     152                                add_qualifiers( newType, typeofType->qualifiers );
     153                        }
     154
     155                        return newType;
     156                }
     157        };
     158} // anonymous namespace
     159
     160const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
     161        ast::Pass< ResolveTypeof_new > mutator{ symtab };
     162        return type->accept( mutator );
     163}
     164
    116165} // namespace ResolvExpr
    117166
  • src/ResolvExpr/Resolver.cc

    r3623f9d r3e2f5e3  
    12261226                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
    12271227
    1228                 void previsit( const ast::ArrayType * );
    1229                 void previsit( const ast::PointerType * );
     1228                const ast::ArrayType * previsit( const ast::ArrayType * );
     1229                const ast::PointerType * previsit( const ast::PointerType * );
    12301230
    12311231                const ast::ExprStmt *        previsit( const ast::ExprStmt * );
     
    13341334
    13351335        template< typename PtrType >
    1336         void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
    1337                 #warning unimplemented; needs support for new Validate::SizeType global
    1338                 (void)type; (void)symtab;
    1339                 assert( false );
    1340         }
    1341 
    1342         void Resolver_new::previsit( const ast::ArrayType * at ) {
    1343                 handlePtrType( at, symtab );
    1344         }
    1345 
    1346         void Resolver_new::previsit( const ast::PointerType * pt ) {
    1347                 handlePtrType( pt, symtab );
     1336        const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
     1337                if ( type->dimension ) {
     1338                        #warning should use new equivalent to Validate::SizeType rather than sizeType here
     1339                        ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };
     1340                        ast::mutate_field(
     1341                                type, &PtrType::dimension,
     1342                                findSingleExpression( type->dimension, sizeType, symtab ) );
     1343                }
     1344                return type;
     1345        }
     1346
     1347        const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
     1348                return handlePtrType( at, symtab );
     1349        }
     1350
     1351        const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
     1352                return handlePtrType( pt, symtab );
    13481353        }
    13491354
  • src/ResolvExpr/typeops.h

    r3623f9d r3e2f5e3  
    9999        // in PtrsCastable.cc
    100100        int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     101        int ptrsCastable(
     102                const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     103                const ast::TypeEnvironment & env );
    101104
    102105        // in Unify.cc
Note: See TracChangeset for help on using the changeset viewer.