source: src/Parser/StatementNode.cpp @ d3b33d5

Last change on this file since d3b33d5 was d3b33d5, checked in by Peter A. Buhr <pabuhr@…>, 2 days ago

fix dangling reference after delete

  • Property mode set to 100644
File size: 18.6 KB
RevLine 
[b87a5ed]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[c92bdcc]7// StatementNode.cpp -- Transform from parse data-structures to AST data-structures, usually deleting the parse
[4e7171f]8//     data-structure after the transformation.
[b87a5ed]9//
10// Author           : Rodolfo G. Esteves
11// Created On       : Sat May 16 14:59:41 2015
[f259682]12// Last Modified By : Peter A. Buhr
[d3b33d5]13// Last Modified On : Mon Sep  9 11:28:07 2024
14// Update Count     : 430
[b87a5ed]15//
16
[c92bdcc]17#include "StatementNode.hpp"
[c468150]18
[e3e16bc]19#include <cassert>                 // for assert, strict_dynamic_cast, assertf
[d180746]20#include <memory>                  // for unique_ptr
21#include <string>                  // for string
[51b7345]22
[bb7422a]23#include "AST/Label.hpp"           // for Label
24#include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
[c92bdcc]25#include "Common/SemanticError.hpp"// for SemanticError
26#include "Common/Utility.hpp"      // for maybeMoveBuild, maybeBuild
27#include "DeclarationNode.hpp"     // for DeclarationNode
28#include "ExpressionNode.hpp"      // for ExpressionNode
29#include "ParserUtility.hpp"       // for notZeroExpr
[d180746]30
31class Declaration;
[51b7345]32
33using namespace std;
34
[6611177]35// Some helpers for cases that really want a single node but check for lists.
36static const ast::Stmt * buildMoveSingle( StatementNode * node ) {
37        std::vector<ast::ptr<ast::Stmt>> list;
38        buildMoveList( node, list );
39        assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" );
40        return list.front().release();
41}
42
43static const ast::Stmt * buildMoveOptional( StatementNode * node ) {
44        std::vector<ast::ptr<ast::Stmt>> list;
45        buildMoveList( node, list );
46        assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" );
47        return list.empty() ? nullptr : list.front().release();
48}
49
[61fc4f6]50StatementNode::StatementNode( DeclarationNode * decl ) {
[c0aa336]51        assert( decl );
[61fc4f6]52        DeclarationNode * agg = decl->extractAggregate();
[c0aa336]53        if ( agg ) {
[bb7422a]54                StatementNode * nextStmt = new StatementNode(
55                        new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
[44adf1b]56                next = nextStmt;
57                if ( decl->next ) {
58                        next->next = new StatementNode( decl->next );
59                        decl->next = nullptr;
[1d4580a]60                } // if
61        } else {
[44adf1b]62                if ( decl->next ) {
63                        next = new StatementNode( decl->next );
64                        decl->next = nullptr;
[c0aa336]65                } // if
66                agg = decl;
[1d4580a]67        } // if
[bb7422a]68        // Local copy to avoid accessing the pointer after it is moved from.
69        CodeLocation declLocation = agg->location;
70        stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
[c0aa336]71} // StatementNode::StatementNode
[1d4580a]72
[c468150]73StatementNode * StatementNode::add_label(
74                const CodeLocation & location,
75                const std::string * name,
76                DeclarationNode * attr ) {
77        stmt->labels.emplace_back( location,
78                *name,
79                attr ? std::move( attr->attributes )
80                        : std::vector<ast::ptr<ast::Attribute>>{} );
81        delete attr;
82        delete name;
83        return this;
84}
85
[6611177]86ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) {
87        ClauseNode * prev = this;
[1d4580a]88        // find end of list and maintain previous pointer
[44adf1b]89        for ( ClauseNode * curr = prev; curr != nullptr; curr = curr->next ) {
90                ClauseNode * node = curr;
[bb7422a]91                assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
[8cc5cb0]92                prev = curr;
93        } // for
[44adf1b]94        ClauseNode * node = prev;
[e82aa9df]95        // convert from StatementNode list to Statement list
[bb7422a]96        std::vector<ast::ptr<ast::Stmt>> stmts;
[7ecbb7e]97        buildMoveList( stmt, stmts );
[e82aa9df]98        // splice any new Statements to end of current Statements
[bb7422a]99        auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
100        for ( auto const & newStmt : stmts ) {
101                caseStmt->stmts.emplace_back( newStmt );
102        }
103        stmts.clear();
[8cc5cb0]104        return this;
[6611177]105} // ClauseNode::append_last_case
[8cc5cb0]106
[bb7422a]107ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
108        if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
109                return new ast::ExprStmt( location, e );
110        } else {
111                return new ast::NullStmt( location );
112        }
[401e61f]113} // build_expr
[8cc5cb0]114
[bb7422a]115static ast::Expr * build_if_control( CondCtl * ctl,
116                std::vector<ast::ptr<ast::Stmt>> & inits ) {
117        assert( inits.empty() );
118        if ( nullptr != ctl->init ) {
119                buildMoveList( ctl->init, inits );
[936e9f4]120        } // if
121
[bb7422a]122        ast::Expr * cond = nullptr;
[a01f7c94]123        if ( ctl->condition ) {
[ab780e6]124                cond = maybeMoveBuild( ctl->condition );
[a01f7c94]125        } else {
[bb7422a]126                for ( ast::ptr<ast::Stmt> & stmt : inits ) {
[a01f7c94]127                        // build the && of all of the declared variables compared against 0
[bb7422a]128                        auto declStmt = stmt.strict_as<ast::DeclStmt>();
129                        auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
[ab780e6]130                        ast::Expr * nze = new ast::VariableExpr( dwt->location, dwt );
[bb7422a]131                        cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
[a01f7c94]132                }
133        }
[6d49ea3]134        delete ctl;
[ee3c93d]135        return cond;
[401e61f]136} // build_if_control
[ee3c93d]137
[bb7422a]138ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
139        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
140        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
[436bbe5]141
[5541a44e]142        ast::Stmt const * astthen = buildMoveSingle( then );
143        ast::Stmt const * astelse = buildMoveOptional( else_ );
[ee3c93d]144
[bb7422a]145        return new ast::IfStmt( location, astcond, astthen, astelse,
146                std::move( astinit )
147        );
[401e61f]148} // build_if
[2f22cc4]149
[6611177]150ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) {
[bb7422a]151        std::vector<ast::ptr<ast::CaseClause>> aststmt;
[6611177]152        buildMoveList( stmt, aststmt );
[bb7422a]153        // If it is not a switch it is a choose statement.
154        if ( ! isSwitch ) {
155                for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
156                        // Code after "case" is the end of case list.
157                        if ( !stmt->stmts.empty() ) {
158                                auto mutStmt = ast::mutate( stmt.get() );
159                                // I believe the stmts are actually always one block.
160                                auto stmts = mutStmt->stmts.front().get_and_mutate();
161                                auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
162                                block->kids.push_back( new ast::BranchStmt( block->location,
163                                        ast::BranchStmt::Break,
164                                        ast::Label( block->location ) ) );
165                                stmt = mutStmt;
[6a276a0]166                        } // if
167                } // for
168        } // if
[436bbe5]169        // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
[bb7422a]170        return new ast::SwitchStmt( location,
171                maybeMoveBuild( ctl ), std::move( aststmt ) );
[401e61f]172} // build_switch
173
[6611177]174ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) {
[bb7422a]175        // stmt starts empty and then added to
176        auto expr = maybeMoveBuild( ctl );
[6611177]177        return new ast::CaseClause( location, expr, {} );
[401e61f]178} // build_case
179
[bb7422a]180ast::CaseClause * build_default( const CodeLocation & location ) {
181        // stmt starts empty and then added to
182        return new ast::CaseClause( location, nullptr, {} );
[401e61f]183} // build_default
184
[bb7422a]185ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
186        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
187        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
[3b0bc16]188
[bb7422a]189        return new ast::WhileDoStmt( location,
190                astcond,
[6611177]191                buildMoveSingle( stmt ),
192                buildMoveOptional( else_ ),
[bb7422a]193                std::move( astinit ),
[3e94a23]194                ast::While
[bb7422a]195        );
[401e61f]196} // build_while
[2f22cc4]197
[bb7422a]198ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
[4e7171f]199        // do-while cannot have declarations in the contitional, so init is always empty
[bb7422a]200        return new ast::WhileDoStmt( location,
[ab780e6]201                maybeMoveBuild( ctl ),
[6611177]202                buildMoveSingle( stmt ),
203                buildMoveOptional( else_ ),
[bb7422a]204                {},
[3e94a23]205                ast::DoWhile
[bb7422a]206        );
[401e61f]207} // build_do_while
[2f22cc4]208
[bb7422a]209ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
[d3b33d5]210        std::vector<ast::ptr<ast::Stmt>> astinit;                       // maybe empty
[436bbe5]211        buildMoveList( forctl->init, astinit );
[2f22cc4]212
[525f7ad]213        if ( forctl->range_over ) {
214                ast::Expr * range_over = maybeMoveBuild( forctl->range_over );
[d3b33d5]215                auto kind = forctl->kind;                                               // save before delete, used in return
[525f7ad]216                delete forctl;
217                return new ast::ForStmt( location,
218                        std::move( astinit ),
[d3b33d5]219                        range_over, kind == OperKinds::LEThan,
[525f7ad]220                        buildMoveSingle( stmt ),
221                        buildMoveOptional( else_ )
222                );
223        }
224
[bb7422a]225        ast::Expr * astcond = nullptr;                                          // maybe empty
[ab780e6]226        astcond = maybeMoveBuild( forctl->condition );
[2f22cc4]227
[bb7422a]228        ast::Expr * astincr = nullptr;                                          // maybe empty
[702e826]229        astincr = maybeMoveBuild( forctl->change );
[436bbe5]230        delete forctl;
[2f22cc4]231
[bb7422a]232        return new ast::ForStmt( location,
233                std::move( astinit ),
234                astcond,
235                astincr,
[6611177]236                buildMoveSingle( stmt ),
237                buildMoveOptional( else_ )
[bb7422a]238        );
[401e61f]239} // build_for
[2f22cc4]240
[bb7422a]241ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
242        return new ast::BranchStmt( location,
243                kind,
244                ast::Label( location )
245        );
[401e61f]246} // build_branch
247
[bb7422a]248ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
249        ast::Stmt * ret = new ast::BranchStmt( location,
250                kind,
251                ast::Label( location, *identifier )
252        );
253        delete identifier;                                                                      // allocated by lexer
[ab57786]254        return ret;
[401e61f]255} // build_branch
256
[bb7422a]257ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
258        ast::Expr * expr = maybeMoveBuild( ctl );
259        return new ast::BranchStmt( expr->location, expr );
[401e61f]260} // build_computedgoto
[8cc5cb0]261
[bb7422a]262ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
263        std::vector<ast::ptr<ast::Expr>> exps;
[7ecbb7e]264        buildMoveList( ctl, exps );
[bb7422a]265        return new ast::ReturnStmt( location,
266                exps.size() > 0 ? exps.back().release() : nullptr
267        );
[401e61f]268} // build_return
[daf1af8]269
[bb7422a]270static ast::Stmt * build_throw_stmt(
271                const CodeLocation & location,
272                ExpressionNode * ctl,
273                ast::ExceptionKind kind ) {
274        std::vector<ast::ptr<ast::Expr>> exps;
[7ecbb7e]275        buildMoveList( ctl, exps );
[436bbe5]276        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
[bb7422a]277        return new ast::ThrowStmt( location,
278                kind,
279                !exps.empty() ? exps.back().release() : nullptr,
280                (ast::Expr *)nullptr
281        );
282}
283
284ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
285        return build_throw_stmt( loc, ctl, ast::Terminate );
[401e61f]286} // build_throw
[daf1af8]287
[bb7422a]288ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
289        return build_throw_stmt( loc, ctl, ast::Resume );
[401e61f]290} // build_resume
[daf1af8]291
[bb7422a]292ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
[794c15b]293        (void)ctl;
294        (void)target;
295        assertf( false, "resume at (non-local throw) is not yet supported," );
[401e61f]296} // build_resume_at
[321f55d]297
[6611177]298ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
[bb7422a]299        std::vector<ast::ptr<ast::CatchClause>> aststmt;
[6611177]300        buildMoveList( catch_, aststmt );
[bb7422a]301        ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
302        ast::FinallyClause * finallyBlock = nullptr;
303        if ( finally_ ) {
304                finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
305        }
306        return new ast::TryStmt( location,
307                tryBlock,
308                std::move( aststmt ),
309                finallyBlock
310        );
[401e61f]311} // build_try
312
[bb7422a]313ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
314        return new ast::CatchClause( location,
315                kind,
316                maybeMoveBuild( decl ),
317                maybeMoveBuild( cond ),
[6611177]318                buildMoveSingle( body )
[bb7422a]319        );
[401e61f]320} // build_catch
321
[bb7422a]322ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
323        return new ast::FinallyClause( location,
[6611177]324                strict_dynamic_cast<const ast::CompoundStmt *>(
325                        buildMoveSingle( stmt )
326                )
[bb7422a]327        );
[401e61f]328} // build_finally
[1d4580a]329
[835d6e8]330ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) {
[6611177]331        return new ast::SuspendStmt( location,
332                strict_dynamic_cast<const ast::CompoundStmt *, nullptr>(
333                        buildMoveOptional( then )
334                ),
335                kind
336        );
[9fd9d015]337} // build_suspend
[427854b]338
[bb7422a]339ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
340        auto clause = new ast::WaitForClause( location );
[c86b08d]341        clause->target = maybeBuild( targetExpr );
[bb7422a]342        clause->stmt = maybeMoveBuild( stmt );
[ab780e6]343        clause->when_cond = maybeMoveBuild( when );
[2065609]344
[44adf1b]345        ExpressionNode * next = targetExpr->next;
346        targetExpr->next = nullptr;
[bb7422a]347        buildMoveList( next, clause->target_args );
[2065609]348
[135b431]349        delete targetExpr;
350
[bb7422a]351        existing->clauses.insert( existing->clauses.begin(), clause );
[135b431]352
[9fd9d015]353        return existing;
[401e61f]354} // build_waitfor
[135b431]355
[bb7422a]356ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
357        existing->else_stmt = maybeMoveBuild( stmt );
[ab780e6]358        existing->else_cond = maybeMoveBuild( when );
[135b431]359
[bb7422a]360        (void)location;
[9fd9d015]361        return existing;
362} // build_waitfor_else
[135b431]363
[bb7422a]364ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
365        existing->timeout_time = maybeMoveBuild( timeout );
366        existing->timeout_stmt = maybeMoveBuild( stmt );
[ab780e6]367        existing->timeout_cond = maybeMoveBuild( when );
[135b431]368
[bb7422a]369        (void)location;
[9fd9d015]370        return existing;
[401e61f]371} // build_waitfor_timeout
[135b431]372
[c86b08d]373ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
[6a4dae6]374        ast::WhenClause * clause = new ast::WhenClause( loc );
[ab780e6]375        clause->when_cond = maybeMoveBuild( when );
[6a4dae6]376        clause->stmt = maybeMoveBuild( stmt );
377        clause->target = maybeMoveBuild( targetExpr );
378        return new ast::WaitUntilStmt::ClauseNode( clause );
[c86b08d]379}
380ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
[6a4dae6]381        ast::WhenClause * clause = new ast::WhenClause( loc );
[ab780e6]382        clause->when_cond = maybeMoveBuild( when );
[6a4dae6]383        clause->stmt = maybeMoveBuild( stmt );
384        return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
[c86b08d]385}
[6a4dae6]386
[c86b08d]387ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
[6a4dae6]388        ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
389        retStmt->predicateTree = root;
390
391        // iterative tree traversal
392        std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
393        ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
394        ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
395        ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
396        nodeStack.push_back(root);
397
398        do {
399                currNode = nodeStack.back();
400                nodeStack.pop_back(); // remove node since it will be processed
401
402                switch (currNode->op) {
403                case ast::WaitUntilStmt::ClauseNode::LEAF:
404                        retStmt->clauses.push_back(currNode->leaf);
405                        break;
406                case ast::WaitUntilStmt::ClauseNode::ELSE:
407                        retStmt->else_stmt = currNode->leaf->stmt
408                                ? ast::deepCopy( currNode->leaf->stmt )
409                                : nullptr;
410                        retStmt->else_cond = currNode->leaf->when_cond
411                                ? ast::deepCopy( currNode->leaf->when_cond )
412                                : nullptr;
413
414                        delete currNode->leaf;
415                        break;
416                case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
417                        retStmt->timeout_time = currNode->leaf->target
418                                ? ast::deepCopy( currNode->leaf->target )
419                                : nullptr;
420                        retStmt->timeout_stmt = currNode->leaf->stmt
421                                ? ast::deepCopy( currNode->leaf->stmt )
422                                : nullptr;
423                        retStmt->timeout_cond = currNode->leaf->when_cond
424                                ? ast::deepCopy( currNode->leaf->when_cond )
425                                : nullptr;
426
427                        delete currNode->leaf;
428                        break;
429                default:
430                        nodeStack.push_back( currNode->right ); // process right after left
431                        nodeStack.push_back( currNode->left );
432
433                        // Cut else/timeout out of the tree
434                        if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
435                                if ( lastInternalNode )
436                                        lastInternalNode->right = currNode->left;
437                                else // if not set then root is LEFT_OR
438                                        retStmt->predicateTree = currNode->left;
439
440                                currNode->left = nullptr;
441                                cleanup = currNode;
442                        }
443
444                        lastInternalNode = currNode;
445                        break;
446                }
447        } while ( !nodeStack.empty() );
448
449        if ( cleanup ) delete cleanup;
450
451        return retStmt;
[c86b08d]452}
453
[bb7422a]454ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
455        std::vector<ast::ptr<ast::Expr>> e;
[a378ca7]456        buildMoveList( exprs, e );
[bb7422a]457        ast::Stmt * s = maybeMoveBuild( stmt );
458        return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
[401e61f]459} // build_with
[a378ca7]460
[bb7422a]461ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
462        auto cs = new ast::CompoundStmt( location );
463        buildMoveList( first, cs->kids );
[b87a5ed]464        return cs;
[401e61f]465} // build_compound
[51b7345]466
[a025ea8]467// A single statement in a control structure is always converted to a compound statement so subsequent generated code
468// can be placed within this compound statement. Otherwise, code generation has to constantly check for a single
469// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
470// conical form for code generation.
[bb7422a]471StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
[a025ea8]472        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
473        // e.g., if (...) {...} do not wrap the existing compound statement.
[bb7422a]474        if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
475                return new StatementNode( build_compound( location, first ) );
[a025ea8]476        } // if
477        return first;
478} // maybe_build_compound
479
[f135b50]480// Question
[32d6fdc]481ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
[bb7422a]482        std::vector<ast::ptr<ast::Expr>> out, in;
483        std::vector<ast::ptr<ast::ConstantExpr>> clob;
[e82aa9df]484
[7ecbb7e]485        buildMoveList( output, out );
486        buildMoveList( input, in );
487        buildMoveList( clobber, clob );
[bb7422a]488        return new ast::AsmStmt( location,
[32d6fdc]489                is_volatile,
490                maybeMoveBuild( instruction ),
[bb7422a]491                std::move( out ),
492                std::move( in ),
493                std::move( clob ),
494                gotolabels ? gotolabels->labels : std::vector<ast::Label>()
495        );
[401e61f]496} // build_asm
[7f5566b]497
[bb7422a]498ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
499        auto stmt = new ast::DirectiveStmt( location, *directive );
500        delete directive;
501        return stmt;
[401e61f]502} // build_directive
[61fc4f6]503
[bb7422a]504ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
505        std::vector<ast::ptr<ast::Expr>> expList;
[de52331]506        buildMoveList( exprs, expList );
[bb7422a]507        ast::Stmt * body = maybeMoveBuild( stmt );
508        return new ast::MutexStmt( location, body, std::move( expList ) );
[de52331]509} // build_mutex
510
[eb779d5]511ast::Stmt * build_corun( const CodeLocation & location, StatementNode * stmt ) {
512        ast::Stmt * body = maybeMoveBuild( stmt );
513        return new ast::CorunStmt( location, body );
514} // build_corun
515
[3d9d017]516ast::Stmt * build_cofor( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt ) {
517        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
518        buildMoveList( forctl->init, astinit );
519
520        ast::Expr * astcond = nullptr;                                          // maybe empty
[ab780e6]521        astcond = maybeMoveBuild( forctl->condition );
[3d9d017]522
523        ast::Expr * astincr = nullptr;                                          // maybe empty
524        astincr = maybeMoveBuild( forctl->change );
525        delete forctl;
526
527        return new ast::CoforStmt( location,
528                std::move( astinit ),
529                astcond,
530                astincr,
531                buildMoveSingle( stmt )
532        );
533} // build_cofor
534
[51b7345]535// Local Variables: //
[b87a5ed]536// tab-width: 4 //
537// mode: c++ //
538// compile-command: "make install" //
[51b7345]539// End: //
Note: See TracBrowser for help on using the repository browser.