Changes in src/Virtual/ExpandCasts.cc [f19fbbc:c19bc90]
- File:
-
- 1 edited
-
src/Virtual/ExpandCasts.cc (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Virtual/ExpandCasts.cc
rf19fbbc rc19bc90 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Jul 22 10:04:00 202013 // Update Count : 312 // Last Modified On : Tue May 26 14:37:00 2020 13 // Update Count : 2 14 14 // 15 15 … … 24 24 #include "Common/PassVisitor.h" // for PassVisitor 25 25 #include "Common/SemanticError.h" // for SemanticError 26 #include "SymTab/Mangler.h" // for mangleType27 26 #include "SynTree/Declaration.h" // for ObjectDecl, StructDecl, FunctionDecl 28 27 #include "SynTree/Expression.h" // for VirtualCastExpr, CastExpr, Address... … … 33 32 namespace Virtual { 34 33 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 62 34 /* Currently virtual depends on the rather brittle name matching between 63 35 * a (strict/explicate) virtual type, its vtable type and the vtable … … 66 38 * and use that information to create better error messages. 67 39 */ 68 69 namespace {70 40 71 41 std::string get_vtable_name( std::string const & name ) { … … 85 55 } 86 56 57 bool is_vtable_name( std::string const & name ) { 58 return (name.substr( name.size() - 7 ) == "_vtable" ); 59 } 60 87 61 bool is_vtable_inst_name( std::string const & name ) { 88 62 return 17 < name.size() && … … 90 64 } 91 65 92 } // namespace93 94 66 class VirtualCastCore { 95 VirtualTableMapvtable_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; 98 70 99 71 Type * pointer_to_pvt(int level_of_indirection) { … … 135 107 void VirtualCastCore::premutate( ObjectDecl * objectDecl ) { 136 108 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; 143 110 } 144 111 } 145 112 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 ) { 150 115 if ( castExpr->location.isSet() ) { 151 116 return castExpr->location; … … 159 124 } 160 125 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 } // namespace216 217 126 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." ); 219 128 220 129 assert( vcast_decl ); 221 130 assert( pvt_decl ); 222 131 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 { 226 140 SemanticError( castLocation( castExpr ), 227 " Could not find virtual table instance." );141 "Virtual cast type must be a pointer or reference type." ); 228 142 } 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; 229 158 230 159 Expression * result = new CastExpr( … … 245 174 castExpr->set_result( nullptr ); 246 175 delete castExpr; 247 delete vtable_type;248 176 return result; 249 177 }
Note:
See TracChangeset
for help on using the changeset viewer.