Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Virtual/ExpandCasts.cc

    rf19fbbc rc19bc90  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jul 22 10:04:00 2020
    13 // Update Count     : 3
     12// Last Modified On : Tue May 26 14:37:00 2020
     13// Update Count     : 2
    1414//
    1515
     
    2424#include "Common/PassVisitor.h"    // for PassVisitor
    2525#include "Common/SemanticError.h"  // for SemanticError
    26 #include "SymTab/Mangler.h"        // for mangleType
    2726#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2827#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3332namespace Virtual {
    3433
    35         // Indented until the new ast code gets added.
    36 
    37         /// Maps virtual table types the instance for that type.
    38         class VirtualTableMap final {
    39                 std::unordered_map<std::string, ObjectDecl *> vtable_instances;
    40         public:
    41                 ObjectDecl * insert( ObjectDecl * vtableDecl ) {
    42                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
    43                         ObjectDecl *& value = vtable_instances[ mangledName ];
    44                         if ( value ) {
    45                                 if ( vtableDecl->storageClasses.is_extern ) {
    46                                         return nullptr;
    47                                 } else if ( ! value->storageClasses.is_extern ) {
    48                                         return value;
    49                                 }
    50                         }
    51                         value = vtableDecl;
    52                         return nullptr;
    53                 }
    54 
    55                 ObjectDecl * lookup( const Type * vtableType ) {
    56                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
    57                         const auto it = vtable_instances.find( mangledName );
    58                         return ( vtable_instances.end() == it ) ? nullptr : it->second;
    59                 }
    60         };
    61 
    6234        /* Currently virtual depends on the rather brittle name matching between
    6335         * a (strict/explicate) virtual type, its vtable type and the vtable
     
    6638         * and use that information to create better error messages.
    6739         */
    68 
    69         namespace {
    7040
    7141        std::string get_vtable_name( std::string const & name ) {
     
    8555        }
    8656
     57        bool is_vtable_name( std::string const & name ) {
     58                return (name.substr( name.size() - 7 ) == "_vtable" );
     59        }
     60
    8761        bool is_vtable_inst_name( std::string const & name ) {
    8862                return 17 < name.size() &&
     
    9064        }
    9165
    92         } // namespace
    93 
    9466        class VirtualCastCore {
    95                 VirtualTableMap vtable_instances;
    96                 FunctionDecl *vcast_decl;
    97                 StructDecl *pvt_decl;
     67        std::map<std::string, ObjectDecl *> vtable_instances;
     68        FunctionDecl *vcast_decl;
     69        StructDecl *pvt_decl;
    9870
    9971                Type * pointer_to_pvt(int level_of_indirection) {
     
    135107        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    136108                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    137                         if ( ObjectDecl * existing = vtable_instances.insert( objectDecl ) ) {
    138                                 std::string msg = "Repeated instance of virtual table, original found at: ";
    139                                 msg += existing->location.filename;
    140                                 msg += ":" + toString( existing->location.first_line );
    141                                 SemanticError( objectDecl->location, msg );
    142                         }
     109                        vtable_instances[objectDecl->get_name()] = objectDecl;
    143110                }
    144111        }
    145112
    146         namespace {
    147 
    148         /// Better error locations for generated casts.
    149         CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
     113        // Better error locations for generated casts.
     114        static CodeLocation castLocation( VirtualCastExpr * castExpr ) {
    150115                if ( castExpr->location.isSet() ) {
    151116                        return castExpr->location;
     
    159124        }
    160125
    161         [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
    162                 SemanticError( castLocation( castExpr ), message );
    163         }
    164 
    165         /// Get the virtual table type used in a virtual cast.
    166         Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
    167                 const Type * objectType;
    168                 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
    169                         objectType = target->base;
    170                 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
    171                         objectType = target->base;
    172                 } else {
    173                         castError( castExpr, "Virtual cast type must be a pointer or reference type." );
    174                 }
    175                 assert( objectType );
    176 
    177                 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
    178                 if ( nullptr == structType ) {
    179                         castError( castExpr, "Virtual cast type must refer to a structure type." );
    180                 }
    181                 const StructDecl * structDecl = structType->baseStruct;
    182                 assert( structDecl );
    183 
    184                 const ObjectDecl * fieldDecl = nullptr;
    185                 if ( 0 < structDecl->members.size() ) {
    186                         const Declaration * memberDecl = structDecl->members.front();
    187                         assert( memberDecl );
    188                         fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    189                         if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
    190                                 fieldDecl = nullptr;
    191                         }
    192                 }
    193                 if ( nullptr == fieldDecl ) {
    194                         castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
    195                 }
    196                 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
    197                 if ( nullptr == fieldType ) {
    198                         castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
    199                 }
    200                 assert( fieldType->base );
    201                 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
    202                 assert( virtualStructType );
    203 
    204                 // Here is the type, but if it is polymorphic it will have lost information.
    205                 // (Always a clone so that it may always be deleted.)
    206                 StructInstType * virtualType = virtualStructType->clone();
    207                 if ( ! structType->parameters.empty() ) {
    208                         deleteAll( virtualType->parameters );
    209                         virtualType->parameters.clear();
    210                         cloneAll( structType->parameters, virtualType->parameters );
    211                 }
    212                 return virtualType;
    213         }
    214 
    215         } // namespace
    216 
    217126        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    218                 assertf( castExpr->result, "Virtual Cast target not found before expansion." );
     127                assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
    219128
    220129                assert( vcast_decl );
    221130                assert( pvt_decl );
    222131
    223                 const Type * vtable_type = getVirtualTableType( castExpr );
    224                 ObjectDecl * table = vtable_instances.lookup( vtable_type );
    225                 if ( nullptr == table ) {
     132                // Get the base type of the pointer/reference.
     133                Type * base;
     134                Type * result_type = castExpr->result;
     135                if ( PointerType * target = dynamic_cast<PointerType *>( result_type ) ) {
     136                        base = target->base;
     137                } else if ( ReferenceType * target = dynamic_cast<ReferenceType *>( result_type ) ) {
     138                        base = target->base;
     139                } else {
    226140                        SemanticError( castLocation( castExpr ),
    227                                 "Could not find virtual table instance." );
     141                                "Virtual cast type must be a pointer or reference type." );
    228142                }
     143
     144                StructInstType * target_struct = dynamic_cast<StructInstType *>( base );
     145                if ( nullptr == target_struct ) {
     146                        SemanticError( castLocation( castExpr ),
     147                                "Virtual cast type must refer to a structure type." );
     148                }
     149                StructDecl * target_decl = target_struct->get_baseStruct();
     150
     151                std::map<std::string, ObjectDecl *>::iterator found =
     152                        vtable_instances.find( get_vtable_inst_name( target_decl->get_name() ) );
     153                if ( vtable_instances.end() == found ) {
     154                        SemanticError( castLocation( castExpr ),
     155                                "Virtual cast type does not have a virtual table instance." );
     156                }
     157                ObjectDecl * table = found->second;
    229158
    230159                Expression * result = new CastExpr(
     
    245174                castExpr->set_result( nullptr );
    246175                delete castExpr;
    247                 delete vtable_type;
    248176                return result;
    249177        }
Note: See TracChangeset for help on using the changeset viewer.