Changeset babeeda


Ignore:
Timestamp:
Mar 1, 2018, 2:48:18 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
a8a2b0a
Parents:
2103a51
Message:

Implement self assignment warning

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Common/SemanticError.h

    r2103a51 rbabeeda  
    3737
    3838constexpr const char * const WarningFormats[] = {
    39 
     39        "self assignment of expression: %s",
    4040};
    4141
    4242enum class Warning {
     43        SelfAssignment,
    4344        NUMBER_OF_WARNINGS, //This MUST be the last warning
    4445};
  • src/Common/utility.h

    r2103a51 rbabeeda  
    162162}
    163163
     164#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
     165
    164166// replace element of list with all elements of another list
    165167template< typename T >
  • src/InitTweak/FixInit.cc

    r2103a51 rbabeeda  
    6868                typedef std::unordered_map< int, int > UnqCount;
    6969
     70                struct SelfAssignChecker {
     71                        void previsit( ApplicationExpr * appExpr );
     72                };
     73
    7074                struct InsertImplicitCalls : public WithTypeSubstitution {
    7175                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     
    235239
    236240        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     241                PassVisitor<SelfAssignChecker> checker;
     242                acceptAll( translationUnit, checker );
     243
    237244                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    238245                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     
    309316                        PassVisitor<FixCtorExprs> fixer;
    310317                        mutateAll( translationUnit, fixer );
     318                }
     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                        }
    311395                }
    312396
Note: See TracChangeset for help on using the changeset viewer.