Changes in / [e04ef3a:c8c03683]
- Files:
-
- 8 added
- 2 deleted
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
re04ef3a rc8c03683 36 36 37 37 def push_build() { 38 build_stage 'Push' 39 40 sh 'git remote add DoLang git@gitlab.do-lang.org:internal/cfa-cc.git' 41 sh 'git push DoLang master' 38 //Don't use the build_stage function which outputs the compiler 39 stage 'Push' 40 41 status_prefix = 'Push' 42 43 def out_dir = pwd tmp: true 44 sh "mkdir -p ${out_dir}" 45 46 //parse git logs to find what changed 47 sh "git remote > ${out_dir}/GIT_REMOTE" 48 git_remote = readFile("${out_dir}/GIT_REMOTE") 49 remoteDoLangExists = git_remote.contains("DoLang") 50 51 if( !remoteDoLangExists ) { 52 sh 'git remote add DoLang git@gitlab.do-lang.org:internal/cfa-cc.git' 53 } 54 55 sh "git push DoLang ${gitRefNewValue}:master" 42 56 } 43 57 … … 74 88 def collect_git_info() { 75 89 90 //create the temporary output directory in case it doesn't already exist 76 91 def out_dir = pwd tmp: true 92 sh "mkdir -p ${out_dir}" 93 94 //parse git logs to find what changed 77 95 gitRefName = env.BRANCH_NAME 78 96 dir("../${gitRefName}@script") { … … 89 107 node ('master'){ 90 108 109 boolean doPromoteBuild2DoLang 91 110 def err = null 92 111 def log_needed = false … … 113 132 ]]) 114 133 115 echo "FULL BUILD = ${promoteBuild2DoLang}" 134 doPromoteBuild2DoLang = promoteBuild2DoLang == 'true' 135 136 echo "FULL BUILD = ${doPromoteBuild2DoLang}" 116 137 117 138 //Compile using gcc-4.9 … … 127 148 cfa_build() 128 149 129 if( promote_build) {150 if( doPromoteBuild2DoLang ) { 130 151 push_build() 131 152 } … … 149 170 finally { 150 171 //Send email with final results 151 notify_result( promote_build, err != null, currentBuild.result, log_needed)172 notify_result(doPromoteBuild2DoLang, err, currentBuild.result, log_needed) 152 173 153 174 /* Must re-throw exception to propagate error */ … … 161 182 //Routine responsible of sending the email notification once the build is completed 162 183 //=========================================================================================================== 163 def promote_email(boolean promote, boolean success, String status, boolean log) {184 def notify_result(boolean promote, Exception err, String status, boolean log) { 164 185 if(promote) { 165 if( !success) {186 if( err ) { 166 187 promote_email(status) 167 188 } -
doc/bibliography/cfa.bib
re04ef3a rc8c03683 356 356 } 357 357 358 @article{Cor :overload,358 @article{Cormack81, 359 359 keywords = {}, 360 360 contributer = {gjditchfield@plg}, … … 2922 2922 } 2923 2923 } 2924 2925 @unpublished{Bilson, 2926 keywords = {generic programming, generics, polymorphism}, 2927 contributor {a3moss@plg}, 2928 author = {Richard C. Bilson and Glen Ditchfield and Peter A. Buhr}, 2929 title = {Generic Programming with Inferred Models}, 2930 } 2931 2924 2932 2925 2933 @article{Haskell, … … 5455 5463 % Q 5456 5464 5465 @article{Grossman06, 5466 keywords = {Cyclone, existential types, polymorphism, type variables}, 5467 contributer = {a3moss@plg}, 5468 author = {Grossman, Dan}, 5469 title = {Quantified Types in an Imperative Language}, 5470 journal = toplas, 5471 issue_date = {May 2006}, 5472 volume = {28}, 5473 number = {3}, 5474 month = may, 5475 year = {2006}, 5476 issn = {0164-0925}, 5477 pages = {429--475}, 5478 numpages = {47}, 5479 url = {http://doi.acm.org.proxy.lib.uwaterloo.ca/10.1145/1133651.1133653}, 5480 doi = {10.1145/1133651.1133653}, 5481 acmid = {1133653}, 5482 publisher = {ACM}, 5483 address = {New York, NY, USA}, 5484 } 5485 5457 5486 @article{Hoare61, 5458 5487 keywords = {quick sort}, -
doc/working/resolver_design.md
re04ef3a rc8c03683 81 81 82 82 ## Conversion Costs ## 83 Each possible resolution of an expression has a _cost_ consisting of four 84 integer components: _unsafe_ conversion cost, _polymorphic_ specialization 85 cost, _safe_ conversion cost, and a _count_ of conversions. 86 These components form a lexically-ordered tuple which can be summed 87 element-wise; summation starts at `(0, 0, 0, 0)`. 83 Each possible resolution of an expression has a _cost_ tuple consisting of 84 the following components: _unsafe_ conversion cost, _polymorphic_ 85 specialization cost, _safe_ conversion cost, a count of _explicit_ 86 conversions, and _qualifier_ conversion cost. 87 These components are lexically-ordered and can be summed element-wise; 88 summation starts at `(0, 0, 0, 0, 0)`. 88 89 89 90 ### Lvalue and Qualifier Conversions ### … … 1224 1225 programmers. 1225 1226 1227 ## Resolver Architecture ## 1228 1229 ### Function Application Resolution ### 1230 Our resolution algorithm for function application expressions is based on 1231 Baker's[3] single-pass bottom-up algorithm, with Cormack's[4] single-pass 1232 top-down algorithm applied where appropriate as an optimization. 1233 Broadly speaking, the cost of this resolution per expression will be 1234 proportional to `i^d`, where `i` is the number of interpretations of each 1235 program symbol, and `d` is the maximum depth of the expression DAG. 1236 Since `d` is determined by the user programmer (in general, bounded by a small 1237 constant), opportunities for resolver optimization primarily revolve around 1238 minimizing `i`, the number of interpretations of each symbol that are 1239 considered. 1240 1241 [3] Baker, Theodore P. A one-pass algorithm for overload resolution in Ada. 1242 ACM Transactions on Programming Languages and Systems (1982) 4:4 p.601-614 1243 1244 [4] Cormack, Gordon V. An algorithm for the selection of overloaded functions 1245 in Ada. SIGPLAN Notices (1981) 16:2 p.48-52 1246 1247 Unlike Baker, our system allows implicit type conversions for function 1248 arguments and return types; the problem then becomes to find the valid 1249 interpretation for an expression that has the unique minimal conversion cost, 1250 if such exists. 1251 Interpretations can be produced both by overloaded names and implicit 1252 conversions applied to existing interpretations; we have proposals to reduce 1253 the number of interpretations considered from both sources. 1254 To simplify the problem for this discussion, we will consider application 1255 resolution restricted to a domain of functions applied to variables, possibly 1256 in a nested manner (e.g. `f( g( x ), y )`, where `x` and `y` are variables and 1257 `f` and `g` are functions), and possibly in a typed context such as a variable 1258 initialization (e.g. `int i = f( x );`); the other aspects of Cforall type 1259 resolution should be able to be straightforwardly mapped into this model. 1260 The types of the symbol tables used for variable and function declarations 1261 look somewhat like the following: 1262 1263 variable_table = name_map( variable_name, variable_map ) 1264 1265 function_table = name_map( function_name, function_map ) 1266 1267 variable_map = multi_index( by_type( variable_type ), 1268 variable_decl_set ) 1269 1270 function_map = multi_index( by_int( n_params ), 1271 by_type( return_type ), 1272 function_decl_set ) 1273 1274 `variable_name` and `function_name` are likely simple strings, with `name_map` 1275 a hash table (or perhaps trie) mapping string keys to values. 1276 `variable_decl_set` and `function_decl_set` can be thought of for the moment 1277 as simple bags of typed declarations, where the declaration types are linked 1278 to the graph of available conversions for that type. 1279 In a typed context both the `variable_decl_set` and the `function_decl_set` 1280 should be able to be selected upon by type; this is accomplished by the 1281 `by_type` index of both `variable_map` and `function_map`. 1282 The `by_int` index of `function_map` also provides a way to select functions 1283 by their number of parameters; this index may be used to swiftly discard any 1284 function declaration which does not have the appropriate number of parameters 1285 for the argument interpretations being passed to it; given the likely small 1286 number of entries in this map, it is possible that a binary search of a sorted 1287 vector or even a linear search of an unsorted vector would be more efficient 1288 than the usual hash-based index. 1289 1290 Given these data structures, the general outline of our algorithm follows 1291 Baker, with Cormack's algorithm used as a heuristic filter in typed contexts. 1292 1293 In an untyped context, we use a variant of Baker's bottom-up algorithm. 1294 The leaves of the interpretation DAG are drawn from the variable symbol table, 1295 with entries in the table each producing zero-cost interpretations, and each 1296 implicit conversion available to be applied to the type of an existing entry 1297 producing a further interpretation with the same cost as the conversion. 1298 As in Baker, if two or more interpretations have the same type, only the 1299 minimum cost interpretation with that type is produced; if there is no unique 1300 minimum cost interpretation than resolution with that type is ambiguous, and 1301 not permitted. 1302 It should be relatively simple to produce the list of interpretations sorted 1303 by cost by producing the interpretations via a breadth-first search of the 1304 conversion graph from the initial interpretations provided in the variable 1305 symbol table. 1306 1307 To match a function at one of the internal nodes of the DAG, we first look up 1308 the function's name in the function symbol table, the appropriate number of 1309 parameters for the arguments that are provided through the `by_int` index of 1310 the returned `function_map`, then go through the resulting `function_decl_set` 1311 searching for functions where the parameter types can unify with the provided 1312 argument lists; any such matching function produces an interpretation with a 1313 cost that is the sum of its argument costs. 1314 Though this is not included in our simplified model, this unification step may 1315 include binding of polymorphic variables, which introduces a cost for the 1316 function binding itself which must be added to the argument costs. 1317 Also, checking of function assertions would likely be done at this step as 1318 well, possibly eliminating some possible matching functions (if no suitable 1319 assertions can be satisfied), or adding further conversion costs for the 1320 assertion satisfaction. 1321 Once the set of valid function interpretations is produced, these may also be 1322 expanded by the graph of implicit conversions on their return types, as the 1323 variable interpretations were. 1324 1325 This implicit conversion-based expansion of interpretations should be skipped 1326 for the top-level expression if used in an untyped (void) context, e.g. for 1327 `f` in `f( g ( x ) );` or `x` in `x;`. 1328 On the other hand, if the top-level expression specifies a type, e.g. in 1329 `int i = f( x );`, only top level expressions that return that type are 1330 relevant to the search, so the candidates for `f` can be filtered first by 1331 those that return `int` (or a type convertable to it); this can be 1332 accomplished by performing a top-down filter of the interpretations of `f` by 1333 the `by_type` index of the `function_map` in a manner similar to Cormack's[4] 1334 algorithm. 1335 1336 In a typed context, such as an initialization expression 1337 `T x = f( g( y ), z );`, only interpretations of `f( g( y ), z )` which have 1338 type `T` are valid; since there are likely to be valid interpretations of 1339 `f( g( y ), z )` which cannot be used to initialize a variable of type `T`, we 1340 can use this information to reduce the number of interpretations considered. 1341 Drawing from Cormack[4], we first search for interpretations of `f` where the 1342 return type is `T`; by breadth-first-search of the conversion graph, it should 1343 be straightforward to order the interpretations of `f` by the cost to convert 1344 their return type to `T`. 1345 We can also filter out interpretations of `f` with less than two parameters, 1346 since both `g( y )` and `z` must produce at least one parameter; we may not, 1347 however, rule out interpretations of `f` with more than two parameters, as 1348 there may be a valid interpretation of `g( y )` as a function returning more 1349 than one parameter (if the expression was `f( y, z )` instead, we could use an 1350 exact parameter count, assuming that variables of tuple type don't exist). 1351 For each compatible interpretation of `f`, we can add the type of the first 1352 parameter of that interpretation of `f` to a set `S`, and recursively search 1353 for interpretations of `g( y )` that return some type `Si` in `S`, and 1354 similarly for interpretations of `z` that match the type of any of the second 1355 parameters of some `f`. 1356 Naturally, if no matching interpretation of `g( y )` can be found for the 1357 first parameter of some `f`, the type of the second parameter of that `f` will 1358 not be added to the set of valid types for `z`. 1359 Each node in this interpretation DAG is given a cost the same way it would be 1360 in the bottom-up approach, with the exception that when going top-down there 1361 must be a final bottom-up pass to sum the interpretation costs and sort them 1362 as appropriate. 1363 1364 If a parameter type for some `f` is a polymorphic type variable that is left 1365 unbound by the return type (e.g. `forall(otype S) int f(S x, int y)`), the 1366 matching arguments should be found using the bottom-up algorithm above for 1367 untyped contexts, because the polymorphic type variable does not sufficiently 1368 constrain the available interpretations of the argument expression. 1369 Similarly, it would likely be an advantage to use top-down resolution for 1370 cast expressions (e.g. `(int)x`), even when those cast expressions are 1371 subexpressions of an otherwise untyped expression. 1372 It may also be fruitful to switch between the bottom-up and top-down 1373 algorithms if the number of valid interpretations for a subexpression or valid 1374 types for an argument exceeds some heuristic threshold, but finding such 1375 a threshold (if any exists) will require experimental data. 1376 This hybrid top-down/bottom-up search provides more opportunities for pruning 1377 interpretations than either a bottom-up or top-down approach alone, and thus 1378 may be more efficient than either. 1379 A top-down-only approach, however, devolves to linear search through every 1380 possible interpretation in the solution space in an untyped context, and is 1381 thus likely to be inferior to a strictly bottom-up approach, though this 1382 hypothesis needs to be empirically validated. 1383 1384 Both Baker and Cormack explicitly generate all possible interpretations of a 1385 given expression; thinking of the set of interpretations of an expression as a 1386 list sorted by cost, this is an eager evaluation of the list. 1387 However, since we generally expect that user programmers will not often use 1388 high-cost implicit conversions, one potentially effective way to prune the 1389 search space would be to first find the minimal-cost interpretations of any 1390 given subexpression, then to save the resolution progress of the 1391 subexpressions and attempt to resolve the superexpression using only those 1392 subexpression interpretations. 1393 If no valid interpretation of the superexpression can be found, the resolver 1394 would then repeatedly find the next-most-minimal cost interpretations of the 1395 subexpressions and attempt to produce the minimal cost interpretation of the 1396 superexpression. 1397 This process would proceed until all possible subexpression interpretations 1398 have been found and considered. 1399 1400 A middle ground between the eager and lazy approaches can be taken by 1401 considering the lexical order on the cost tuple; essentially, every 1402 interpretation in each of the classes below will be strictly cheaper than any 1403 interpretation in the class after it, so if a min-cost valid interpretation 1404 can be found while only generating interpretations in a given class, that 1405 interpretation is guaranteed to be the best possible one: 1406 1407 1. Interpretations without polymorphic functions or implicit conversions 1408 2. Interpretations without polymorphic functions using only safe conversions 1409 3. Interpretations using polymorphic functions without unsafe conversions 1410 4. Interpretations using unsafe conversions 1411 1412 In this lazy-eager approach, all the interpretations in one class would be 1413 eagerly generated, while the interpretations in the next class would only be 1414 considered if no match was found in the previous class. 1415 1226 1416 ## Appendix A: Partial and Total Orders ## 1227 1417 The `<=` relation on integers is a commonly known _total order_, and -
src/ArgTweak/FunctionFixer.cc
re04ef3a rc8c03683 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FunctionFixer.cc -- 7 // FunctionFixer.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 42 42 Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr ) throw ( SemanticError ) { 43 43 assert( untypedExpr != 0 ); 44 NameExpr *function;45 44 46 if ( ( function = dynamic_cast< NameExpr *>(untypedExpr->get_function()) ) != 0) {45 if ( NameExpr * function = dynamic_cast< NameExpr *>(untypedExpr->get_function() ) ) { 47 46 std::list < DeclarationWithType * > options; 48 47 index->lookupId ( function->get_name(), options ); 49 48 for ( std::list < DeclarationWithType * >::iterator i = options.begin(); i != options.end(); i++ ) { 50 FunctionType *f; 51 if ( ( f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) ) != 0 ) { 49 if ( FunctionType * f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) ) { 52 50 std::list < DeclarationWithType * > &pars = f->get_parameters(); 53 54 51 bool candidateExists ; 55 for ( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ ) 52 for ( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ ) { 56 53 if ( ( candidateExists = align( f->get_parameters(), untypedExpr->get_args(), Matcher() ) ) ) break; 57 54 } 58 55 if ( ! candidateExists ) throw SemanticError("Error in function call"); 59 56 } // if -
src/CodeGen/CodeGenerator.cc
re04ef3a rc8c03683 26 26 #include "SynTree/Statement.h" 27 27 #include "SynTree/Type.h" 28 #include "SynTree/Attribute.h" 28 29 29 30 #include "Common/utility.h" … … 33 34 #include "OperatorTable.h" 34 35 #include "GenType.h" 36 37 #include "InitTweak/InitTweak.h" 35 38 36 39 using namespace std; … … 74 77 } 75 78 79 void CodeGenerator::genAttributes( std::list< Attribute * > & attributes ) { 80 if ( ! attributes.empty() ) { 81 output << "__attribute__ (("; 82 for ( Attribute *& attr : attributes ) { 83 if ( ! attr->empty() ) { 84 output << attr->get_name() << "("; 85 genCommaList( attr->get_parameters().begin(), attr->get_parameters().end() ); 86 output << ")"; 87 } 88 output << ","; 89 } 90 output << ")) "; 91 } 92 } 93 94 76 95 //*** Declarations 77 96 void CodeGenerator::visit( FunctionDecl *functionDecl ) { 78 // generalize this 79 FunctionDecl::Attribute attr = functionDecl->get_attribute(); 80 switch ( attr.type ) { 81 case FunctionDecl::Attribute::Constructor: 82 output << "__attribute__ ((constructor"; 83 if ( attr.priority != FunctionDecl::Attribute::Default ) { 84 output << "(" << attr.priority << ")"; 85 } 86 output << ")) "; 87 break; 88 case FunctionDecl::Attribute::Destructor: 89 output << "__attribute__ ((destructor"; 90 if ( attr.priority != FunctionDecl::Attribute::Default ) { 91 output << "(" << attr.priority << ")"; 92 } 93 output << ")) "; 94 break; 95 default: 96 break; 97 } 97 genAttributes( functionDecl->get_attributes() ); 98 98 99 handleStorageClass( functionDecl ); 99 100 if ( functionDecl->get_isInline() ) { … … 270 271 UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) ); 271 272 newExpr->get_args().push_back( *arg ); 273 assert( (*arg)->get_results().size() == 1 ); 274 Type * type = InitTweak::getPointerBase( (*arg)->get_results().front() ); 275 assert( type ); 276 newExpr->get_results().push_back( type ); 272 277 *arg = newExpr; 273 278 } // if … … 298 303 if ( applicationExpr->get_args().size() == 1 ) { 299 304 // the expression fed into a single parameter constructor or destructor 300 // may contain side effects - output as a voidexpression301 output << "( (void)(";305 // may contain side effects, so must still output this expression 306 output << "("; 302 307 (*arg++)->accept( *this ); 303 output << ") )/* " << opInfo.inputName << " */";308 output << ") /* " << opInfo.inputName << " */"; 304 309 } else if ( applicationExpr->get_args().size() == 2 ) { 305 310 // intrinsic two parameter constructors are essentially bitwise assignment … … 384 389 if ( untypedExpr->get_args().size() == 1 ) { 385 390 // the expression fed into a single parameter constructor or destructor 386 // may contain side effects - output as a voidexpression387 output << "( (void)(";391 // may contain side effects, so must still output this expression 392 output << "("; 388 393 (*arg++)->accept( *this ); 389 output << ") )/* " << opInfo.inputName << " */";394 output << ") /* " << opInfo.inputName << " */"; 390 395 } else if ( untypedExpr->get_args().size() == 2 ) { 391 396 // intrinsic two parameter constructors are essentially bitwise assignment … … 626 631 627 632 void CodeGenerator::visit( ExprStmt *exprStmt ) { 628 // I don't see why this check is necessary.629 // If this starts to cause problems then put it back in,630 // with an explanation631 633 assert( exprStmt ); 632 633 // if ( exprStmt != 0 ) { 634 exprStmt->get_expr()->accept( *this ); 635 output << ";" ; 636 // } // if 634 // cast the top-level expression to void to reduce gcc warnings. 635 Expression * expr = new CastExpr( exprStmt->get_expr() ); 636 expr->accept( *this ); 637 output << ";"; 637 638 } 638 639 … … 743 744 744 745 void CodeGenerator::visit( WhileStmt *whileStmt ) { 745 if ( whileStmt->get_isDoWhile() ) 746 if ( whileStmt->get_isDoWhile() ) { 746 747 output << "do" ; 747 else {748 } else { 748 749 output << "while (" ; 749 750 whileStmt->get_condition()->accept( *this ); … … 769 770 output << "for (;"; 770 771 771 if ( forStmt->get_condition() != 0 ) 772 if ( forStmt->get_condition() != 0 ) { 772 773 forStmt->get_condition()->accept( *this ); 774 } 773 775 output << ";"; 774 776 775 if ( forStmt->get_increment() != 0 ) 776 forStmt->get_increment()->accept( *this ); 777 if ( forStmt->get_increment() != 0 ) { 778 // cast the top-level expression to void to reduce gcc warnings. 779 Expression * expr = new CastExpr( forStmt->get_increment() ); 780 expr->accept( *this ); 781 } 777 782 output << ") "; 778 783 -
src/CodeGen/CodeGenerator.h
re04ef3a rc8c03683 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // CodeGenerator.h -- 7 // CodeGenerator.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 60 60 virtual void visit( MemberExpr *memberExpr ); 61 61 virtual void visit( VariableExpr *variableExpr ); 62 virtual void visit( ConstantExpr *constantExpr ); 62 virtual void visit( ConstantExpr *constantExpr ); 63 63 virtual void visit( SizeofExpr *sizeofExpr ); 64 64 virtual void visit( AlignofExpr *alignofExpr ); … … 85 85 virtual void visit( ForStmt * ); 86 86 virtual void visit( NullStmt * ); 87 virtual void visit( DeclStmt * ); 87 virtual void visit( DeclStmt * ); 88 89 void genAttributes( std::list< Attribute * > & attributes ); 88 90 89 91 template< class Iterator > void genCommaList( Iterator begin, Iterator end ); … … 114 116 115 117 }; 116 118 117 119 template< class Iterator > 118 120 void CodeGenerator::genCommaList( Iterator begin, Iterator end ) { … … 125 127 } // for 126 128 } 127 129 128 130 inline bool doSemicolon( Declaration* decl ) { 129 131 if ( FunctionDecl* func = dynamic_cast< FunctionDecl* >( decl ) ) { -
src/GenPoly/Box.cc
re04ef3a rc8c03683 1947 1947 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); 1948 1948 derefExpr->get_args().push_back( derefdVar ); 1949 // xxx - should set results on derefExpr 1949 1950 derefdVar = derefExpr; 1950 1951 } -
src/GenPoly/Specialize.cc
re04ef3a rc8c03683 25 25 #include "SynTree/Statement.h" 26 26 #include "SynTree/Type.h" 27 #include "SynTree/Attribute.h" 27 28 #include "SynTree/TypeSubstitution.h" 28 29 #include "SynTree/Mutator.h" … … 101 102 thunkFunc->fixUniqueId(); 102 103 104 // thunks may be generated and not used - silence warning with attribute 105 thunkFunc->get_attributes().push_back( new Attribute( "unused" ) ); 106 103 107 // thread thunk parameters into call to actual function, naming thunk parameters as we go 104 108 UniqueName paramNamer( paramPrefix ); -
src/InitTweak/FixGlobalInit.cc
re04ef3a rc8c03683 22 22 #include "SynTree/Initializer.h" 23 23 #include "SynTree/Visitor.h" 24 #include "SynTree/Attribute.h" 24 25 #include <algorithm> 25 26 … … 116 117 GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) { 117 118 std::string fixedName = globalFunctionName( name ); 118 initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Constructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) ); 119 120 destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Destructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) ); 119 std::list< Expression * > ctorParameters; 120 std::list< Expression * > dtorParameters; 121 if ( inLibrary ) { 122 // Constructor/destructor attributes take a single parameter which 123 // is the priority, with lower numbers meaning higher priority. 124 // Functions specified with priority are guaranteed to run before 125 // functions without a priority. To ensure that constructors and destructors 126 // for library code are run before constructors and destructors for user code, 127 // specify a priority when building the library. Priorities 0-100 are reserved by gcc. 128 ctorParameters.push_back( new ConstantExpr( Constant::from_int( 101 ) ) ); 129 dtorParameters.push_back( new ConstantExpr( Constant::from_int( 101 ) ) ); 130 } 131 initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 132 initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) ); 133 destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 134 destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) ); 121 135 } 122 136 … … 125 139 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids(); 126 140 127 // if ( objDecl->get_init() == NULL ) return;128 141 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects 129 if ( objDecl->get_type()->get_isConst() ) return; // temporary: can't assign to a const variable130 142 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return; 131 143 // C allows you to initialize objects with constant expressions … … 146 158 init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 147 159 init->get_args().push_back( new VariableExpr( newObj ) ); 148 initStatements.push_back( new ExprStmt( noLabels, init) );160 initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) ); 149 161 150 162 // add destructor calls to global destroy function 151 163 UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) ); 152 164 destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 153 destroyStatements.push_front( new ExprStmt( noLabels, destroy) );165 destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) ); 154 166 } 155 167 } -
src/InitTweak/FixInit.cc
re04ef3a rc8c03683 132 132 return appExpr; 133 133 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 134 // FunctionType * ftype = funcDecl->get_functionType();135 134 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 136 135 assert( ftype ); -
src/InitTweak/GenInit.cc
re04ef3a rc8c03683 164 164 assert( ctor.size() == 1 ); 165 165 assert( dtor.size() == 1 ); 166 167 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 166 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctor.front() ), new ImplicitCtorDtorStmt( dtor.front() ), objDecl->get_init() ) ); 168 167 } else { 169 168 // array came with an initializer list: initialize each element … … 185 184 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 186 185 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 187 objDecl->set_init( new ConstructorInit( ctorStmt, dtorStmt, objDecl->get_init() ) );186 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 188 187 } 189 188 } -
src/InitTweak/InitTweak.cc
re04ef3a rc8c03683 7 7 8 8 namespace InitTweak { 9 10 11 12 13 14 15 16 17 18 19 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 }; 21 21 22 23 24 25 26 27 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 }; 29 29 30 31 32 30 void InitExpander::visit( SingleInit * singleInit ) { 31 argList.push_back( singleInit->get_value()->clone() ); 32 } 33 33 34 35 36 37 38 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 } 42 42 43 44 45 46 47 43 std::list< Expression * > makeInitList( Initializer * init ) { 44 InitExpander expander; 45 maybeAccept( init, expander ); 46 return expander.argList; 47 } 48 48 49 50 51 52 53 49 bool isDesignated( Initializer * init ) { 50 HasDesignations finder; 51 maybeAccept( init, finder ); 52 return finder.hasDesignations; 53 } 54 54 55 56 57 58 59 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 } 61 61 62 bool isInstrinsicSingleArgCallStmt( Statement * stmt ) { 63 if ( stmt == NULL ) return false; 64 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) { 65 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( exprStmt->get_expr() ); 66 assert( appExpr ); 67 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 68 assert( function ); 69 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 70 // will call all member dtors, and some members may have a user defined dtor. 71 FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() ); 72 assert( funcType ); 73 return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1; 74 } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) { 75 // could also be a compound statement with a loop, in the case of an array 76 assert( compoundStmt->get_kids().size() == 2 ); // loop variable and loop 77 ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() ); 78 assert( forStmt && forStmt->get_body() ); 79 return isInstrinsicSingleArgCallStmt( forStmt->get_body() ); 80 } else { 81 // should never get here 82 assert( false && "encountered unknown call statement" ); 83 } 84 } 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 } 79 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 } 93 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 } 105 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 } 115 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 } 129 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 } 139 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 } 149 150 Type * isPointerType( Type * type ) { 151 if ( getPointerBase( type ) ) return type; 152 else return NULL; 153 } 85 154 } -
src/InitTweak/InitTweak.h
re04ef3a rc8c03683 39 39 /// Currently has assertions that make it less than fully general. 40 40 bool isInstrinsicSingleArgCallStmt( Statement * expr ); 41 42 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call 43 Expression * getCtorDtorCall( Statement * stmt ); 44 45 /// returns the name of the function being called 46 std::string getFunctionName( Expression * expr ); 47 48 /// returns the argument to a call expression in position N indexed from 0 49 Expression *& getCallArg( Expression * callExpr, unsigned int pos ); 50 51 /// returns the base type of a PointerType or ArrayType, else returns NULL 52 Type * getPointerBase( Type * ); 53 54 /// returns the argument if it is a PointerType or ArrayType, else returns NULL 55 Type * isPointerType( Type * ); 41 56 } // namespace 42 57 -
src/Makefile.in
re04ef3a rc8c03683 195 195 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \ 196 196 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \ 197 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \ 197 198 Tuples/driver_cfa_cpp-Mutate.$(OBJEXT) \ 198 199 Tuples/driver_cfa_cpp-AssignExpand.$(OBJEXT) \ … … 411 412 SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \ 412 413 SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \ 413 SynTree/TypeSubstitution.cc Tuples/Mutate.cc \414 Tuples/ AssignExpand.cc Tuples/FunctionFixer.cc \415 Tuples/ TupleAssignment.cc Tuples/FunctionChecker.cc \416 Tuples/ NameMatcher.cc414 SynTree/TypeSubstitution.cc SynTree/Attribute.cc \ 415 Tuples/Mutate.cc Tuples/AssignExpand.cc \ 416 Tuples/FunctionFixer.cc Tuples/TupleAssignment.cc \ 417 Tuples/FunctionChecker.cc Tuples/NameMatcher.cc 417 418 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \ 418 419 ${cfa_cpplib_PROGRAMS}} … … 783 784 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT): \ 784 785 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) 786 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \ 787 SynTree/$(DEPDIR)/$(am__dirstamp) 785 788 Tuples/$(am__dirstamp): 786 789 @$(MKDIR_P) Tuples … … 880 883 -rm -f SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT) 881 884 -rm -f SynTree/driver_cfa_cpp-AttrType.$(OBJEXT) 885 -rm -f SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) 882 886 -rm -f SynTree/driver_cfa_cpp-BasicType.$(OBJEXT) 883 887 -rm -f SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT) … … 989 993 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po@am__quote@ 990 994 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Po@am__quote@ 995 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po@am__quote@ 991 996 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po@am__quote@ 992 997 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po@am__quote@ … … 2424 2429 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2425 2430 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeSubstitution.obj `if test -f 'SynTree/TypeSubstitution.cc'; then $(CYGPATH_W) 'SynTree/TypeSubstitution.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeSubstitution.cc'; fi` 2431 2432 SynTree/driver_cfa_cpp-Attribute.o: SynTree/Attribute.cc 2433 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc 2434 @am__fastdepCXX_TRUE@ $(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po 2435 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.o' libtool=no @AMDEPBACKSLASH@ 2436 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2437 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc 2438 2439 SynTree/driver_cfa_cpp-Attribute.obj: SynTree/Attribute.cc 2440 @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi` 2441 @am__fastdepCXX_TRUE@ $(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po 2442 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.obj' libtool=no @AMDEPBACKSLASH@ 2443 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2444 @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi` 2426 2445 2427 2446 Tuples/driver_cfa_cpp-Mutate.o: Tuples/Mutate.cc -
src/ResolvExpr/AlternativeFinder.cc
re04ef3a rc8c03683 39 39 #include "Tuples/NameMatcher.h" 40 40 #include "Common/utility.h" 41 #include "InitTweak/InitTweak.h" 41 42 42 43 extern bool resolvep; … … 546 547 547 548 { 548 NameExpr *fname = 0;; 549 if ( ( fname = dynamic_cast<NameExpr *>( untypedExpr->get_function())) 550 && ( fname->get_name() == std::string("&&")) ) { 549 std::string fname = InitTweak::getFunctionName( untypedExpr ); 550 if ( fname == "&&" ) { 551 551 VoidType v = Type::Qualifiers(); // resolve to type void * 552 552 PointerType pt( Type::Qualifiers(), v.clone() ); -
src/ResolvExpr/CommonType.cc
re04ef3a rc8c03683 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // CommonType.cc -- 7 // CommonType.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 134 134 result = new BasicType( basicType->get_qualifiers() + otherBasic->get_qualifiers(), newType ); 135 135 } // if 136 } else if ( EnumInstType *enumInstType = dynamic_cast< EnumInstType * > ( type2 ) ) { 137 // use signed int in lieu of the enum type 138 BasicType::Kind newType = combinedType[ basicType->get_kind() ][ BasicType::SignedInt ]; 139 if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= enumInstType->get_qualifiers() ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->get_qualifiers() <= enumInstType->get_qualifiers() ) || widenSecond ) ) { 140 result = new BasicType( basicType->get_qualifiers() + enumInstType->get_qualifiers(), newType ); 141 } // if 136 142 } // if 137 143 } … … 183 189 } 184 190 185 void CommonType::visit( EnumInstType *aggregateUseType ) { 191 void CommonType::visit( EnumInstType *enumInstType ) { 192 if ( dynamic_cast< BasicType * >( type2 ) ) { 193 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 194 Type * temp = type2; 195 type2 = enumInstType; 196 temp->accept( *this ); 197 type2 = temp; 198 } // if 186 199 } 187 200 -
src/ResolvExpr/ConversionCost.cc
re04ef3a rc8c03683 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ConversionCost.cc -- 7 // ConversionCost.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 157 157 cost = Cost( 0, 0, tableResult ); 158 158 } // if 159 } // if 159 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 160 // xxx - not positive this is correct, but appears to allow casting int => enum 161 cost = Cost( 1, 0, 0 ); 162 } // if 160 163 } 161 164 -
src/ResolvExpr/Resolver.cc
re04ef3a rc8c03683 38 38 virtual void visit( ObjectDecl *functionDecl ); 39 39 virtual void visit( TypeDecl *typeDecl ); 40 virtual void visit( EnumDecl * enumDecl ); 40 41 41 42 virtual void visit( ArrayType * at ); … … 52 53 virtual void visit( BranchStmt *branchStmt ); 53 54 virtual void visit( ReturnStmt *returnStmt ); 55 virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ); 54 56 55 57 virtual void visit( SingleInit *singleInit ); … … 65 67 Type *initContext; 66 68 Type *switchType; 69 bool inEnumDecl = false; 67 70 }; 68 71 … … 177 180 Type *temp = initContext; 178 181 initContext = new_type; 182 if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) { 183 // enumerator initializers should not use the enum type to initialize, since 184 // the enum type is still incomplete at this point. Use signed int instead. 185 initContext = new BasicType( Type::Qualifiers(), BasicType::SignedInt ); 186 } 179 187 SymTab::Indexer::visit( objectDecl ); 188 if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) { 189 // delete newly created signed int type 190 delete initContext; 191 } 180 192 initContext = temp; 181 193 } … … 215 227 SymTab::Indexer::visit( functionDecl ); 216 228 functionReturn = oldFunctionReturn; 229 } 230 231 void Resolver::visit( EnumDecl * enumDecl ) { 232 // in case we decide to allow nested enums 233 bool oldInEnumDecl = inEnumDecl; 234 inEnumDecl = true; 235 SymTab::Indexer::visit( enumDecl ); 236 inEnumDecl = oldInEnumDecl; 217 237 } 218 238 … … 492 512 } catch ( SemanticError ) { 493 513 // no alternatives for the constructor initializer - fallback on C-style initializer 494 // xxx - not sure if this makes a ton of sense - should maybe never be able to have this situation?514 // xxx - not sure if this makes a ton of sense - should maybe never be able to have this situation? 495 515 fallbackInit( ctorInit ); 496 516 return; … … 513 533 } 514 534 } 535 536 void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) { 537 // before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed). 538 // Do this through a cast expression to greatly simplify the code. 539 Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt ); 540 assert( callExpr ); 541 Expression *& constructee = InitTweak::getCallArg( callExpr, 0 ); 542 Type * type = 0; 543 544 // need to find the type of the first argument, which is unfortunately not uniform since array construction 545 // includes an untyped '+' expression. 546 if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) { 547 // constructee is <array>+<index> 548 // get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed 549 Expression * arr = InitTweak::getCallArg( plusExpr, 0 ); 550 assert( dynamic_cast< VariableExpr * >( arr ) ); 551 assert( arr && arr->get_results().size() == 1 ); 552 type = arr->get_results().front()->clone(); 553 } else { 554 // otherwise, constructing a plain object, which means the object's address is being taken. 555 // Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the 556 // type of the VariableExpr to do so. 557 assert( constructee->get_results().size() == 1 ); 558 AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee ); 559 assert( addrExpr && addrExpr->get_results().size() == 1); 560 type = addrExpr->get_results().front()->clone(); 561 } 562 // cast to T* with qualifiers removed. 563 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 564 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 565 // remove lvalue as a qualifier, this can change to 566 // type->get_qualifiers() = Type::Qualifiers(); 567 Type * base = InitTweak::getPointerBase( type ); 568 assert( base ); 569 base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 570 // if pointer has lvalue qualifier, cast won't appear in output 571 type->set_isLvalue( false ); 572 constructee = new CastExpr( constructee, type ); 573 574 // finally, resolve the ctor/dtor 575 impCtorDtorStmt->get_callStmt()->accept( *this ); 576 } 515 577 } // namespace ResolvExpr 516 578 -
src/SymTab/Autogen.cc
re04ef3a rc8c03683 102 102 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 103 103 104 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 ); 105 assignType->get_parameters().push_back( dstParam ); 106 107 // void ?{}(E *); void ^?{}(E *); 108 FunctionType * ctorType = assignType->clone(); 109 FunctionType * dtorType = assignType->clone(); 110 111 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 ); 112 assignType->get_parameters().push_back( srcParam ); 113 // void ?{}(E *, E); 114 FunctionType *copyCtorType = assignType->clone(); 115 116 // T ?=?(E *, E); 104 117 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 ); 105 118 assignType->get_returnVals().push_back( returnVal ); 106 119 107 // need two assignment operators with different types 108 FunctionType * assignType2 = assignType->clone(); 109 110 // E ?=?(E volatile *, E) 111 Type *etype = refType->clone(); 112 // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false); 113 114 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 ); 115 assignType->get_parameters().push_back( dstParam ); 116 117 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 ); 118 assignType->get_parameters().push_back( srcParam ); 119 120 // E ?=?(E volatile *, int) 121 assignType2->get_parameters().push_back( dstParam->clone() ); 122 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt); 123 ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 ); 124 assignType2->get_parameters().push_back( srcParam2 ); 120 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 121 // right now these cases work, but that might change. 125 122 126 123 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 127 124 // because each unit generates copies of the default routines for each aggregate. 128 129 // since there is no definition, these should not be inline 130 // make these intrinsic so that the code generator does not make use of them 131 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false ); 125 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment. 126 // Really they're something of a cross between instrinsic and autogen, so should 127 // probably make a new linkage type 128 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false ); 129 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false ); 130 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false ); 131 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false ); 132 132 assignDecl->fixUniqueId(); 133 FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false ); 134 assignDecl2->fixUniqueId(); 135 136 // these should be built in the same way that the prelude 137 // functions are, so build a list containing the prototypes 138 // and allow MakeLibCfa to autogenerate the bodies. 139 std::list< Declaration * > assigns; 140 assigns.push_back( assignDecl ); 141 assigns.push_back( assignDecl2 ); 142 143 LibCfa::makeLibCfa( assigns ); 144 145 // need to remove the prototypes, since this may be nested in a routine 146 for (int start = 0, end = assigns.size()/2; start < end; start++) { 147 delete assigns.front(); 148 assigns.pop_front(); 149 } // for 150 151 declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() ); 133 ctorDecl->fixUniqueId(); 134 copyCtorDecl->fixUniqueId(); 135 dtorDecl->fixUniqueId(); 136 137 // enum copy construct and assignment is just C-style assignment. 138 // this looks like a bad recursive call, but code gen will turn it into 139 // a C-style assignment. 140 // This happens before function pointer type conversion, so need to do it manually here 141 VariableExpr * assignVarExpr = new VariableExpr( assignDecl ); 142 Type *& assignVarExprType = assignVarExpr->get_results().front(); 143 assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType ); 144 ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr ); 145 assignExpr->get_args().push_back( new VariableExpr( dstParam ) ); 146 assignExpr->get_args().push_back( new VariableExpr( srcParam ) ); 147 148 // body is either return stmt or expr stmt 149 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) ); 150 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) ); 151 152 declsToAdd.push_back( assignDecl ); 153 declsToAdd.push_back( ctorDecl ); 154 declsToAdd.push_back( copyCtorDecl ); 155 declsToAdd.push_back( dtorDecl ); 152 156 } 153 157 … … 488 492 type->get_parameters().push_back( dst ); 489 493 type->get_parameters().push_back( src ); 490 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );494 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false ); 491 495 declsToAdd.push_back( func ); 492 496 } -
src/SymTab/Validate.cc
re04ef3a rc8c03683 279 279 void Pass1::visit( EnumDecl *enumDecl ) { 280 280 // Set the type of each member of the enumeration to be EnumConstant 281 282 281 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) { 283 282 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i ); 284 283 assert( obj ); 285 // obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) ); 286 BasicType * enumType = new BasicType( Type::Qualifiers(), BasicType::SignedInt ); 287 obj->set_type( enumType ) ; 284 obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) ); 288 285 } // for 289 286 Parent::visit( enumDecl ); -
src/SynTree/Declaration.h
re04ef3a rc8c03683 115 115 typedef DeclarationWithType Parent; 116 116 public: 117 // temporary - merge this into general GCC attributes 118 struct Attribute { 119 enum Type { 120 NoAttribute, Constructor, Destructor, 121 } type; 122 enum Priority { 123 // priorities 0-100 are reserved by gcc, so it's okay to use 100 an exceptional case 124 Default = 100, High, 125 } priority; 126 Attribute(Type t = NoAttribute, Priority p = Default) : type(t), priority(p) {}; 127 }; 128 129 FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute = Attribute() ); 117 FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, const std::list< Attribute * > attributes = std::list< Attribute * >() ); 130 118 FunctionDecl( const FunctionDecl &other ); 131 119 virtual ~FunctionDecl(); … … 140 128 std::list< std::string >& get_oldIdents() { return oldIdents; } 141 129 std::list< Declaration* >& get_oldDecls() { return oldDecls; } 142 Attribute get_attribute() const { return attribute; } 143 void set_attribute( Attribute newValue ) { attribute = newValue; } 130 std::list< Attribute * >& get_attributes() { return attributes; } 144 131 145 132 virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); } … … 153 140 std::list< std::string > oldIdents; 154 141 std::list< Declaration* > oldDecls; 155 Attribute attribute;142 std::list< Attribute * > attributes; 156 143 }; 157 144 -
src/SynTree/FunctionDecl.cc
re04ef3a rc8c03683 19 19 #include "Statement.h" 20 20 #include "Type.h" 21 #include "Attribute.h" 21 22 #include "Common/utility.h" 22 23 23 FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute)24 : Parent( name, sc, linkage ), type( type ), statements( statements ), attribute ( attribute) {24 FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes ) 25 : Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) { 25 26 set_isInline( isInline ); 26 27 set_isNoreturn( isNoreturn ); … … 32 33 33 34 FunctionDecl::FunctionDecl( const FunctionDecl &other ) 34 : Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ), attribute( other.attribute ) { 35 : Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) { 36 cloneAll( other.attributes, attributes ); 35 37 } 36 38 … … 38 40 delete type; 39 41 delete statements; 42 deleteAll( attributes ); 40 43 } 41 44 … … 65 68 os << "_Noreturn "; 66 69 } // if 67 switch ( attribute.type ) { 68 case Attribute::Constructor: 69 os << "Global Constructor "; 70 break; 71 case Attribute::Destructor: 72 os << "Global Destructor "; 73 break; 74 default: 75 break; 76 } 77 if ( attribute.priority != Attribute::Default ) { 78 os << "with priority " << attribute.priority << " "; 79 } 70 71 printAll( attributes, os, indent ); 72 80 73 if ( get_storageClass() != DeclarationNode::NoStorageClass ) { 81 74 os << DeclarationNode::storageName[ get_storageClass() ] << ' '; … … 118 111 os << "_Noreturn "; 119 112 } // if 120 switch ( attribute.type ) { 121 case Attribute::Constructor: 122 os << " Global Constructor "; 123 break; 124 case Attribute::Destructor: 125 os << " Global Destructor "; 126 break; 127 default: 128 break; 129 } 130 if ( attribute.priority != Attribute::Default ) { 131 os << "with priority " << attribute.priority << " "; 132 } 113 114 // xxx - should printShort print attributes? 115 133 116 if ( get_storageClass() != DeclarationNode::NoStorageClass ) { 134 117 os << DeclarationNode::storageName[ get_storageClass() ] << ' '; -
src/SynTree/Initializer.cc
re04ef3a rc8c03683 20 20 21 21 Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {} 22 Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) { 23 } 24 22 25 23 26 Initializer::~Initializer() {} … … 39 42 } 40 43 41 SingleInit::~SingleInit() { }42 43 SingleInit *SingleInit::clone() const { return new SingleInit( *this);}44 SingleInit::~SingleInit() { 45 deleteAll(designators); 46 } 44 47 45 48 void SingleInit::print( std::ostream &os, int indent ) { … … 58 61 59 62 ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed ) 60 : Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) {63 : Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) { 61 64 } 62 65 63 ListInit::~ListInit() {} 64 65 ListInit *ListInit::clone() const { 66 return new ListInit( *this ); 66 ListInit::~ListInit() { 67 deleteAll( initializers ); 68 deleteAll( designators ); 67 69 } 68 70 … … 85 87 86 88 ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {} 89 ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) { 90 } 91 87 92 ConstructorInit::~ConstructorInit() { 88 93 delete ctor; 94 delete dtor; 89 95 delete init; 90 }91 92 ConstructorInit *ConstructorInit::clone() const {93 return new ConstructorInit( *this );94 96 } 95 97 -
src/SynTree/Initializer.h
re04ef3a rc8c03683 20 20 #include "Visitor.h" 21 21 #include "Mutator.h" 22 #include "Type.h" 22 23 23 24 #include <cassert> … … 28 29 // Initializer( std::string _name = std::string(""), int _pos = 0 ); 29 30 Initializer( bool maybeConstructed ); 31 Initializer( const Initializer & other ); 30 32 virtual ~Initializer(); 31 33 … … 68 70 std::list<Expression *> &get_designators() { return designators; } 69 71 70 virtual SingleInit *clone() const ;72 virtual SingleInit *clone() const { return new SingleInit( *this); } 71 73 virtual void accept( Visitor &v ) { v.visit( this ); } 72 74 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); } … … 94 96 std::list<Initializer*>::iterator end_initializers() { return initializers.end(); } 95 97 96 virtual ListInit *clone() const ;98 virtual ListInit *clone() const { return new ListInit( *this ); } 97 99 virtual void accept( Visitor &v ) { v.visit( this ); } 98 100 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); } … … 108 110 public: 109 111 ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ); 112 ConstructorInit( const ConstructorInit &other ); 110 113 virtual ~ConstructorInit(); 111 114 … … 117 120 Initializer * get_init() const { return init; } 118 121 119 virtual ConstructorInit *clone() const;122 ConstructorInit *clone() const { return new ConstructorInit( *this ); } 120 123 virtual void accept( Visitor &v ) { v.visit( this ); } 121 124 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); } -
src/SynTree/Mutator.cc
re04ef3a rc8c03683 182 182 } 183 183 184 Statement *Mutator::mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ) { 185 impCtorDtorStmt->set_callStmt( maybeMutate( impCtorDtorStmt->get_callStmt(), *this ) ); 186 return impCtorDtorStmt; 187 } 188 184 189 Expression *Mutator::mutate( ApplicationExpr *applicationExpr ) { 185 190 mutateAll( applicationExpr->get_results(), *this ); -
src/SynTree/Mutator.h
re04ef3a rc8c03683 52 52 virtual NullStmt* mutate( NullStmt *nullStmt ); 53 53 virtual Statement* mutate( DeclStmt *declStmt ); 54 virtual Statement* mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ); 54 55 55 56 virtual Expression* mutate( ApplicationExpr *applicationExpr ); -
src/SynTree/Statement.cc
re04ef3a rc8c03683 358 358 359 359 void CatchStmt::print( std::ostream &os, int indent ) const { 360 os << string( indent, ' ' ) <<"Catch Statement" << endl;360 os << "Catch Statement" << endl; 361 361 362 362 os << string( indent, ' ' ) << "... catching" << endl; … … 383 383 384 384 void FinallyStmt::print( std::ostream &os, int indent ) const { 385 os << string( indent, ' ' ) <<"Finally Statement" << endl;385 os << "Finally Statement" << endl; 386 386 os << string( indent + 2, ' ' ) << "with block: " << endl; 387 387 block->print( os, indent + 4 ); … … 393 393 void NullStmt::print( std::ostream &os, int indent ) const { 394 394 os << "Null Statement" << endl ; 395 } 396 397 ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement( std::list<Label>() ), callStmt( callStmt ) { 398 assert( callStmt ); 399 } 400 401 ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ) : Statement( other ), callStmt( other.callStmt ) { 402 } 403 404 ImplicitCtorDtorStmt::~ImplicitCtorDtorStmt() { 405 } 406 407 void ImplicitCtorDtorStmt::print( std::ostream &os, int indent ) const { 408 os << "Implicit Ctor Dtor Statement" << endl; 409 os << string( indent + 2, ' ' ) << "with Ctor/Dtor: "; 410 callStmt->print( os, indent + 2); 411 os << endl; 395 412 } 396 413 -
src/SynTree/Statement.h
re04ef3a rc8c03683 21 21 #include "Mutator.h" 22 22 #include "Common/SemanticError.h" 23 #include "Type.h" 23 24 24 25 class Statement { … … 394 395 virtual ~DeclStmt(); 395 396 396 Declaration *get_decl() { return decl; }397 Declaration *get_decl() const { return decl; } 397 398 void set_decl( Declaration *newValue ) { decl = newValue; } 398 399 … … 404 405 Declaration *decl; 405 406 }; 407 408 409 /// represents an implicit application of a constructor or destructor. Qualifiers are replaced 410 /// immediately before and after the call so that qualified objects can be constructed 411 /// with the same functions as unqualified objects. 412 class ImplicitCtorDtorStmt : public Statement { 413 public: 414 ImplicitCtorDtorStmt( Statement * callStmt ); 415 ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ); 416 virtual ~ImplicitCtorDtorStmt(); 417 418 Statement *get_callStmt() const { return callStmt; } 419 void set_callStmt( Statement * newValue ) { callStmt = newValue; } 420 421 virtual ImplicitCtorDtorStmt *clone() const { return new ImplicitCtorDtorStmt( *this ); } 422 virtual void accept( Visitor &v ) { v.visit( this ); } 423 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); } 424 virtual void print( std::ostream &os, int indent = 0 ) const; 425 426 private: 427 // Non-owned pointer to the constructor/destructor statement 428 Statement * callStmt; 429 }; 430 406 431 407 432 std::ostream & operator<<( std::ostream & out, Statement * statement ); -
src/SynTree/SynTree.h
re04ef3a rc8c03683 56 56 class DeclStmt; 57 57 class NullStmt; 58 class ImplicitCtorDtorStmt; 58 59 59 60 class Expression; … … 117 118 class TypeSubstitution; 118 119 120 // gcc attribute 121 class Attribute; 122 119 123 #endif // SYNTREE_H 120 124 -
src/SynTree/Type.cc
re04ef3a rc8c03683 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Type.cc -- 7 // Type.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 54 54 } 55 55 56 void Type::Qualifiers::print( std::ostream &os, int indent ) const { 57 if ( isConst ) { 58 os << "const "; 59 } // if 60 if ( isVolatile ) { 61 os << "volatile "; 62 } // if 63 if ( isRestrict ) { 64 os << "restrict "; 65 } // if 66 if ( isLvalue ) { 67 os << "lvalue "; 68 } // if 69 if ( isAtomic ) { 70 os << "_Atomic "; 71 } // if 72 if ( isAttribute ) { 73 os << "__attribute(( )) "; 74 } // if 75 } 76 56 77 void Type::print( std::ostream &os, int indent ) const { 57 78 if ( ! forall.empty() ) { … … 60 81 os << std::string( indent+2, ' ' ); 61 82 } // if 62 if ( tq.isConst ) { 63 os << "const "; 64 } // if 65 if ( tq.isVolatile ) { 66 os << "volatile "; 67 } // if 68 if ( tq.isRestrict ) { 69 os << "restrict "; 70 } // if 71 if ( tq.isLvalue ) { 72 os << "lvalue "; 73 } // if 74 if ( tq.isAtomic ) { 75 os << "_Atomic "; 76 } // if 77 if ( tq.isAttribute ) { 78 os << "__attribute(( )) "; 79 } // if 83 tq.print( os, indent ); 80 84 } 81 85 -
src/SynTree/Type.h
re04ef3a rc8c03683 36 36 bool operator<( const Qualifiers &other ); 37 37 bool operator>( const Qualifiers &other ); 38 void print( std::ostream &os, int indent = 0 ) const; 38 39 39 40 bool isConst; -
src/SynTree/Visitor.cc
re04ef3a rc8c03683 152 152 } 153 153 154 void Visitor::visit( ImplicitCtorDtorStmt *impCtorDtorStmt ) { 155 maybeAccept( impCtorDtorStmt->get_callStmt(), *this ); 156 } 157 154 158 void Visitor::visit( ApplicationExpr *applicationExpr ) { 155 159 acceptAll( applicationExpr->get_results(), *this ); -
src/SynTree/Visitor.h
re04ef3a rc8c03683 52 52 virtual void visit( NullStmt *nullStmt ); 53 53 virtual void visit( DeclStmt *declStmt ); 54 virtual void visit( ImplicitCtorDtorStmt *impCtorDtorStmt ); 54 55 55 56 virtual void visit( ApplicationExpr *applicationExpr ); -
src/SynTree/module.mk
re04ef3a rc8c03683 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## module.mk -- 8 ## module.mk -- 9 9 ## 10 10 ## Author : Richard C. Bilson … … 46 46 SynTree/Visitor.cc \ 47 47 SynTree/Mutator.cc \ 48 SynTree/TypeSubstitution.cc 48 SynTree/TypeSubstitution.cc \ 49 SynTree/Attribute.cc 49 50 -
src/examples/avltree/avl-private.h
re04ef3a rc8c03683 1 #ifndef AVL_PRIVATE_H 1 2 #include "avl.h" 2 3 … … 13 14 forall(otype K | Comparable(K), otype V) 14 15 int height(tree(K, V) * t); 16 17 #endif
Note: See TracChangeset
for help on using the changeset viewer.