Changes in src/Virtual/ExpandCasts.cc [6dba8755:8e6214f]
- File:
-
- 1 edited
-
src/Virtual/ExpandCasts.cc (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
r6dba8755 r8e6214f 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 31 10:29:00 202013 // Update Count : 412 // Last Modified On : Tus Aug 2 14:59:00 2017 13 // Update Count : 1 14 14 // 15 15 … … 18 18 #include <cassert> // for assert, assertf 19 19 #include <iterator> // for back_inserter, inserter 20 #include <map> // for map, _Rb_tree_iterator, map<>::ite... 20 21 #include <string> // for string, allocator, operator==, ope... 22 #include <utility> // for pair 21 23 22 24 #include "Common/PassVisitor.h" // for PassVisitor 23 #include "Common/ScopedMap.h" // for ScopedMap24 25 #include "Common/SemanticError.h" // for SemanticError 25 #include "SymTab/Mangler.h" // for mangleType26 26 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 27 27 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... … … 32 32 namespace Virtual { 33 33 34 // Indented until the new ast code gets added.35 36 /// Maps virtual table types the instance for that type.37 class VirtualTableMap final {38 ScopedMap<std::string, ObjectDecl *> vtable_instances;39 public:40 void enterScope() {41 vtable_instances.beginScope();42 }43 void leaveScope() {44 vtable_instances.endScope();45 }46 47 ObjectDecl * insert( ObjectDecl * vtableDecl ) {48 std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );49 ObjectDecl *& value = vtable_instances[ mangledName ];50 if ( value ) {51 if ( vtableDecl->storageClasses.is_extern ) {52 return nullptr;53 } else if ( ! value->storageClasses.is_extern ) {54 return value;55 }56 }57 value = vtableDecl;58 return nullptr;59 }60 61 ObjectDecl * lookup( const Type * vtableType ) {62 std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );63 const auto it = vtable_instances.find( mangledName );64 return ( vtable_instances.end() == it ) ? nullptr : it->second;65 }66 };67 68 34 /* Currently virtual depends on the rather brittle name matching between 69 35 * a (strict/explicate) virtual type, its vtable type and the vtable … … 72 38 * and use that information to create better error messages. 73 39 */ 74 75 namespace {76 40 77 41 std::string get_vtable_name( std::string const & name ) { … … 91 55 } 92 56 57 bool is_vtable_name( std::string const & name ) { 58 return (name.substr( name.size() - 7 ) == "_vtable" ); 59 } 60 93 61 bool is_vtable_inst_name( std::string const & name ) { 94 62 return 17 < name.size() && … … 96 64 } 97 65 98 } // namespace 66 class VirtualCastCore { 67 std::map<std::string, ObjectDecl *> vtable_instances; 68 FunctionDecl *vcast_decl; 69 StructDecl *pvt_decl; 99 70 100 class VirtualCastCore {101 71 Type * pointer_to_pvt(int level_of_indirection) { 102 72 Type * type = new StructInstType( … … 110 80 public: 111 81 VirtualCastCore() : 112 indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )82 vtable_instances(), vcast_decl( nullptr ), pvt_decl( nullptr ) 113 83 {} 114 84 … … 118 88 119 89 Expression * postmutate( VirtualCastExpr * castExpr ); 120 121 VirtualTableMap indexer;122 private:123 FunctionDecl *vcast_decl;124 StructDecl *pvt_decl;125 90 }; 126 91 … … 142 107 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 143 108 if ( is_vtable_inst_name( objectDecl->get_name() ) ) { 144 if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) { 145 std::string msg = "Repeated instance of virtual table, original found at: "; 146 msg += existing->location.filename; 147 msg += ":" + toString( existing->location.first_line ); 148 SemanticError( objectDecl->location, msg ); 149 } 109 vtable_instances[objectDecl->get_name()] = objectDecl; 150 110 } 151 111 } 152 112 153 namespace {154 155 /// Better error locations for generated casts.156 CodeLocation castLocation( const VirtualCastExpr * castExpr ) {157 if ( castExpr->location.isSet() ) {158 return castExpr->location;159 } else if ( castExpr->arg->location.isSet() ) {160 return castExpr->arg->location;161 } else if ( castExpr->result->location.isSet() ) {162 return castExpr->result->location;163 } else {164 return CodeLocation();165 }166 }167 168 [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {169 SemanticError( castLocation( castExpr ), message );170 }171 172 /// Get the virtual table type used in a virtual cast.173 Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {174 const Type * objectType;175 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {176 objectType = target->base;177 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {178 objectType = target->base;179 } else {180 castError( castExpr, "Virtual cast type must be a pointer or reference type." );181 }182 assert( objectType );183 184 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );185 if ( nullptr == structType ) {186 castError( castExpr, "Virtual cast type must refer to a structure type." );187 }188 const StructDecl * structDecl = structType->baseStruct;189 assert( structDecl );190 191 const ObjectDecl * fieldDecl = nullptr;192 if ( 0 < structDecl->members.size() ) {193 const Declaration * memberDecl = structDecl->members.front();194 assert( memberDecl );195 fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );196 if ( fieldDecl && fieldDecl->name != "virtual_table" ) {197 fieldDecl = nullptr;198 }199 }200 if ( nullptr == fieldDecl ) {201 castError( castExpr, "Virtual cast type must have a leading virtual_table field." );202 }203 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );204 if ( nullptr == fieldType ) {205 castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );206 }207 assert( fieldType->base );208 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );209 assert( virtualStructType );210 211 // Here is the type, but if it is polymorphic it will have lost information.212 // (Always a clone so that it may always be deleted.)213 StructInstType * virtualType = virtualStructType->clone();214 if ( ! structType->parameters.empty() ) {215 deleteAll( virtualType->parameters );216 virtualType->parameters.clear();217 cloneAll( structType->parameters, virtualType->parameters );218 }219 return virtualType;220 }221 222 } // namespace223 224 113 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 225 assertf( castExpr-> result, "Virtual Cast target not found before expansion." );114 assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." ); 226 115 227 116 assert( vcast_decl ); 228 117 assert( pvt_decl ); 229 118 230 const Type * vtable_type = getVirtualTableType( castExpr ); 231 ObjectDecl * table = indexer.lookup( vtable_type ); 232 if ( nullptr == table ) { 233 SemanticError( castLocation( castExpr ), 234 "Could not find virtual table instance." ); 119 // May only cast to a pointer or reference type. 120 // A earlier validation should give a syntax error, this is 121 // just to make sure errors don't creep during translation. 122 // Move to helper with more detailed error messages. 123 PointerType * target_type = 124 dynamic_cast<PointerType *>( castExpr->get_result() ); 125 assert( target_type ); 126 127 StructInstType * target_struct = 128 dynamic_cast<StructInstType *>( target_type->get_base() ); 129 assert( target_struct ); 130 131 StructDecl * target_decl = target_struct->get_baseStruct(); 132 133 std::map<std::string, ObjectDecl *>::iterator found = 134 vtable_instances.find( 135 get_vtable_inst_name( target_decl->get_name() ) ); 136 if ( vtable_instances.end() == found ) { 137 assertf( false, "virtual table instance not found." ); 235 138 } 139 ObjectDecl * table = found->second; 236 140 237 141 Expression * result = new CastExpr( 142 //new ApplicationExpr( 143 //new AddressExpr( new VariableExpr( vcast_decl ) ), 144 //new CastExpr( new VariableExpr( vcast_decl ), 145 // new PointerType( noQualifiers, 146 // vcast_decl->get_type()->clone() 147 // ) 148 // ), 238 149 new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), { 239 150 new CastExpr( … … 252 163 castExpr->set_result( nullptr ); 253 164 delete castExpr; 254 delete vtable_type;255 165 return result; 256 166 }
Note:
See TracChangeset
for help on using the changeset viewer.