Changeset caa649b for src/InitTweak
- Timestamp:
- Mar 6, 2018, 12:11:11 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:
- 520145b, e5d4e5c, e6c5e79
- Parents:
- 094476d (diff), 1feb535f (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
-
src/InitTweak/FixInit.cc (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r094476d rcaa649b 68 68 typedef std::unordered_map< int, int > UnqCount; 69 69 70 struct SelfAssignChecker { 71 void previsit( ApplicationExpr * appExpr ); 72 }; 73 70 74 struct InsertImplicitCalls : public WithTypeSubstitution { 71 75 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 183 187 }; 184 188 185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {189 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution { 186 190 public: 187 191 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 235 239 236 240 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 241 PassVisitor<SelfAssignChecker> checker; 242 acceptAll( translationUnit, checker ); 243 237 244 // fixes ConstructorInit for global variables. should happen before fixInitializers. 238 245 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); … … 311 318 } 312 319 320 namespace { 321 // Relatively simple structural comparison for expressions, needed to determine 322 // if two expressions are "the same" (used to determine if self assignment occurs) 323 struct StructuralChecker { 324 Expression * stripCasts( Expression * expr ) { 325 // this might be too permissive. It's possible that only particular casts are relevant. 326 while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) { 327 expr = cast->arg; 328 } 329 return expr; 330 } 331 332 void previsit( Expression * ) { 333 // anything else does not qualify 334 isSimilar = false; 335 } 336 337 template<typename T> 338 T * cast( Expression * node ) { 339 // all expressions need to ignore casts, so this bit has been factored out 340 return dynamic_cast< T * >( stripCasts( node ) ); 341 } 342 343 // ignore casts 344 void previsit( CastExpr * ) {} 345 346 void previsit( MemberExpr * memExpr ) { 347 if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) { 348 if ( otherMember->member == memExpr->member ) { 349 other = otherMember->aggregate; 350 return; 351 } 352 } 353 isSimilar = false; 354 } 355 356 void previsit( VariableExpr * varExpr ) { 357 if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) { 358 if ( otherVar->var == varExpr->var ) { 359 return; 360 } 361 } 362 isSimilar = false; 363 } 364 365 void previsit( AddressExpr * ) { 366 if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) { 367 other = addrExpr->arg; 368 return; 369 } 370 isSimilar = false; 371 } 372 373 Expression * other = nullptr; 374 bool isSimilar = true; 375 }; 376 377 bool structurallySimilar( Expression * e1, Expression * e2 ) { 378 PassVisitor<StructuralChecker> checker; 379 checker.pass.other = e2; 380 e1->accept( checker ); 381 return checker.pass.isSimilar; 382 } 383 } 384 385 void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) { 386 DeclarationWithType * function = getFunction( appExpr ); 387 if ( isAssignment( function ) ) { 388 if ( appExpr->args.size() == 2 ) { 389 // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits) 390 if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) { 391 SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) ); 392 } 393 } 394 } 395 } 396 313 397 Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) { 314 398 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { … … 364 448 ResolvExpr::findVoidExpression( resolved, indexer ); 365 449 assert( resolved ); 366 if ( resolved-> get_env()) {450 if ( resolved->env ) { 367 451 // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes. 368 env->add( *resolved-> get_env());369 delete resolved-> get_env();370 resolved-> set_env( nullptr );452 env->add( *resolved->env ); 453 delete resolved->env; 454 resolved->env = nullptr; 371 455 } // if 372 456 delete stmt; … … 550 634 // add destructors after current statement 551 635 for ( Expression * dtor : dtors ) { 636 // take relevant bindings from environment 637 assert( ! dtor->env ); 638 dtor->env = maybeClone( env ); 552 639 stmtsToAddAfter.push_back( new ExprStmt( dtor ) ); 553 640 } // for
Note:
See TracChangeset
for help on using the changeset viewer.