Changes in / [e04ef3a:c8c03683]


Ignore:
Files:
8 added
2 deleted
35 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    re04ef3a rc8c03683  
    3636
    3737def 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"
    4256}
    4357
     
    7488def collect_git_info() {
    7589
     90        //create the temporary output directory in case it doesn't already exist
    7691        def out_dir = pwd tmp: true
     92        sh "mkdir -p ${out_dir}"
     93
     94        //parse git logs to find what changed
    7795        gitRefName = env.BRANCH_NAME
    7896        dir("../${gitRefName}@script") {
     
    89107node ('master'){
    90108
     109        boolean doPromoteBuild2DoLang
    91110        def err = null
    92111        def log_needed = false
     
    113132                                        ]])
    114133
    115                                 echo "FULL BUILD = ${promoteBuild2DoLang}"
     134                                doPromoteBuild2DoLang = promoteBuild2DoLang == 'true'
     135
     136                                echo "FULL BUILD = ${doPromoteBuild2DoLang}"
    116137
    117138                                //Compile using gcc-4.9
     
    127148                                cfa_build()
    128149
    129                                 if(promote_build) {
     150                                if( doPromoteBuild2DoLang ) {
    130151                                        push_build()
    131152                                }
     
    149170        finally {
    150171                //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)
    152173
    153174                /* Must re-throw exception to propagate error */
     
    161182//Routine responsible of sending the email notification once the build is completed
    162183//===========================================================================================================
    163 def promote_email(boolean promote, boolean success, String status, boolean log) {
     184def notify_result(boolean promote, Exception err, String status, boolean log) {
    164185        if(promote)     {
    165                 if( !success ) {
     186                if( err ) {
    166187                        promote_email(status)
    167188                }
  • doc/bibliography/cfa.bib

    re04ef3a rc8c03683  
    356356}
    357357
    358 @article{Cor:overload,
     358@article{Cormack81,
    359359    keywords    = {},
    360360    contributer = {gjditchfield@plg},
     
    29222922    }
    29232923}
     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
    29242932
    29252933@article{Haskell,
     
    54555463% Q
    54565464
     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
    54575486@article{Hoare61,
    54585487    keywords    = {quick sort},
  • doc/working/resolver_design.md

    re04ef3a rc8c03683  
    8181
    8282## 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)`.
     83Each possible resolution of an expression has a _cost_ tuple consisting of
     84the following components: _unsafe_ conversion cost, _polymorphic_
     85specialization cost, _safe_ conversion cost, a count of _explicit_
     86conversions, and _qualifier_ conversion cost.
     87These components are lexically-ordered and can be summed element-wise;
     88summation starts at `(0, 0, 0, 0, 0)`.
    8889
    8990### Lvalue and Qualifier Conversions ###
     
    12241225programmers.
    12251226
     1227## Resolver Architecture ##
     1228
     1229### Function Application Resolution ###
     1230Our resolution algorithm for function application expressions is based on
     1231Baker's[3] single-pass bottom-up algorithm, with Cormack's[4] single-pass
     1232top-down algorithm applied where appropriate as an optimization.
     1233Broadly speaking, the cost of this resolution per expression will be
     1234proportional to `i^d`, where `i` is the number of interpretations of each
     1235program symbol, and `d` is the maximum depth of the expression DAG.
     1236Since `d` is determined by the user programmer (in general, bounded by a small
     1237constant), opportunities for resolver optimization primarily revolve around
     1238minimizing `i`, the number of interpretations of each symbol that are
     1239considered.
     1240
     1241[3] Baker, Theodore P. A one-pass algorithm for overload resolution in Ada.
     1242ACM 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
     1245in Ada. SIGPLAN Notices (1981) 16:2 p.48-52
     1246
     1247Unlike Baker, our system allows implicit type conversions for function
     1248arguments and return types; the problem then becomes to find the valid
     1249interpretation for an expression that has the unique minimal conversion cost,
     1250if such exists.
     1251Interpretations can be produced both by overloaded names and implicit
     1252conversions applied to existing interpretations; we have proposals to reduce
     1253the number of interpretations considered from both sources.
     1254To simplify the problem for this discussion, we will consider application
     1255resolution restricted to a domain of functions applied to variables, possibly
     1256in 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
     1258initialization (e.g. `int i = f( x );`); the other aspects of Cforall type
     1259resolution should be able to be straightforwardly mapped into this model.
     1260The types of the symbol tables used for variable and function declarations
     1261look 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`
     1275a 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
     1277as simple bags of typed declarations, where the declaration types are linked
     1278to the graph of available conversions for that type.
     1279In a typed context both the `variable_decl_set` and the `function_decl_set`
     1280should be able to be selected upon by type; this is accomplished by the
     1281`by_type` index of both `variable_map` and `function_map`.
     1282The `by_int` index of `function_map` also provides a way to select functions
     1283by their number of parameters; this index may be used to swiftly discard any
     1284function declaration which does not have the appropriate number of parameters
     1285for the argument interpretations being passed to it; given the likely small
     1286number of entries in this map, it is possible that a binary search of a sorted
     1287vector or even a linear search of an unsorted vector would be more efficient
     1288than the usual hash-based index.
     1289
     1290Given these data structures, the general outline of our algorithm follows
     1291Baker, with Cormack's algorithm used as a heuristic filter in typed contexts.
     1292
     1293In an untyped context, we use a variant of Baker's bottom-up algorithm.
     1294The leaves of the interpretation DAG are drawn from the variable symbol table,
     1295with entries in the table each producing zero-cost interpretations, and each
     1296implicit conversion available to be applied to the type of an existing entry
     1297producing a further interpretation with the same cost as the conversion.
     1298As in Baker, if two or more interpretations have the same type, only the
     1299minimum cost interpretation with that type is produced; if there is no unique
     1300minimum cost interpretation than resolution with that type is ambiguous, and
     1301not permitted.
     1302It should be relatively simple to produce the list of interpretations sorted
     1303by cost by producing the interpretations via a breadth-first search of the
     1304conversion graph from the initial interpretations provided in the variable
     1305symbol table.
     1306
     1307To match a function at one of the internal nodes of the DAG, we first look up
     1308the function's name in the function symbol table, the appropriate number of
     1309parameters for the arguments that are provided through the `by_int` index of
     1310the returned `function_map`, then go through the resulting `function_decl_set`
     1311searching for functions where the parameter types can unify with the provided
     1312argument lists; any such matching function produces an interpretation with a
     1313cost that is the sum of its argument costs.
     1314Though this is not included in our simplified model, this unification step may
     1315include binding of polymorphic variables, which introduces a cost for the
     1316function binding itself which must be added to the argument costs.
     1317Also, checking of function assertions would likely be done at this step as
     1318well, possibly eliminating some possible matching functions (if no suitable
     1319assertions can be satisfied), or adding further conversion costs for the
     1320assertion satisfaction.
     1321Once the set of valid function interpretations is produced, these may also be
     1322expanded by the graph of implicit conversions on their return types, as the
     1323variable interpretations were.
     1324
     1325This implicit conversion-based expansion of interpretations should be skipped
     1326for the top-level expression if used in an untyped (void) context, e.g. for
     1327`f` in `f( g ( x ) );` or `x` in `x;`.
     1328On 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
     1330relevant to the search, so the candidates for `f` can be filtered first by
     1331those that return `int` (or a type convertable to it); this can be
     1332accomplished by performing a top-down filter of the interpretations of `f` by
     1333the `by_type` index of the `function_map` in a manner similar to Cormack's[4]
     1334algorithm.
     1335
     1336In a typed context, such as an initialization expression
     1337`T x = f( g( y ), z );`, only interpretations of `f( g( y ), z )` which have
     1338type `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
     1340can use this information to reduce the number of interpretations considered.
     1341Drawing from Cormack[4], we first search for interpretations of `f` where the
     1342return type is `T`; by breadth-first-search of the conversion graph, it should
     1343be straightforward to order the interpretations of `f` by the cost to convert
     1344their return type to `T`.
     1345We can also filter out interpretations of `f` with less than two parameters,
     1346since both `g( y )` and `z` must produce at least one parameter; we may not,
     1347however, rule out interpretations of `f` with more than two parameters, as
     1348there may be a valid interpretation of `g( y )` as a function returning more
     1349than one parameter (if the expression was `f( y, z )` instead, we could use an
     1350exact parameter count, assuming that variables of tuple type don't exist).
     1351For each compatible interpretation of `f`, we can add the type of the first
     1352parameter of that interpretation of `f` to a set `S`, and recursively search
     1353for interpretations of `g( y )` that return some type `Si` in `S`, and
     1354similarly for interpretations of `z` that match the type of any of the second
     1355parameters of some `f`.
     1356Naturally, if no matching interpretation of `g( y )` can be found for the
     1357first parameter of some `f`, the type of the second parameter of that `f` will
     1358not be added to the set of valid types for `z`.
     1359Each node in this interpretation DAG is given a cost the same way it would be
     1360in the bottom-up approach, with the exception that when going top-down there
     1361must be a final bottom-up pass to sum the interpretation costs and sort them
     1362as appropriate.
     1363
     1364If a parameter type for some `f` is a polymorphic type variable that is left
     1365unbound by the return type (e.g. `forall(otype S) int f(S x, int y)`), the
     1366matching arguments should be found using the bottom-up algorithm above for
     1367untyped contexts, because the polymorphic type variable does not sufficiently
     1368constrain the available interpretations of the argument expression.
     1369Similarly, it would likely be an advantage to use top-down resolution for
     1370cast expressions (e.g. `(int)x`), even when those cast expressions are
     1371subexpressions of an otherwise untyped expression.
     1372It may also be fruitful to switch between the bottom-up and top-down
     1373algorithms if the number of valid interpretations for a subexpression or valid
     1374types for an argument exceeds some heuristic threshold, but finding such
     1375a threshold (if any exists) will require experimental data.
     1376This hybrid top-down/bottom-up search provides more opportunities for pruning
     1377interpretations than either a bottom-up or top-down approach alone, and thus
     1378may be more efficient than either.
     1379A top-down-only approach, however, devolves to linear search through every
     1380possible interpretation in the solution space in an untyped context, and is
     1381thus likely to be inferior to a strictly bottom-up approach, though this
     1382hypothesis needs to be empirically validated.
     1383
     1384Both Baker and Cormack explicitly generate all possible interpretations of a
     1385given expression; thinking of the set of interpretations of an expression as a
     1386list sorted by cost, this is an eager evaluation of the list.
     1387However, since we generally expect that user programmers will not often use
     1388high-cost implicit conversions, one potentially effective way to prune the
     1389search space would be to first find the minimal-cost interpretations of any
     1390given subexpression, then to save the resolution progress of the
     1391subexpressions and attempt to resolve the superexpression using only those
     1392subexpression interpretations.
     1393If no valid interpretation of the superexpression can be found, the resolver
     1394would then repeatedly find the next-most-minimal cost interpretations of the
     1395subexpressions and attempt to produce the minimal cost interpretation of the
     1396superexpression.
     1397This process would proceed until all possible subexpression interpretations
     1398have been found and considered.
     1399
     1400A middle ground between the eager and lazy approaches can be taken by
     1401considering the lexical order on the cost tuple; essentially, every
     1402interpretation in each of the classes below will be strictly cheaper than any
     1403interpretation in the class after it, so if a min-cost valid interpretation
     1404can be found while only generating interpretations in a given class, that
     1405interpretation is guaranteed to be the best possible one:
     1406
     14071. Interpretations without polymorphic functions or implicit conversions
     14082. Interpretations without polymorphic functions using only safe conversions
     14093. Interpretations using polymorphic functions without unsafe conversions
     14104. Interpretations using unsafe conversions
     1411
     1412In this lazy-eager approach, all the interpretations in one class would be
     1413eagerly generated, while the interpretations in the next class would only be
     1414considered if no match was found in the previous class.
     1415
    12261416## Appendix A: Partial and Total Orders ##
    12271417The `<=` relation on integers is a commonly known _total order_, and
  • src/ArgTweak/FunctionFixer.cc

    re04ef3a rc8c03683  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FunctionFixer.cc -- 
     7// FunctionFixer.cc --
    88//
    99// Author           : Rodolfo G. Esteves
     
    4242        Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr ) throw ( SemanticError ) {
    4343                assert( untypedExpr != 0 );
    44                 NameExpr *function;
    4544
    46                 if ( ( function = dynamic_cast< NameExpr *>(untypedExpr->get_function()) ) != 0 ) {
     45                if ( NameExpr * function = dynamic_cast< NameExpr *>(untypedExpr->get_function() ) ) {
    4746                        std::list < DeclarationWithType * > options;
    4847                        index->lookupId ( function->get_name(), options );
    4948                        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() ) )   {
    5250                                        std::list < DeclarationWithType * > &pars = f->get_parameters();
    53 
    5451                                        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++ ) {
    5653                                                if ( ( candidateExists = align( f->get_parameters(), untypedExpr->get_args(), Matcher() ) ) ) break;
    57 
     54                                        }
    5855                                        if ( ! candidateExists ) throw SemanticError("Error in function call");
    5956                                } // if
  • src/CodeGen/CodeGenerator.cc

    re04ef3a rc8c03683  
    2626#include "SynTree/Statement.h"
    2727#include "SynTree/Type.h"
     28#include "SynTree/Attribute.h"
    2829
    2930#include "Common/utility.h"
     
    3334#include "OperatorTable.h"
    3435#include "GenType.h"
     36
     37#include "InitTweak/InitTweak.h"
    3538
    3639using namespace std;
     
    7477        }
    7578
     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
    7695        //*** Declarations
    7796        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
    9899                handleStorageClass( functionDecl );
    99100                if ( functionDecl->get_isInline() ) {
     
    270271                                                        UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) );
    271272                                                        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 );
    272277                                                        *arg = newExpr;
    273278                                                } // if
     
    298303                                        if ( applicationExpr->get_args().size() == 1 ) {
    299304                                                // the expression fed into a single parameter constructor or destructor
    300                                                 // may contain side effects - output as a void expression
    301                                                 output << "((void)(";
     305                                                // may contain side effects, so must still output this expression
     306                                                output << "(";
    302307                                                (*arg++)->accept( *this );
    303                                                 output << ")) /* " << opInfo.inputName << " */";
     308                                                output << ") /* " << opInfo.inputName << " */";
    304309                                        } else if ( applicationExpr->get_args().size() == 2 ) {
    305310                                                // intrinsic two parameter constructors are essentially bitwise assignment
     
    384389                                        if ( untypedExpr->get_args().size() == 1 ) {
    385390                                                // the expression fed into a single parameter constructor or destructor
    386                                                 // may contain side effects - output as a void expression
    387                                                 output << "((void)(";
     391                                                // may contain side effects, so must still output this expression
     392                                                output << "(";
    388393                                                (*arg++)->accept( *this );
    389                                                 output << ")) /* " << opInfo.inputName << " */";
     394                                                output << ") /* " << opInfo.inputName << " */";
    390395                                        } else if ( untypedExpr->get_args().size() == 2 ) {
    391396                                                // intrinsic two parameter constructors are essentially bitwise assignment
     
    626631
    627632        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 explanation
    631633                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 << ";";
    637638        }
    638639
     
    743744
    744745        void CodeGenerator::visit( WhileStmt *whileStmt ) {
    745                 if ( whileStmt->get_isDoWhile() )
     746                if ( whileStmt->get_isDoWhile() ) {
    746747                        output << "do" ;
    747                 else {
     748                } else {
    748749                        output << "while (" ;
    749750                        whileStmt->get_condition()->accept( *this );
     
    769770                output << "for (;";
    770771
    771                 if ( forStmt->get_condition() != 0 )
     772                if ( forStmt->get_condition() != 0 ) {
    772773                        forStmt->get_condition()->accept( *this );
     774                }
    773775                output << ";";
    774776
    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                }
    777782                output << ") ";
    778783
  • src/CodeGen/CodeGenerator.h

    re04ef3a rc8c03683  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // CodeGenerator.h -- 
     7// CodeGenerator.h --
    88//
    99// Author           : Richard C. Bilson
     
    6060                virtual void visit( MemberExpr *memberExpr );
    6161                virtual void visit( VariableExpr *variableExpr );
    62                 virtual void visit( ConstantExpr *constantExpr ); 
     62                virtual void visit( ConstantExpr *constantExpr );
    6363                virtual void visit( SizeofExpr *sizeofExpr );
    6464                virtual void visit( AlignofExpr *alignofExpr );
     
    8585                virtual void visit( ForStmt * );
    8686                virtual void visit( NullStmt * );
    87                 virtual void visit( DeclStmt * );
     87                virtual void visit( DeclStmt * );
     88
     89                void genAttributes( std::list< Attribute * > & attributes );
    8890
    8991                template< class Iterator > void genCommaList( Iterator begin, Iterator end );
     
    114116
    115117        };
    116        
     118
    117119        template< class Iterator >
    118120        void CodeGenerator::genCommaList( Iterator begin, Iterator end ) {
     
    125127                } // for
    126128        }
    127  
     129
    128130        inline bool doSemicolon( Declaration* decl ) {
    129131                if ( FunctionDecl* func = dynamic_cast< FunctionDecl* >( decl ) ) {
  • src/GenPoly/Box.cc

    re04ef3a rc8c03683  
    19471947                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    19481948                                derefExpr->get_args().push_back( derefdVar );
     1949                                // xxx - should set results on derefExpr
    19491950                                derefdVar = derefExpr;
    19501951                        }
  • src/GenPoly/Specialize.cc

    re04ef3a rc8c03683  
    2525#include "SynTree/Statement.h"
    2626#include "SynTree/Type.h"
     27#include "SynTree/Attribute.h"
    2728#include "SynTree/TypeSubstitution.h"
    2829#include "SynTree/Mutator.h"
     
    101102                thunkFunc->fixUniqueId();
    102103
     104                // thunks may be generated and not used - silence warning with attribute
     105                thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
     106
    103107                // thread thunk parameters into call to actual function, naming thunk parameters as we go
    104108                UniqueName paramNamer( paramPrefix );
  • src/InitTweak/FixGlobalInit.cc

    re04ef3a rc8c03683  
    2222#include "SynTree/Initializer.h"
    2323#include "SynTree/Visitor.h"
     24#include "SynTree/Attribute.h"
    2425#include <algorithm>
    2526
     
    116117        GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
    117118                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 ) );
    121135        }
    122136
     
    125139                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    126140
    127                 // if ( objDecl->get_init() == NULL ) return;
    128141                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 variable
    130142                if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    131143                // C allows you to initialize objects with constant expressions
     
    146158                        init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    147159                        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 ) ) );
    149161
    150162                        // add destructor calls to global destroy function
    151163                        UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
    152164                        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 ) ) );
    154166                }
    155167        }
  • src/InitTweak/FixInit.cc

    re04ef3a rc8c03683  
    132132                                return appExpr;
    133133                        } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    134                                 // FunctionType * ftype = funcDecl->get_functionType();
    135134                                FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    136135                                assert( ftype );
  • src/InitTweak/GenInit.cc

    re04ef3a rc8c03683  
    164164                                                assert( ctor.size() == 1 );
    165165                                                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() ) );
    168167                                        } else {
    169168                                                // array came with an initializer list: initialize each element
     
    185184                                        ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
    186185                                        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() ) );
    188187                                }
    189188                        }
  • src/InitTweak/InitTweak.cc

    re04ef3a rc8c03683  
    77
    88namespace InitTweak {
    9   namespace {
    10     class HasDesignations : public Visitor {
    11     public:
    12       bool hasDesignations = false;
    13       template<typename Init>
    14       void handleInit( Init * init ) {
    15         if ( ! init->get_designators().empty() ) hasDesignations = true;
    16         else Visitor::visit( init );
    17       }
    18       virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
    19       virtual void visit( ListInit * listInit ) { handleInit( listInit); }
    20     };
     9        namespace {
     10                class HasDesignations : public Visitor {
     11                public:
     12                        bool hasDesignations = false;
     13                        template<typename Init>
     14                        void handleInit( Init * init ) {
     15                                if ( ! init->get_designators().empty() ) hasDesignations = true;
     16                                else Visitor::visit( init );
     17                        }
     18                        virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
     19                        virtual void visit( ListInit * listInit ) { handleInit( listInit); }
     20                };
    2121
    22     class InitExpander : public Visitor {
    23       public:
    24       InitExpander() {}
    25       virtual void visit( SingleInit * singleInit );
    26       virtual void visit( ListInit * listInit );
    27       std::list< Expression * > argList;
    28     };
     22                class InitExpander : public Visitor {
     23                        public:
     24                        InitExpander() {}
     25                        virtual void visit( SingleInit * singleInit );
     26                        virtual void visit( ListInit * listInit );
     27                        std::list< Expression * > argList;
     28                };
    2929
    30     void InitExpander::visit( SingleInit * singleInit ) {
    31       argList.push_back( singleInit->get_value()->clone() );
    32     }
     30                void InitExpander::visit( SingleInit * singleInit ) {
     31                        argList.push_back( singleInit->get_value()->clone() );
     32                }
    3333
    34     void InitExpander::visit( ListInit * listInit ) {
    35       // xxx - for now, assume no nested list inits
    36       std::list<Initializer*>::iterator it = listInit->begin_initializers();
    37       for ( ; it != listInit->end_initializers(); ++it ) {
    38         (*it)->accept( *this );
    39       }
    40     }
    41   }
     34                void InitExpander::visit( ListInit * listInit ) {
     35                        // xxx - for now, assume no nested list inits
     36                        std::list<Initializer*>::iterator it = listInit->begin_initializers();
     37                        for ( ; it != listInit->end_initializers(); ++it ) {
     38                                (*it)->accept( *this );
     39                        }
     40                }
     41        }
    4242
    43   std::list< Expression * > makeInitList( Initializer * init ) {
    44     InitExpander expander;
    45     maybeAccept( init, expander );
    46     return expander.argList;
    47   }
     43        std::list< Expression * > makeInitList( Initializer * init ) {
     44                InitExpander expander;
     45                maybeAccept( init, expander );
     46                return expander.argList;
     47        }
    4848
    49   bool isDesignated( Initializer * init ) {
    50     HasDesignations finder;
    51     maybeAccept( init, finder );
    52     return finder.hasDesignations;
    53   }
     49        bool isDesignated( Initializer * init ) {
     50                HasDesignations finder;
     51                maybeAccept( init, finder );
     52                return finder.hasDesignations;
     53        }
    5454
    55   bool tryConstruct( ObjectDecl * objDecl ) {
    56     return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    57       (objDecl->get_init() == NULL ||
    58         ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59       ! isDesignated( objDecl->get_init() );
    60   }
     55        bool tryConstruct( ObjectDecl * objDecl ) {
     56                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
     57                        (objDecl->get_init() == NULL ||
     58                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
     59                        ! isDesignated( objDecl->get_init() );
     60        }
    6161
    62   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        }
    85154}
  • src/InitTweak/InitTweak.h

    re04ef3a rc8c03683  
    3939  /// Currently has assertions that make it less than fully general.
    4040  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 * );
    4156} // namespace
    4257
  • src/Makefile.in

    re04ef3a rc8c03683  
    195195        SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \
    196196        SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
     197        SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
    197198        Tuples/driver_cfa_cpp-Mutate.$(OBJEXT) \
    198199        Tuples/driver_cfa_cpp-AssignExpand.$(OBJEXT) \
     
    411412        SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
    412413        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.cc
     414        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
    417418MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
    418419        ${cfa_cpplib_PROGRAMS}}
     
    783784SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
    784785        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     786SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
     787        SynTree/$(DEPDIR)/$(am__dirstamp)
    785788Tuples/$(am__dirstamp):
    786789        @$(MKDIR_P) Tuples
     
    880883        -rm -f SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT)
    881884        -rm -f SynTree/driver_cfa_cpp-AttrType.$(OBJEXT)
     885        -rm -f SynTree/driver_cfa_cpp-Attribute.$(OBJEXT)
    882886        -rm -f SynTree/driver_cfa_cpp-BasicType.$(OBJEXT)
    883887        -rm -f SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT)
     
    989993@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po@am__quote@
    990994@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@
    991996@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po@am__quote@
    992997@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po@am__quote@
     
    24242429@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    24252430@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
     2432SynTree/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
     2439SynTree/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`
    24262445
    24272446Tuples/driver_cfa_cpp-Mutate.o: Tuples/Mutate.cc
  • src/ResolvExpr/AlternativeFinder.cc

    re04ef3a rc8c03683  
    3939#include "Tuples/NameMatcher.h"
    4040#include "Common/utility.h"
     41#include "InitTweak/InitTweak.h"
    4142
    4243extern bool resolvep;
     
    546547
    547548                {
    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 == "&&" ) {
    551551                                VoidType v = Type::Qualifiers();                // resolve to type void *
    552552                                PointerType pt( Type::Qualifiers(), v.clone() );
  • src/ResolvExpr/CommonType.cc

    re04ef3a rc8c03683  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // CommonType.cc -- 
     7// CommonType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    134134                                result = new BasicType( basicType->get_qualifiers() + otherBasic->get_qualifiers(), newType );
    135135                        } // 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
    136142                } // if
    137143        }
     
    183189        }
    184190
    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
    186199        }
    187200
  • src/ResolvExpr/ConversionCost.cc

    re04ef3a rc8c03683  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ConversionCost.cc -- 
     7// ConversionCost.cc --
    88//
    99// Author           : Richard C. Bilson
     
    157157                                cost = Cost( 0, 0, tableResult );
    158158                        } // 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
    160163        }
    161164
  • src/ResolvExpr/Resolver.cc

    re04ef3a rc8c03683  
    3838                virtual void visit( ObjectDecl *functionDecl );
    3939                virtual void visit( TypeDecl *typeDecl );
     40                virtual void visit( EnumDecl * enumDecl );
    4041
    4142                virtual void visit( ArrayType * at );
     
    5253                virtual void visit( BranchStmt *branchStmt );
    5354                virtual void visit( ReturnStmt *returnStmt );
     55                virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5456
    5557                virtual void visit( SingleInit *singleInit );
     
    6567                Type *initContext;
    6668                Type *switchType;
     69                bool inEnumDecl = false;
    6770        };
    6871
     
    177180                Type *temp = initContext;
    178181                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                }
    179187                SymTab::Indexer::visit( objectDecl );
     188                if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
     189                        // delete newly created signed int type
     190                        delete initContext;
     191                }
    180192                initContext = temp;
    181193        }
     
    215227                SymTab::Indexer::visit( functionDecl );
    216228                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;
    217237        }
    218238
     
    492512                } catch ( SemanticError ) {
    493513                        // 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?
    495515                        fallbackInit( ctorInit );
    496516                        return;
     
    513533                }
    514534        }
     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        }
    515577} // namespace ResolvExpr
    516578
  • src/SymTab/Autogen.cc

    re04ef3a rc8c03683  
    102102                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    103103
     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);
    104117                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    105118                assignType->get_returnVals().push_back( returnVal );
    106119
    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.
    125122
    126123                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    127124                // 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 );
    132132                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 );
    152156        }
    153157
     
    488492                type->get_parameters().push_back( dst );
    489493                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 );
    491495                declsToAdd.push_back( func );
    492496        }
  • src/SymTab/Validate.cc

    re04ef3a rc8c03683  
    279279        void Pass1::visit( EnumDecl *enumDecl ) {
    280280                // Set the type of each member of the enumeration to be EnumConstant
    281 
    282281                for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
    283282                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
    284283                        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() ) );
    288285                } // for
    289286                Parent::visit( enumDecl );
  • src/SynTree/Declaration.h

    re04ef3a rc8c03683  
    115115        typedef DeclarationWithType Parent;
    116116  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 * >() );
    130118        FunctionDecl( const FunctionDecl &other );
    131119        virtual ~FunctionDecl();
     
    140128        std::list< std::string >& get_oldIdents() { return oldIdents; }
    141129        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; }
    144131
    145132        virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
     
    153140        std::list< std::string > oldIdents;
    154141        std::list< Declaration* > oldDecls;
    155         Attribute attribute;
     142        std::list< Attribute * > attributes;
    156143};
    157144
  • src/SynTree/FunctionDecl.cc

    re04ef3a rc8c03683  
    1919#include "Statement.h"
    2020#include "Type.h"
     21#include "Attribute.h"
    2122#include "Common/utility.h"
    2223
    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 ) {
     24FunctionDecl::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 ) {
    2526        set_isInline( isInline );
    2627        set_isNoreturn( isNoreturn );
     
    3233
    3334FunctionDecl::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 );
    3537}
    3638
     
    3840        delete type;
    3941        delete statements;
     42        deleteAll( attributes );
    4043}
    4144
     
    6568                os << "_Noreturn ";
    6669        } // 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
    8073        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
    8174                os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
     
    118111                os << "_Noreturn ";
    119112        } // 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
    133116        if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
    134117                os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
  • src/SynTree/Initializer.cc

    re04ef3a rc8c03683  
    2020
    2121Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
     22Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) {
     23}
     24
    2225
    2326Initializer::~Initializer() {}
     
    3942}
    4043
    41 SingleInit::~SingleInit() {}
    42 
    43 SingleInit *SingleInit::clone() const { return new SingleInit( *this); }
     44SingleInit::~SingleInit() {
     45        deleteAll(designators);
     46}
    4447
    4548void SingleInit::print( std::ostream &os, int indent ) {
     
    5861
    5962ListInit::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 ) {
    6164}
    6265
    63 ListInit::~ListInit() {}
    64 
    65 ListInit *ListInit::clone() const {
    66         return new ListInit( *this );
     66ListInit::~ListInit() {
     67        deleteAll( initializers );
     68        deleteAll( designators );
    6769}
    6870
     
    8587
    8688ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
     89ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) {
     90}
     91
    8792ConstructorInit::~ConstructorInit() {
    8893        delete ctor;
     94        delete dtor;
    8995        delete init;
    90 }
    91 
    92 ConstructorInit *ConstructorInit::clone() const {
    93         return new ConstructorInit( *this );
    9496}
    9597
  • src/SynTree/Initializer.h

    re04ef3a rc8c03683  
    2020#include "Visitor.h"
    2121#include "Mutator.h"
     22#include "Type.h"
    2223
    2324#include <cassert>
     
    2829        //      Initializer( std::string _name = std::string(""), int _pos = 0 );
    2930        Initializer( bool maybeConstructed );
     31        Initializer( const Initializer & other );
    3032        virtual ~Initializer();
    3133
     
    6870        std::list<Expression *> &get_designators() { return designators; }
    6971
    70         virtual SingleInit *clone() const;
     72        virtual SingleInit *clone() const { return new SingleInit( *this); }
    7173        virtual void accept( Visitor &v ) { v.visit( this ); }
    7274        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     
    9496        std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
    9597
    96         virtual ListInit *clone() const;
     98        virtual ListInit *clone() const { return new ListInit( *this ); }
    9799        virtual void accept( Visitor &v ) { v.visit( this ); }
    98100        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     
    108110  public:
    109111        ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );
     112        ConstructorInit( const ConstructorInit &other );
    110113        virtual ~ConstructorInit();
    111114
     
    117120        Initializer * get_init() const { return init; }
    118121
    119         virtual ConstructorInit *clone() const;
     122        ConstructorInit *clone() const { return new ConstructorInit( *this ); }
    120123        virtual void accept( Visitor &v ) { v.visit( this ); }
    121124        virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
  • src/SynTree/Mutator.cc

    re04ef3a rc8c03683  
    182182}
    183183
     184Statement *Mutator::mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
     185        impCtorDtorStmt->set_callStmt( maybeMutate( impCtorDtorStmt->get_callStmt(), *this ) );
     186        return impCtorDtorStmt;
     187}
     188
    184189Expression *Mutator::mutate( ApplicationExpr *applicationExpr ) {
    185190        mutateAll( applicationExpr->get_results(), *this );
  • src/SynTree/Mutator.h

    re04ef3a rc8c03683  
    5252        virtual NullStmt* mutate( NullStmt *nullStmt );
    5353        virtual Statement* mutate( DeclStmt *declStmt );
     54        virtual Statement* mutate( ImplicitCtorDtorStmt *impCtorDtorStmt );
    5455
    5556        virtual Expression* mutate( ApplicationExpr *applicationExpr );
  • src/SynTree/Statement.cc

    re04ef3a rc8c03683  
    358358
    359359void CatchStmt::print( std::ostream &os, int indent ) const {
    360         os << string( indent, ' ' ) << "Catch Statement" << endl;
     360        os << "Catch Statement" << endl;
    361361
    362362        os << string( indent, ' ' ) << "... catching" << endl;
     
    383383
    384384void FinallyStmt::print( std::ostream &os, int indent ) const {
    385         os << string( indent, ' ' ) << "Finally Statement" << endl;
     385        os << "Finally Statement" << endl;
    386386        os << string( indent + 2, ' ' ) << "with block: " << endl;
    387387        block->print( os, indent + 4 );
     
    393393void NullStmt::print( std::ostream &os, int indent ) const {
    394394        os << "Null Statement" << endl ;
     395}
     396
     397ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement( std::list<Label>() ), callStmt( callStmt ) {
     398        assert( callStmt );
     399}
     400
     401ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ) : Statement( other ), callStmt( other.callStmt ) {
     402}
     403
     404ImplicitCtorDtorStmt::~ImplicitCtorDtorStmt() {
     405}
     406
     407void 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;
    395412}
    396413
  • src/SynTree/Statement.h

    re04ef3a rc8c03683  
    2121#include "Mutator.h"
    2222#include "Common/SemanticError.h"
     23#include "Type.h"
    2324
    2425class Statement {
     
    394395        virtual ~DeclStmt();
    395396
    396         Declaration *get_decl() { return decl; }
     397        Declaration *get_decl() const { return decl; }
    397398        void set_decl( Declaration *newValue ) { decl = newValue; }
    398399
     
    404405        Declaration *decl;
    405406};
     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.
     412class 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
    406431
    407432std::ostream & operator<<( std::ostream & out, Statement * statement );
  • src/SynTree/SynTree.h

    re04ef3a rc8c03683  
    5656class DeclStmt;
    5757class NullStmt;
     58class ImplicitCtorDtorStmt;
    5859
    5960class Expression;
     
    117118class TypeSubstitution;
    118119
     120// gcc attribute
     121class Attribute;
     122
    119123#endif // SYNTREE_H
    120124
  • src/SynTree/Type.cc

    re04ef3a rc8c03683  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Type.cc -- 
     7// Type.cc --
    88//
    99// Author           : Richard C. Bilson
     
    5454}
    5555
     56void 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
    5677void Type::print( std::ostream &os, int indent ) const {
    5778        if ( ! forall.empty() ) {
     
    6081                os << std::string( indent+2, ' ' );
    6182        } // 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 );
    8084}
    8185
  • src/SynTree/Type.h

    re04ef3a rc8c03683  
    3636                bool operator<( const Qualifiers &other );
    3737                bool operator>( const Qualifiers &other );
     38                void print( std::ostream &os, int indent = 0 ) const;
    3839
    3940                bool isConst;
  • src/SynTree/Visitor.cc

    re04ef3a rc8c03683  
    152152}
    153153
     154void Visitor::visit( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
     155        maybeAccept( impCtorDtorStmt->get_callStmt(), *this );
     156}
     157
    154158void Visitor::visit( ApplicationExpr *applicationExpr ) {
    155159        acceptAll( applicationExpr->get_results(), *this );
  • src/SynTree/Visitor.h

    re04ef3a rc8c03683  
    5252        virtual void visit( NullStmt *nullStmt );
    5353        virtual void visit( DeclStmt *declStmt );
     54        virtual void visit( ImplicitCtorDtorStmt *impCtorDtorStmt );
    5455
    5556        virtual void visit( ApplicationExpr *applicationExpr );
  • src/SynTree/module.mk

    re04ef3a rc8c03683  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## module.mk -- 
     8## module.mk --
    99##
    1010## Author           : Richard C. Bilson
     
    4646       SynTree/Visitor.cc \
    4747       SynTree/Mutator.cc \
    48        SynTree/TypeSubstitution.cc
     48       SynTree/TypeSubstitution.cc \
     49       SynTree/Attribute.cc
    4950
  • src/examples/avltree/avl-private.h

    re04ef3a rc8c03683  
     1#ifndef AVL_PRIVATE_H
    12#include "avl.h"
    23
     
    1314forall(otype K | Comparable(K), otype V)
    1415int height(tree(K, V) * t);
     16
     17#endif
Note: See TracChangeset for help on using the changeset viewer.