Changeset 64071c2


Ignore:
Timestamp:
Jun 6, 2016, 2:16:00 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
7baed7d
Parents:
321a2481
Message:

greatly simplify construction of qualified objects using cast expressions, which also reduces gcc warnings

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r321a2481 r64071c2  
    257257                                std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
    258258                                switch ( opInfo.type ) {
    259                                   case OT_CTOR:
    260                                   case OT_DTOR:
    261                                         {
    262                                                 // if the first argument's type is const then GCC complains. In this
    263                                                 // case, output an explicit ctor/dtor call and exit, rather than following
    264                                                 // the normal path
    265                                                 assert( arg != applicationExpr->get_args().end() );
    266                                                 assert( (*arg)->get_results().size() >= 1 );
    267                                                 Type * baseType = InitTweak::getPointerBase( (*arg)->get_results().front() );
    268                                                 if ( baseType->get_isConst() ) {
    269                                                         // cast away the qualifiers, to eliminate warnings
    270                                                         Type * newType = baseType->clone();
    271                                                         newType->get_qualifiers() = Type::Qualifiers();
    272                                                         *arg = new CastExpr( *arg, new PointerType( Type::Qualifiers(), newType ) );
    273                                                         varExpr->accept( *this );
    274                                                         output << "(";
    275                                                         genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
    276                                                         output << ")";
    277                                                         return;
    278                                                 }
    279                                         }
    280                                         // intentional fallthrough - instrinsic ctor/dtor for non-const objects should
    281                                         // be handled the same way as assignment
    282259                                  case OT_PREFIXASSIGN:
    283260                                  case OT_POSTFIXASSIGN:
    284261                                  case OT_INFIXASSIGN:
     262                                  case OT_CTOR:
     263                                  case OT_DTOR:
    285264                                        {
    286265                                                assert( arg != applicationExpr->get_args().end() );
     
    324303                                        if ( applicationExpr->get_args().size() == 1 ) {
    325304                                                // the expression fed into a single parameter constructor or destructor
    326                                                 // may contain side effects - output as a void expression
    327                                                 output << "((void)(";
     305                                                // may contain side effects, so must still output this expression
     306                                                output << "(";
    328307                                                (*arg++)->accept( *this );
    329                                                 output << ")) /* " << opInfo.inputName << " */";
     308                                                output << ") /* " << opInfo.inputName << " */";
    330309                                        } else if ( applicationExpr->get_args().size() == 2 ) {
    331310                                                // intrinsic two parameter constructors are essentially bitwise assignment
     
    409388                                        if ( untypedExpr->get_args().size() == 1 ) {
    410389                                                // the expression fed into a single parameter constructor or destructor
    411                                                 // may contain side effects - output as a void expression
    412                                                 output << "((void)(";
     390                                                // may contain side effects, so must still output this expression
     391                                                output << "(";
    413392                                                (*arg++)->accept( *this );
    414                                                 output << ")) /* " << opInfo.inputName << " */";
     393                                                output << ") /* " << opInfo.inputName << " */";
    415394                                        } else if ( untypedExpr->get_args().size() == 2 ) {
    416395                                                // intrinsic two parameter constructors are essentially bitwise assignment
  • src/InitTweak/InitTweak.cc

    r321a2481 r64071c2  
    77
    88namespace InitTweak {
    9   namespace {
    10     class HasDesignations : public Visitor {
    11     public:
    12       bool hasDesignations = false;
    13       template<typename Init>
    14       void handleInit( Init * init ) {
    15         if ( ! init->get_designators().empty() ) hasDesignations = true;
    16         else Visitor::visit( init );
    17       }
    18       virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
    19       virtual void visit( ListInit * listInit ) { handleInit( listInit); }
    20     };
     9        namespace {
     10                class HasDesignations : public Visitor {
     11                public:
     12                        bool hasDesignations = false;
     13                        template<typename Init>
     14                        void handleInit( Init * init ) {
     15                                if ( ! init->get_designators().empty() ) hasDesignations = true;
     16                                else Visitor::visit( init );
     17                        }
     18                        virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
     19                        virtual void visit( ListInit * listInit ) { handleInit( listInit); }
     20                };
    2121
    22     class InitExpander : public Visitor {
    23       public:
    24       InitExpander() {}
    25       virtual void visit( SingleInit * singleInit );
    26       virtual void visit( ListInit * listInit );
    27       std::list< Expression * > argList;
    28     };
     22                class InitExpander : public Visitor {
     23                        public:
     24                        InitExpander() {}
     25                        virtual void visit( SingleInit * singleInit );
     26                        virtual void visit( ListInit * listInit );
     27                        std::list< Expression * > argList;
     28                };
    2929
    30     void InitExpander::visit( SingleInit * singleInit ) {
    31       argList.push_back( singleInit->get_value()->clone() );
    32     }
     30                void InitExpander::visit( SingleInit * singleInit ) {
     31                        argList.push_back( singleInit->get_value()->clone() );
     32                }
    3333
    34     void InitExpander::visit( ListInit * listInit ) {
    35       // xxx - for now, assume no nested list inits
    36       std::list<Initializer*>::iterator it = listInit->begin_initializers();
    37       for ( ; it != listInit->end_initializers(); ++it ) {
    38         (*it)->accept( *this );
    39       }
    40     }
    41   }
     34                void InitExpander::visit( ListInit * listInit ) {
     35                        // xxx - for now, assume no nested list inits
     36                        std::list<Initializer*>::iterator it = listInit->begin_initializers();
     37                        for ( ; it != listInit->end_initializers(); ++it ) {
     38                                (*it)->accept( *this );
     39                        }
     40                }
     41        }
    4242
    43   std::list< Expression * > makeInitList( Initializer * init ) {
    44     InitExpander expander;
    45     maybeAccept( init, expander );
    46     return expander.argList;
    47   }
     43        std::list< Expression * > makeInitList( Initializer * init ) {
     44                InitExpander expander;
     45                maybeAccept( init, expander );
     46                return expander.argList;
     47        }
    4848
    49   bool isDesignated( Initializer * init ) {
    50     HasDesignations finder;
    51     maybeAccept( init, finder );
    52     return finder.hasDesignations;
    53   }
     49        bool isDesignated( Initializer * init ) {
     50                HasDesignations finder;
     51                maybeAccept( init, finder );
     52                return finder.hasDesignations;
     53        }
    5454
    55   bool tryConstruct( ObjectDecl * objDecl ) {
    56     return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    57       (objDecl->get_init() == NULL ||
    58         ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59       ! isDesignated( objDecl->get_init() );
    60   }
     55        bool tryConstruct( ObjectDecl * objDecl ) {
     56                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
     57                        (objDecl->get_init() == NULL ||
     58                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
     59                        ! isDesignated( objDecl->get_init() );
     60        }
    6161
    62   Expression * getCtorDtorCall( Statement * stmt ) {
    63     if ( stmt == NULL ) return NULL;
    64     if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
    65       return exprStmt->get_expr();
    66     } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
    67       // could also be a compound statement with a loop, in the case of an array
    68       assert( compoundStmt->get_kids().size() == 2 ); // loop variable and loop
    69       ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
    70       assert( forStmt && forStmt->get_body() );
    71       return getCtorDtorCall( forStmt->get_body() );
    72     } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
    73       return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
    74     } else {
    75       // should never get here
    76       assert( false && "encountered unknown call statement" );
    77     }
    78   }
     62        Expression * getCtorDtorCall( Statement * stmt ) {
     63                if ( stmt == NULL ) return NULL;
     64                if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
     65                        return exprStmt->get_expr();
     66                } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
     67                        // could also be a compound statement with a loop, in the case of an array
     68                        assert( compoundStmt->get_kids().size() == 2 ); // loop variable and loop
     69                        ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
     70                        assert( forStmt && forStmt->get_body() );
     71                        return getCtorDtorCall( forStmt->get_body() );
     72                } if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
     73                        return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
     74                } else {
     75                        // should never get here
     76                        assert( false && "encountered unknown call statement" );
     77                }
     78        }
    7979
    80   bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
    81     Expression * callExpr = getCtorDtorCall( stmt );
    82     if ( ! callExpr ) return false;
    83     ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
    84     assert( appExpr );
    85     VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    86     assert( function );
    87     // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    88     // will call all member dtors, and some members may have a user defined dtor.
    89     FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
    90     assert( funcType );
    91     return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
    92   }
     80        bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
     81                Expression * callExpr = getCtorDtorCall( stmt );
     82                if ( ! callExpr ) return false;
     83                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
     84                assert( appExpr );
     85                VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
     86                assert( function );
     87                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
     88                // will call all member dtors, and some members may have a user defined dtor.
     89                FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
     90                assert( funcType );
     91                return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
     92        }
    9393
    94   namespace {
    95     template<typename CallExpr>
    96     Expression * callArg( CallExpr * callExpr, unsigned int pos ) {
    97       if ( pos >= callExpr->get_args().size() ) assert( false && "asking for argument that doesn't exist. Return NULL/throw exception?" );
    98       for ( Expression * arg : callExpr->get_args() ) {
    99         if ( pos == 0 ) return arg;
    100         pos--;
    101       }
    102       assert( false );
    103     }
    104   }
     94        namespace {
     95                template<typename CallExpr>
     96                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
     97                        if ( pos >= callExpr->get_args().size() ) assert( false && "asking for argument that doesn't exist. Return NULL/throw exception?" );
     98                        for ( Expression *& arg : callExpr->get_args() ) {
     99                                if ( pos == 0 ) return arg;
     100                                pos--;
     101                        }
     102                        assert( false );
     103                }
     104        }
    105105
    106   Expression * getCallArg( Expression * callExpr, unsigned int pos ) {
    107     if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
    108       return callArg( appExpr, pos );
    109     } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
    110       return callArg( untypedExpr, pos );
    111     } else {
    112       assert( false && "Unexpected expression type passed to getCallArg" );
    113     }
    114   }
     106        Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
     107                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
     108                        return callArg( appExpr, pos );
     109                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
     110                        return callArg( untypedExpr, pos );
     111                } else {
     112                        assert( false && "Unexpected expression type passed to getCallArg" );
     113                }
     114        }
    115115
    116   namespace {
    117     template<typename CallExpr>
    118     std::string funcName( CallExpr * expr ) {
    119       Expression * func = expr->get_function();
    120       if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
    121         return nameExpr->get_name();
    122       } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
    123         return varExpr->get_var()->get_name();
    124       } else {
    125         assert( false && "Unexpected expression type being called as a function in call expression" );
    126       }
    127     }
    128   }
     116        namespace {
     117                template<typename CallExpr>
     118                std::string funcName( CallExpr * expr ) {
     119                        Expression * func = expr->get_function();
     120                        if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
     121                                return nameExpr->get_name();
     122                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
     123                                return varExpr->get_var()->get_name();
     124                        } else {
     125                                assert( false && "Unexpected expression type being called as a function in call expression" );
     126                        }
     127                }
     128        }
    129129
    130   std::string getFunctionName( Expression * expr ) {
    131     if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
    132       return funcName( appExpr );
    133     } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
    134       return funcName( untypedExpr );
    135     } else {
    136       assert( false && "Unexpected expression type passed to getFunctionName" );
    137     }
    138   }
     130        std::string getFunctionName( Expression * expr ) {
     131                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
     132                        return funcName( appExpr );
     133                } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
     134                        return funcName( untypedExpr );
     135                } else {
     136                        assert( false && "Unexpected expression type passed to getFunctionName" );
     137                }
     138        }
    139139
    140   Type * getPointerBase( Type * type ) {
    141     if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
    142       return ptrType->get_base();
    143     } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    144       return arrayType->get_base();
    145     } else {
    146       return NULL;
    147     }
    148   }
     140        Type * getPointerBase( Type * type ) {
     141                if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
     142                        return ptrType->get_base();
     143                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     144                        return arrayType->get_base();
     145                } else {
     146                        return NULL;
     147                }
     148        }
    149149
     150        Type * isPointerType( Type * type ) {
     151                if ( getPointerBase( type ) ) return type;
     152                else return NULL;
     153        }
    150154}
  • src/InitTweak/InitTweak.h

    r321a2481 r64071c2  
    4747
    4848  /// returns the argument to a call expression in position N indexed from 0
    49   Expression * getCallArg( Expression * callExpr, unsigned int pos );
     49  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    5050
    51   /// returns the base type of a PointerType or ArrayType
     51  /// returns the base type of a PointerType or ArrayType, else returns NULL
    5252  Type * getPointerBase( Type * );
     53
     54  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     55  Type * isPointerType( Type * );
    5356} // namespace
    5457
  • src/ResolvExpr/Resolver.cc

    r321a2481 r64071c2  
    516516
    517517        void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
    518                 // this code is fairly gross. If VariableExpr didn't have its own results list then this could be cleaned up a bit
    519                 // by remembering the ObjectDecl in the ImplicitCtorDtorStmt and changing the ObjectDecl's type temporarily, but currently
    520                 // VariableExprs have their own type list which is manipulated in AlternativeFinder (e.g. in inferRecursive).
    521 
    522                 // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed)
     518                // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
     519                // Do this through a cast expression to greatly simplify the code.
    523520                Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
    524521                assert( callExpr );
    525                 Expression * constructee = InitTweak::getCallArg( callExpr, 0 );
     522                Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
    526523                Type * type = 0;
     524
     525                // need to find the type of the first argument, which is unfortunately not uniform since array construction
     526                // includes an untyped '+' expression.
    527527                if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {
    528528                        // constructee is <array>+<index>
     
    531531                        assert( dynamic_cast< VariableExpr * >( arr ) );
    532532                        assert( arr && arr->get_results().size() == 1 );
    533                         type = InitTweak::getPointerBase( arr->get_results().front() );
    534                         assert( type );
     533                        type = arr->get_results().front()->clone();
    535534                } else {
    536535                        // otherwise, constructing a plain object, which means the object's address is being taken.
     
    539538                        assert( constructee->get_results().size() == 1 );
    540539                        AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
    541                         assert( addrExpr );
    542                         VariableExpr * varExpr = dynamic_cast< VariableExpr * >( addrExpr->get_arg() );
    543                         assert( varExpr && varExpr->get_results().size() == 1 );
    544                         type = varExpr->get_results().front();
    545                 }
    546                 // remember qualifiers so they can be replaced
    547                 Type::Qualifiers qualifiers = type->get_qualifiers();
    548 
     540                        assert( addrExpr && addrExpr->get_results().size() == 1);
     541                        type = addrExpr->get_results().front()->clone();
     542                }
     543                // cast to T* with qualifiers removed.
    549544                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    550545                // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    551546                // remove lvalue as a qualifier, this can change to
    552547                //   type->get_qualifiers() = Type::Qualifiers();
    553                 type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     548                Type * base = InitTweak::getPointerBase( type );
     549                assert( base );
     550                base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     551                // if pointer has lvalue qualifier, cast won't appear in output
     552                type->set_isLvalue( false );
     553                constructee = new CastExpr( constructee, type );
    554554
    555555                // finally, resolve the ctor/dtor
    556556                impCtorDtorStmt->get_callStmt()->accept( *this );
    557 
    558                 // reset type qualifiers, but first need to figure out where everything is again
    559                 // because the expressions are often changed by the resolver.
    560                 callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
    561                 assert( callExpr );
    562                 constructee = InitTweak::getCallArg( callExpr, 0 );
    563                 if ( ApplicationExpr * plusExpr = dynamic_cast< ApplicationExpr * >( constructee ) ) {
    564                         // constructee is <array>+<index>
    565                         // get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed
    566                         Expression * arr = InitTweak::getCallArg( plusExpr, 0 );
    567                         assert( dynamic_cast< VariableExpr * >( arr ) );
    568                         assert( arr && arr->get_results().size() == 1 );
    569                         type = InitTweak::getPointerBase( arr->get_results().front() );
    570                         assert( type );
    571                         type->get_qualifiers() = qualifiers;
    572                 } else {
    573                         // otherwise constructing a plain object
    574                         // replace qualifiers on AddressExpr and on inner VariableExpr
    575                         assert( constructee->get_results().size() == 1 );
    576                         AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
    577                         assert( addrExpr );
    578                         type = InitTweak::getPointerBase( addrExpr->get_results().front() );
    579                         assert( type );
    580                         type->get_qualifiers() = qualifiers;
    581 
    582                         VariableExpr * varExpr = dynamic_cast< VariableExpr * >( addrExpr->get_arg() );
    583                         assert( varExpr && varExpr->get_results().size() == 1 );
    584                         type = varExpr->get_results().front();
    585                         type->get_qualifiers() = qualifiers;
    586                 }
    587557        }
    588558} // namespace ResolvExpr
Note: See TracChangeset for help on using the changeset viewer.