Changeset 79970ed


Ignore:
Timestamp:
Aug 24, 2016, 12:36:33 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, 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:
0555f4b
Parents:
f87408e
Message:

implement warnings for missing struct member constructor calls, remove bad clones

Location:
src
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/GenType.h

    rf87408e r79970ed  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // GenType.h -- 
     7// GenType.h --
    88//
    99// Author           : Richard C. Bilson
  • src/Common/utility.h

    rf87408e r79970ed  
    144144
    145145template < typename T >
    146 std::string toString ( T value ) {
     146void toString_single ( std::ostream & os, const T & value ) {
     147        os << value;
     148}
     149
     150template < typename T, typename... Params >
     151void toString_single ( std::ostream & os, const T & value, const Params & ... params ) {
     152        os << value;
     153        toString_single( os, params ... );
     154}
     155
     156template < typename ... Params >
     157std::string toString ( const Params & ... params ) {
    147158        std::ostringstream os;
    148         os << value; // << std::ends;
     159        toString_single( os, params... );
    149160        return os.str();
    150161}
     
    218229}
    219230
     231template< typename T >
     232void warn_single( const T & arg ) {
     233        std::cerr << arg << std::endl;
     234}
     235
     236template< typename T, typename... Params >
     237void warn_single(const T & arg, const Params & ... params ) {
     238        std::cerr << arg;
     239        warn_single( params... );
     240}
     241
     242template< typename... Params >
     243void warn( const Params & ... params ) {
     244        std::cerr << "Warning: ";
     245        warn_single( params... );
     246}
     247
    220248#endif // _UTILITY_H
    221249
  • src/InitTweak/FixInit.cc

    rf87408e r79970ed  
    3333#include "GenPoly/PolyMutator.h"
    3434#include "SynTree/AddStmtVisitor.h"
     35#include "CodeGen/GenType.h"  // for warnings
    3536
    3637bool ctordtorp = false;
     
    174175                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    175176                };
     177
     178                class WarnStructMembers : public Visitor {
     179                  public:
     180                        typedef Visitor Parent;
     181                        /// warn if a user-defined constructor or destructor is missing calls for
     182                        /// a struct member or if a member is used before constructed
     183                        static void warnings( std::list< Declaration * > & translationUnit );
     184
     185                        virtual void visit( FunctionDecl * funcDecl );
     186
     187                        virtual void visit( MemberExpr * memberExpr );
     188                        virtual void visit( ApplicationExpr * appExpr );
     189
     190                  private:
     191                        void handleFirstParam( Expression * firstParam );
     192
     193                        FunctionDecl * function = 0;
     194                        std::set< DeclarationWithType * > unhandled;
     195                        ObjectDecl * thisParam = 0;
     196                };
    176197        } // namespace
    177198
     
    187208                // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
    188209                FixCopyCtors::fixCopyCtors( translationUnit );
     210
     211                WarnStructMembers::warnings( translationUnit );
    189212        }
    190213
     
    231254                }
    232255
     256                void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {
     257                        if ( true ) { // fix this condition to skip this pass if warnings aren't enabled
     258                                WarnStructMembers warner;
     259                                acceptAll( translationUnit, warner );
     260                        }
     261                }
     262
    233263                Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
    234264                        appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) );
     
    242272                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    243273                                        assert( ftype );
    244                                         if ( (funcDecl->get_name() == "?{}" || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {
     274                                        if ( (isConstructor( funcDecl->get_name() ) || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {
    245275                                                Type * t1 = ftype->get_parameters().front()->get_type();
    246276                                                Type * t2 = ftype->get_parameters().back()->get_type();
     
    253283                                                        return appExpr;
    254284                                                } // if
    255                                         } else if ( funcDecl->get_name() == "^?{}" ) {
     285                                        } else if ( isDestructor( funcDecl->get_name() ) ) {
    256286                                                // correctness: never copy construct arguments to a destructor
    257287                                                return appExpr;
     
    670700                        } // switch
    671701                }
     702
     703                bool checkWarnings( FunctionDecl * funcDecl ) {
     704                        // only check for warnings if the current function is a user-defined
     705                        // constructor or destructor
     706                        if ( ! funcDecl ) return false;
     707                        if ( ! funcDecl->get_statements() ) return false;
     708                        return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     709                }
     710
     711                void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
     712                        WarnStructMembers old = *this;
     713                        *this = WarnStructMembers();
     714
     715                        function = funcDecl;
     716                        if ( checkWarnings( funcDecl ) ) {
     717                                FunctionType * type = funcDecl->get_functionType();
     718                                assert( ! type->get_parameters().empty() );
     719                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
     720                                PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
     721                                StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
     722                                if ( structType ) {
     723                                        StructDecl * structDecl = structType->get_baseStruct();
     724                                        for ( Declaration * member : structDecl->get_members() ) {
     725                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     726                                                        // record all of the struct type's members that need to be constructed or
     727                                                        // destructed by the end of the function
     728                                                        unhandled.insert( field );
     729                                                }
     730                                        }
     731                                }
     732                        }
     733                        Parent::visit( funcDecl );
     734
     735                        for ( DeclarationWithType * member : unhandled ) {
     736                                // emit a warning for each unhandled member
     737                                warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name() ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" );
     738                        }
     739
     740                        *this = old;
     741                }
     742
     743                void WarnStructMembers::visit( ApplicationExpr * appExpr ) {
     744                        if ( ! checkWarnings( function ) ) return;
     745
     746                        std::string fname = getFunctionName( appExpr );
     747                        if ( fname == function->get_name() ) {
     748                                // call to same kind of function
     749                                Expression * firstParam = appExpr->get_args().front();
     750
     751                                if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
     752                                        // if calling another constructor on thisParam, assume that function handles
     753                                        // all members - if it doesn't a warning will appear in that function.
     754                                        if ( varExpr->get_var() == thisParam ) {
     755                                                unhandled.clear();
     756                                        }
     757                                } else {
     758                                        // if first parameter is a member expression then
     759                                        // remove the member from unhandled set.
     760                                        handleFirstParam( firstParam );
     761                                }
     762                        } else if ( fname == "?=?" && isIntrinsicCallExpr( appExpr ) ) {
     763                                // forgive use of intrinsic assignment to construct, since instrinsic constructors
     764                                // codegen as assignment anyway.
     765                                assert( appExpr->get_args().size() == 2 );
     766                                handleFirstParam( appExpr->get_args().front() );
     767                        }
     768
     769                        Parent::visit( appExpr );
     770                }
     771
     772                void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
     773                        using namespace std;
     774                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     775                                if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) {
     776                                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     777                                                if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
     778                                                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
     779                                                                if ( varExpr->get_var() == thisParam ) {
     780                                                                        unhandled.erase( memberExpr->get_member() );
     781                                                                }
     782                                                        }
     783                                                }
     784                                        }
     785                                }
     786                        }
     787                }
     788
     789                void WarnStructMembers::visit( MemberExpr * memberExpr ) {
     790                        if ( ! checkWarnings( function ) ) return;
     791                        if ( ! isConstructor( function->get_name() ) );
     792
     793                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     794                                if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
     795                                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
     796                                                if ( varExpr->get_var() == thisParam ) {
     797                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
     798                                                                // emit a warning because a member was used before it was constructed
     799                                                                warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name() ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
     800                                                        }
     801                                                }
     802                                        }
     803                                }
     804                        }
     805                        Parent::visit( memberExpr );
     806                }
    672807        } // namespace
    673808} // namespace InitTweak
  • src/InitTweak/InitTweak.cc

    rf87408e r79970ed  
    433433        }
    434434
     435        bool isConstructor( const std::string & str ) { return str == "?{}"; }
     436        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
     437        bool isCtorDtor( const std::string & str ) { return isConstructor( str ) || isDestructor( str ); }
    435438}
  • src/InitTweak/InitTweak.h

    rf87408e r79970ed  
    2626// helper functions for initialization
    2727namespace InitTweak {
     28        bool isConstructor( const std::string & );
     29        bool isDestructor( const std::string & );
     30        bool isCtorDtor( const std::string & );
     31
    2832        /// transform Initializer into an argument list that can be passed to a call expression
    2933        std::list< Expression * > makeInitList( Initializer * init );
  • src/Parser/LinkageSpec.cc

    rf87408e r79970ed  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // LinkageSpec.cc -- 
    8 // 
     7// LinkageSpec.cc --
     8//
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:22:09 2015
     
    1212// Last Modified On : Sun Aug 21 12:32:53 2016
    1313// Update Count     : 17
    14 // 
     14//
    1515
    1616#include <string>
     
    3232
    3333std::string LinkageSpec::toString( LinkageSpec::Spec linkage ) {
     34        assert( linkage >= 0 && linkage < LinkageSpec::NoOfSpecs );
    3435        static const char *linkageKinds[LinkageSpec::NoOfSpecs] = {
    3536                "intrinsic", "Cforall", "C", "automatically generated", "compiler built-in",
     
    3940
    4041bool LinkageSpec::isDecoratable( Spec spec ) {
     42        assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs );
    4143        static bool decoratable[LinkageSpec::NoOfSpecs] = {
    4244                //      Intrinsic,      Cforall,        C,              AutoGen,        Compiler
    43                         true,           true,           false,  true,           false, 
     45                        true,           true,           false,  true,           false,
    4446        };
    4547        return decoratable[spec];
     
    4749
    4850bool LinkageSpec::isGeneratable( Spec spec ) {
     51        assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs );
    4952        static bool generatable[LinkageSpec::NoOfSpecs] = {
    5053                //      Intrinsic,      Cforall,        C,              AutoGen,        Compiler
    51                         true,           true,           true,   true,           false, 
     54                        true,           true,           true,   true,           false,
    5255        };
    5356        return generatable[spec];
     
    5558
    5659bool LinkageSpec::isOverridable( Spec spec ) {
     60        assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs );
    5761        static bool overridable[LinkageSpec::NoOfSpecs] = {
    5862                //      Intrinsic,      Cforall,        C,              AutoGen,        Compiler
    59                         true,           false,          false,  true,           false, 
     63                        true,           false,          false,  true,           false,
    6064        };
    6165        return overridable[spec];
     
    6367
    6468bool LinkageSpec::isBuiltin( Spec spec ) {
     69        assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs );
    6570        static bool builtin[LinkageSpec::NoOfSpecs] = {
    6671                //      Intrinsic,      Cforall,        C,              AutoGen,        Compiler
    67                         true,           false,          false,  false,          true, 
     72                        true,           false,          false,  false,          true,
    6873        };
    6974        return builtin[spec];
  • src/ResolvExpr/AlternativeFinder.cc

    rf87408e r79970ed  
    244244                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    245245                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    246                                 alternatives.push_back( Alternative( new MemberExpr( dwt->clone(), expr->clone() ), env, newCost ) );
     246                                alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
    247247                                renameTypes( alternatives.back().expr );
    248248                        } else {
     
    418418        // /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included
    419419        //typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;
    420        
     420
    421421        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    422422        //static const unsigned recursionParentLimit = 1;  ///< Limit to the number of times an assertion can recursively use itself
     
    429429                }
    430430        }
    431        
     431
    432432        template< typename ForwardIterator, typename OutputIterator >
    433         void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/ 
     433        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/
    434434                                                 int level, const SymTab::Indexer &indexer, OutputIterator out ) {
    435435                if ( begin == end ) {
     
    469469                                std::cerr << std::endl;
    470470                        )
    471                        
     471
    472472                        AssertionSet newHave, newerNeed( newNeed );
    473473                        TypeEnvironment newEnv( newAlt.env );
     
    847847                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    848848                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    849                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt->clone() ), env, Cost::zero ) );
     849                                alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
    850850                                renameTypes( alternatives.back().expr );
    851851                        } else {
  • src/SymTab/Validate.cc

    rf87408e r79970ed  
    5858#include "Autogen.h"
    5959#include "ResolvExpr/typeops.h"
     60#include <algorithm>
    6061
    6162#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
     
    372373                } // if
    373374
    374                 applySubstitution( ctx->get_parameters().begin(), ctx->get_parameters().end(), contextInst->get_parameters().begin(), ctx->get_members().begin(), ctx->get_members().end(), back_inserter( contextInst->get_members() ) );
     375                // need to clone members of the context for ownership purposes
     376                std::list< Declaration * > members;
     377                std::transform( ctx->get_members().begin(), ctx->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
     378
     379                applySubstitution( ctx->get_parameters().begin(), ctx->get_parameters().end(), contextInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( contextInst->get_members() ) );
    375380        }
    376381
  • src/SynTree/AggregateDecl.cc

    rf87408e r79970ed  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AggregateDecl.cc -- 
     7// AggregateDecl.cc --
    88//
    99// Author           : Richard C. Bilson
  • src/SynTree/Expression.cc

    rf87408e r79970ed  
    200200
    201201OffsetofExpr::OffsetofExpr( const OffsetofExpr &other ) :
    202         Expression( other ), type( maybeClone( other.type ) ), member( maybeClone( other.member ) ) {}
     202        Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
    203203
    204204OffsetofExpr::~OffsetofExpr() {
    205205        delete type;
    206         delete member;
    207206}
    208207
     
    359358        assert( member );
    360359        os << std::string( indent + 2, ' ' );
     360        os << (void*)member << " ";
    361361        member->print( os, indent + 2 );
    362362        os << std::endl;
  • src/SynTree/TypeSubstitution.h

    rf87408e r79970ed  
    169169        TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
    170170        for ( std::list< Declaration* >::iterator i = memberBegin; i != memberEnd; ++i ) {
    171                 Declaration *newdecl = (*i)->clone();
    172                 sub.apply( newdecl );
    173                 *out++ = newdecl;
     171                sub.apply( *i );
     172                *out++ = *i;
    174173        } // for
    175174}
Note: See TracChangeset for help on using the changeset viewer.