source: src/ControlStruct/TranslateEnumRange.cpp@ 8da3cc4d

Last change on this file since 8da3cc4d was 5f210c0, checked in by JiadaL <j82liang@…>, 14 months ago

Change enum pos to signed int to avoid underflow; operator on enum will not have range check (but succ and pred still have range check

  • Property mode set to 100644
File size: 2.9 KB
Line 
1#include "TranslateEnumRange.hpp"
2
3#include "AST/Pass.hpp"
4#include "AST/TranslationUnit.hpp"
5
6namespace ControlStruct {
7
8struct addInit {
9 const ast::Stmt * postvisit( const ast::ForStmt * stmt );
10};
11
12struct translateEnumRangeCore {
13 const ast::Stmt * postvisit( const ast::ForStmt * stmt );
14};
15
16const ast::Stmt* addInit::postvisit( const ast::ForStmt * stmt ) {
17 if ( stmt->range_over ) {
18 auto inits = stmt->inits;
19 auto init = stmt->inits.front();
20
21 if (auto declStmt = init.as<ast::DeclStmt>()) {
22 auto decl = declStmt->decl;
23 if ( auto objDecl = decl.as<ast::ObjectDecl>()) {
24 if ( !objDecl->init ) {
25 auto location = stmt->location;
26 ast::SingleInit * newInit = new ast::SingleInit( location,
27 stmt->is_inc?
28 ast::UntypedExpr::createCall( location, "lowerBound", {} ):
29 ast::UntypedExpr::createCall( location, "upperBound", {} ),
30 ast::ConstructFlag::MaybeConstruct
31 );
32 auto objDeclWithInit = ast::mutate_field( objDecl, &ast::ObjectDecl::init, newInit );
33 auto declWithInit = ast::mutate_field( declStmt, &ast::DeclStmt::decl, objDeclWithInit );
34 stmt = ast::mutate_field_index( stmt, &ast::ForStmt::inits, 0, declWithInit );
35 }
36 }
37 }
38 }
39 return stmt;
40}
41
42const ast::Stmt* translateEnumRangeCore::postvisit( const ast::ForStmt * stmt ) {
43 if ( !stmt->range_over ) return stmt;
44 auto location = stmt->location;
45 auto declStmt = stmt->inits.front().strict_as<ast::DeclStmt>();
46 auto initDecl = declStmt->decl.strict_as<ast::ObjectDecl>();
47 auto indexName = initDecl->name;
48
49 // Both inc and dec check if the current posn less than the number of enumerator
50 // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,
51 // it wraps around and become unsigned max
52 ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,
53 stmt->is_inc? "?<=?": "?>=?",
54 { new ast::NameExpr( location, indexName ),
55 stmt->is_inc?
56 ast::UntypedExpr::createCall( location, "upperBound", {} ):
57 ast::UntypedExpr::createCall( location, "lowerBound", {} )
58 });
59 auto increment = ast::UntypedExpr::createCall( location,
60 stmt->is_inc? "succ_unsafe": "pred_unsafe",
61 { new ast::NameExpr( location, indexName ) });
62 auto assig = ast::UntypedExpr::createAssign( location, new ast::NameExpr( location, indexName ), increment );
63 auto mut = ast::mutate_field( stmt, &ast::ForStmt::cond, condition );
64 mut = ast::mutate_field(stmt, &ast::ForStmt::inc, assig );
65 return mut;
66}
67
68void translateEnumRange( ast::TranslationUnit & translationUnit ) {
69 ast::Pass<addInit>::run( translationUnit );
70 ast::Pass<translateEnumRangeCore>::run( translationUnit );
71}
72}
Note: See TracBrowser for help on using the repository browser.