Changeset 6b224a52 for src/ResolvExpr/CommonType.cc
- Timestamp:
- Aug 25, 2017, 12:11:53 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- bf7b9da7
- Parents:
- 135b431 (diff), f676b84 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CommonType.cc
r135b431 r6b224a52 26 26 #include "typeops.h" // for isFtype 27 27 28 29 /// #define DEBUG 28 // #define DEBUG 30 29 31 30 namespace ResolvExpr { … … 39 38 virtual void visit( PointerType *pointerType ); 40 39 virtual void visit( ArrayType *arrayType ); 40 virtual void visit( ReferenceType *refType ); 41 41 virtual void visit( FunctionType *functionType ); 42 42 virtual void visit( StructInstType *aggregateUseType ); … … 50 50 virtual void visit( OneType *oneType ); 51 51 52 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ); 52 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 53 54 54 55 Type *result; … … 60 61 }; 61 62 63 Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) { 64 Type * result = nullptr, * common = nullptr; 65 AssertionSet have, need; 66 OpenVarSet newOpen( openVars ); 67 // need unify to bind type variables 68 if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) { 69 // std::cerr << "unify success" << std::endl; 70 if ( widenSecond ) { 71 // std::cerr << "widen second" << std::endl; 72 if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) { 73 result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone(); 74 result->get_qualifiers() |= other->get_qualifiers(); 75 } 76 } else if ( widenFirst ) { 77 // std::cerr << "widen first" << std::endl; 78 if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) { 79 result = common; 80 result->get_qualifiers() |= refType->get_qualifiers(); 81 } 82 } 83 } else { 84 // std::cerr << "exact unify failed: " << refType << " " << other << std::endl; 85 } 86 // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl; 87 return result; 88 } 89 62 90 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 63 91 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 92 93 int depth1 = type1->referenceDepth(); 94 int depth2 = type2->referenceDepth(); 95 if ( depth1 > 0 || depth2 > 0 ) { 96 int diff = depth1-depth2; 97 // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed. 98 if ( diff > 1 || diff < -1 ) return nullptr; 99 100 // special case where one type has a reference depth of 1 larger than the other 101 if ( diff > 0 ) { 102 return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars ); 103 } else if ( diff < 0 ) { 104 return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars ); 105 } 106 // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor. 107 } 108 64 109 type1->accept( visitor ); 65 110 Type *result = visitor.get_result(); … … 88 133 } // if 89 134 #ifdef DEBUG 90 std::c out<< "============= commonType" << std::endl << "type1 is ";91 type1->print( std::c out);92 std::c out<< " type2 is ";93 type2->print( std::c out);135 std::cerr << "============= commonType" << std::endl << "type1 is "; 136 type1->print( std::cerr ); 137 std::cerr << " type2 is "; 138 type2->print( std::cerr ); 94 139 if ( result ) { 95 std::c out<< " common type is ";96 result->print( std::c out);140 std::cerr << " common type is "; 141 result->print( std::cerr ); 97 142 } else { 98 std::c out<< " no common type";99 } // if 100 std::c out<< std::endl;143 std::cerr << " no common type"; 144 } // if 145 std::cerr << std::endl; 101 146 #endif 102 147 return result; … … 150 195 } 151 196 152 void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) { 197 template< typename Pointer > 198 void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 153 199 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 154 200 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 165 211 void CommonType::visit( PointerType *pointerType ) { 166 212 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 213 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; 167 214 if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) { 168 215 getCommonWithVoidPointer( otherPointer, pointerType ); … … 171 218 } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst ) 172 219 && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) { 220 // std::cerr << "middle case" << std::endl; 173 221 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers(); 174 222 pointerType->get_base()->get_qualifiers() = Type::Qualifiers(); … … 177 225 OpenVarSet newOpen( openVars ); 178 226 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) { 227 // std::cerr << "unifyExact success" << std::endl; 179 228 if ( tq1 < tq2 ) { 180 229 result = pointerType->clone(); … … 184 233 result->get_qualifiers() = tq1 | tq2; 185 234 } else { 186 /// std::c out<< "place for ptr-to-type" << std::endl;235 /// std::cerr << "place for ptr-to-type" << std::endl; 187 236 } // if 188 237 pointerType->get_base()->get_qualifiers() = tq1; … … 196 245 197 246 void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {} 247 248 void CommonType::visit( ReferenceType *refType ) { 249 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 250 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; 251 // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl; 252 if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) { 253 getCommonWithVoidPointer( otherRef, refType ); 254 } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) { 255 getCommonWithVoidPointer( refType, otherRef ); 256 } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) 257 && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) { 258 // std::cerr << "middle case" << std::endl; 259 Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers(); 260 refType->get_base()->get_qualifiers() = Type::Qualifiers(); 261 otherRef->get_base()->get_qualifiers() = Type::Qualifiers(); 262 AssertionSet have, need; 263 OpenVarSet newOpen( openVars ); 264 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) { 265 if ( tq1 < tq2 ) { 266 result = refType->clone(); 267 } else { 268 result = otherRef->clone(); 269 } // if 270 result->get_qualifiers() = tq1 | tq2; 271 } else { 272 /// std::cerr << "place for ptr-to-type" << std::endl; 273 } // if 274 refType->get_base()->get_qualifiers() = tq1; 275 otherRef->get_base()->get_qualifiers() = tq2; 276 } // if 277 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) { 278 result = refType->clone(); 279 result->get_qualifiers() |= type2->get_qualifiers(); 280 } // if 281 } 282 198 283 void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {} 199 284 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {} … … 203 288 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 204 289 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 205 Type * temp = type2;290 ValueGuard< Type * > temp( type2 ); 206 291 type2 = enumInstType; 207 temp->accept( *this ); 208 type2 = temp; 292 temp.old->accept( *this ); 209 293 } // if 210 294 }
Note:
See TracChangeset
for help on using the changeset viewer.