Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    rc600df1 r09867ec  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Oct 25 13:53:00 2021
    13 // Update Count     : 186
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 23:15:10 2019
     13// Update Count     : 184
    1414//
    1515#include "GenInit.h"
     
    2424#include "AST/Decl.hpp"
    2525#include "AST/Init.hpp"
    26 #include "AST/Pass.hpp"
    2726#include "AST/Node.hpp"
    2827#include "AST/Stmt.hpp"
     
    295294        }
    296295
    297 namespace {
    298 
    299 #       warning Remove the _New suffix after the conversion is complete.
    300         struct HoistArrayDimension_NoResolve_New final :
    301                         public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting,
    302                         public ast::WithGuards, public ast::WithConstTranslationUnit,
    303                         public ast::WithVisitorRef<HoistArrayDimension_NoResolve_New> {
    304                 void previsit( const ast::ObjectDecl * decl );
    305                 const ast::DeclWithType * postvisit( const ast::ObjectDecl * decl );
    306                 // Do not look for objects inside there declarations (and type).
    307                 void previsit( const ast::AggregateDecl * ) { visit_children = false; }
    308                 void previsit( const ast::NamedTypeDecl * ) { visit_children = false; }
    309                 void previsit( const ast::FunctionType * ) { visit_children = false; }
    310 
    311                 const ast::Type * hoist( const ast::Type * type );
    312 
    313                 ast::Storage::Classes storageClasses;
    314         };
    315 
    316         void HoistArrayDimension_NoResolve_New::previsit(
    317                         const ast::ObjectDecl * decl ) {
    318                 GuardValue( storageClasses ) = decl->storage;
    319         }
    320 
    321         const ast::DeclWithType * HoistArrayDimension_NoResolve_New::postvisit(
    322                         const ast::ObjectDecl * objectDecl ) {
    323                 return mutate_field( objectDecl, &ast::ObjectDecl::type,
    324                                 hoist( objectDecl->type ) );
    325         }
    326 
    327         const ast::Type * HoistArrayDimension_NoResolve_New::hoist(
    328                         const ast::Type * type ) {
    329                 static UniqueName dimensionName( "_array_dim" );
    330 
    331                 if ( !isInFunction() || storageClasses.is_static ) {
    332                         return type;
    333                 }
    334 
    335                 if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    336                         if ( nullptr == arrayType->dimension ) {
    337                                 return type;
    338                         }
    339 
    340                         if ( !Tuples::maybeImpure( arrayType->dimension ) ) {
    341                                 return type;
    342                         }
    343 
    344                         ast::ptr<ast::Type> dimType = transUnit().global.sizeType;
    345                         assert( dimType );
    346                         add_qualifiers( dimType, ast::CV::Qualifiers( ast::CV::Const ) );
    347 
    348                         ast::ObjectDecl * arrayDimension = new ast::ObjectDecl(
    349                                 arrayType->dimension->location,
    350                                 dimensionName.newName(),
    351                                 dimType,
    352                                 new ast::SingleInit(
    353                                         arrayType->dimension->location,
    354                                         arrayType->dimension
    355                                 )
    356                         );
    357 
    358                         ast::ArrayType * mutType = ast::mutate( arrayType );
    359                         mutType->dimension = new ast::VariableExpr(
    360                                         arrayDimension->location, arrayDimension );
    361                         declsToAddBefore.push_back( arrayDimension );
    362 
    363                         mutType->base = hoist( mutType->base );
    364                         return mutType;
    365                 }
    366                 return type;
    367         }
    368 
    369         struct ReturnFixer_New final :
    370                         public ast::WithStmtsToAdd<>, ast::WithGuards {
    371                 void previsit( const ast::FunctionDecl * decl );
    372                 const ast::ReturnStmt * previsit( const ast::ReturnStmt * stmt );
    373         private:
    374                 const ast::FunctionDecl * funcDecl = nullptr;
    375         };
    376 
    377         void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
    378                 GuardValue( funcDecl ) = decl;
    379         }
    380 
    381         const ast::ReturnStmt * ReturnFixer_New::previsit(
    382                         const ast::ReturnStmt * stmt ) {
    383                 auto & returns = funcDecl->returns;
    384                 assert( returns.size() < 2 );
    385                 // Hands off if the function returns a reference.
    386                 // Don't allocate a temporary if the address is returned.
    387                 if ( stmt->expr && 1 == returns.size() ) {
    388                         ast::ptr<ast::DeclWithType> retDecl = returns.front();
    389                         if ( isConstructable( retDecl->get_type() ) ) {
    390                                 // Explicitly construct the return value using the return
    391                                 // expression and the retVal object.
    392                                 assertf( "" != retDecl->name,
    393                                         "Function %s has unnamed return value.\n",
    394                                         funcDecl->name.c_str() );
    395 
    396                                 auto retVal = retDecl.strict_as<ast::ObjectDecl>();
    397                                 if ( auto varExpr = stmt->expr.as<ast::VariableExpr>() ) {
    398                                         // Check if the return statement is already set up.
    399                                         if ( varExpr->var == retVal ) return stmt;
    400                                 }
    401                                 ast::ptr<ast::Stmt> ctorStmt = genCtorDtor(
    402                                         retVal->location, "?{}", retVal, stmt->expr );
    403                                 assertf( ctorStmt,
    404                                         "ReturnFixer: genCtorDtor returned nllptr: %s / %s",
    405                                         toString( retVal ).c_str(),
    406                                         toString( stmt->expr ).c_str() );
    407                                         stmtsToAddBefore.push_back( ctorStmt );
    408 
    409                                 // Return the retVal object.
    410                                 ast::ReturnStmt * mutStmt = ast::mutate( stmt );
    411                                 mutStmt->expr = new ast::VariableExpr(
    412                                         stmt->location, retDecl );
    413                                 return mutStmt;
    414                         }
    415                 }
    416                 return stmt;
    417         }
    418 
    419 } // namespace
    420 
    421         void genInit( ast::TranslationUnit & transUnit ) {
    422                 ast::Pass<HoistArrayDimension_NoResolve_New>::run( transUnit );
    423                 ast::Pass<ReturnFixer_New>::run( transUnit );
    424         }
    425 
    426296        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
    427297                PassVisitor<CtorDtor> ctordtor;
Note: See TracChangeset for help on using the changeset viewer.