Changeset a554e5f4


Ignore:
Timestamp:
Feb 9, 2022, 3:33:42 PM (3 years ago)
Author:
caparsons <caparson@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
Children:
850aff1
Parents:
21a99cc (diff), c4f8170 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.sty

    r21a99cc ra554e5f4  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon May 31 09:08:37 2021
    14 %% Update Count     : 565
     13%% Last Modified On : Mon Feb  7 23:00:46 2022
     14%% Update Count     : 569
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    4343\newcommand{\CCIcon}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}} % C++ icon
    4444\newcommand{\CC}[1][]{\protect\CCIcon{#1}\xspace}               % C++ symbolic name
     45\newcommand{\Cpp}[1][]{\CC{#1}}                                                 % C++ synonym
    4546% numbers disallowed in latex variables names => use number names
    4647\newcommand{\CCeleven}{\protect\CCIcon{11}\xspace}              % C++11 symbolic name
     
    5152
    5253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     54
     55\usepackage{pslatex}                                                                    % reduce size of san serif font
     56\usepackage{relsize}                                                                    % must be after change to small or selects old size
     57\usepackage{rotating}
     58\usepackage{calc}                                                                               % latex arithmetic
    5359
    5460% remove special-character warning in PDF side-bar names
     
    7177\newlength{\parindentlnth}
    7278\setlength{\parindentlnth}{\parindent}
    73 
    74 \usepackage{pslatex}                                                                    % reduce size of san serif font
    75 \usepackage{relsize}                                                                    % must be after change to small or selects old size
    76 \usepackage{rotating}
    77 \usepackage{calc}                                                                               % latex arithmetic
    7879
    7980% reduce size of chapter/section titles
     
    151152\newcommand{\@snewterm}[2][\@empty]{{\newtermFontInline{#2}}\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi}
    152153
     154% \snake{<identifier>}
     155% Improves writing of snake case (or any convention that uses _) by allowing
     156% line breaks after _. Disables commands inside the block and formats the
     157% identifier to look like code.
     158\newcommand*\snake[1]{\snakefont{\expandafter\snake@next\detokenize{#1}\@nil}}
     159
     160% \snakefont{<text>}
     161% Command used by \snake, you may renew the command to change its formating.
     162\newcommand*\snakefont[1]{\LstBasicStyle{#1}}
     163
     164% Thanks Manuel of TeX Stack exchange. (I got the base pattern from one of
     165% their answers.) Note: \@nil should never be defined.
     166\newcommand*\snake@next[1]{\ifx\@nil#1\else
     167  \expandafter\ifx\string_#1\string_\allowbreak\else#1\fi
     168  \expandafter\snake@next\fi
     169}
     170
     171% \lang{<language>}{<code>}
     172% Use the listings package to format the snipit of <code> in <language>.
     173\newcommand{\lang}[2]{\lstinline[language=#1]{#2}}
     174
    153175% Latin abbreviation
    154176\newcommand{\abbrevFont}{\textit}                       % set empty for no italics
     
    263285extendedchars=true,                                             % allow ASCII characters in the range 128-255
    264286escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    265 mathescape=false,                                               % LaTeX math escape in CFA code $...$
     287mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    266288keepspaces=true,                                                %
    267289showstringspaces=false,                                 % do not show spaces with cup
     
    308330}{}
    309331% inline code @...@ (at symbol)
    310 \makeatother
    311332\lstMakeShortInline@                                    % single-character for \lstinline
    312 \makeatletter
    313333\fi%
    314334
  • doc/LaTeXmacros/common.tex

    r21a99cc ra554e5f4  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon May 31 09:10:49 2021
    14 %% Update Count     : 546
     13%% Last Modified On : Mon Feb  7 23:00:08 2022
     14%% Update Count     : 552
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    4343\newcommand{\CCIcon}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}} % C++ icon
    4444\newcommand{\CC}[1][]{\protect\CCIcon{#1}\xspace}               % C++ symbolic name
     45\newcommand{\Cpp}[1][]{\CC{#1}}                                                 % C++ synonym
    4546% numbers disallowed in latex variables names => use number names
    4647\newcommand{\CCeleven}{\protect\CCIcon{11}\xspace}              % C++11 symbolic name
     
    5152
    5253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     54
     55\usepackage{pslatex}                                                                    % reduce size of san serif font
     56\usepackage{relsize}                                                                    % must be after change to small or selects old size
     57\usepackage{rotating}
     58\usepackage{calc}                                                                               % latex arithmetic
    5359
    5460% remove special-character warning in PDF side-bar names
     
    7278\newlength{\parindentlnth}
    7379\setlength{\parindentlnth}{\parindent}
    74 
    75 \usepackage{pslatex}                                                                    % reduce size of san serif font
    76 \usepackage{relsize}                                                                    % must be after change to small or selects old size
    77 \usepackage{rotating}
    78 \usepackage{calc}                                                                               % latex arithmetic
    7980
    8081% reduce size of chapter/section titles
     
    152153\newcommand{\@snewterm}[2][\@empty]{{\newtermFontInline{#2}}\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi}
    153154
     155% \snake{<identifier>}
     156% Improves writing of snake case (or any convention that uses _) by allowing
     157% line breaks after _. Disables commands inside the block and formats the
     158% identifier to look like code.
     159\newcommand*\snake[1]{\snakefont{\expandafter\snake@next\detokenize{#1}\@nil}}
     160
     161% \snakefont{<text>}
     162% Command used by \snake, you may renew the command to change its formating.
     163\newcommand*\snakefont[1]{\LstBasicStyle{#1}}
     164
     165% Thanks Manuel of TeX Stack exchange. (I got the base pattern from one of
     166% their answers.) Note: \@nil should never be defined.
     167\newcommand*\snake@next[1]{\ifx\@nil#1\else
     168  \expandafter\ifx\string_#1\string_\allowbreak\else#1\fi
     169  \expandafter\snake@next\fi
     170}
     171
     172% \lang{<language>}{<code>}
     173% Use the listings package to format the snipit of <code> in <language>.
     174\newcommand{\lang}[2]{\lstinline[language=#1]{#2}}
     175
    154176% Latin abbreviation
    155177\newcommand{\abbrevFont}{\textit}                       % set empty for no italics
     
    268290extendedchars=true,                                             % allow ASCII characters in the range 128-255
    269291escapechar=\$,                                                  % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'
    270 mathescape=false,                                               % LaTeX math escape in CFA code $...$
     292mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
    271293keepspaces=true,                                                %
    272294showstringspaces=false,                                 % do not show spaces with cup
  • doc/theses/thierry_delisle_PhD/thesis/Makefile

    r21a99cc ra554e5f4  
    4848## Define the documents that need to be made.
    4949all: thesis.pdf
    50 thesis.pdf: ${TEXTS} ${FIGURES} ${PICTURES} thesis.tex glossary.tex local.bib
     50thesis.pdf: ${TEXTS} ${FIGURES} ${PICTURES} thesis.tex glossary.tex local.bib ../../../LaTeXmacros/common.tex ../../../LaTeXmacros/common.sty
    5151
    5252DOCUMENT = thesis.pdf
  • libcfa/src/concurrency/preemption.cfa

    r21a99cc ra554e5f4  
    251251        bool enabled = __cfaabi_tls.preemption_state.enabled;
    252252
     253        // Check if there is a pending preemption
     254        processor   * proc = __cfaabi_tls.this_processor;
     255        bool pending = proc ? proc->pending_preemption : false;
     256        if( enabled && pending ) proc->pending_preemption = false;
     257
    253258        // create a assembler label after
    254259        // marked as clobber all to avoid movement
    255260        __cfaasm_label(check, after);
     261
     262        // If we can preempt and there is a pending one
     263        // this is a good time to yield
     264        if( enabled && pending ) {
     265                force_yield( __POLL_PREEMPTION );
     266        }
    256267        return enabled;
    257268}
     
    282293        // marked as clobber all to avoid movement
    283294        __cfaasm_label(get, after);
     295
     296        // This is used everywhere, to avoid cost, we DO NOT poll pending preemption
    284297        return val;
    285298}
     
    358371        if(!ready) { abort("Preemption should be ready"); }
    359372
    360         __cfaasm_label(debug, before);
    361 
    362                 sigset_t oldset;
    363                 int ret;
    364                 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    365                 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    366 
    367                 ret = sigismember(&oldset, SIGUSR1);
    368                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    369                 if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); }
    370 
    371                 ret = sigismember(&oldset, SIGALRM);
    372                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    373                 if(ret == 0) { abort("ERROR SIGALRM is enabled"); }
    374 
    375                 ret = sigismember(&oldset, SIGTERM);
    376                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    377                 if(ret == 1) { abort("ERROR SIGTERM is disabled"); }
    378 
    379         __cfaasm_label(debug, after);
     373        sigset_t oldset;
     374        int ret;
     375        ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     376        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
     377
     378        ret = sigismember(&oldset, SIGUSR1);
     379        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     380        if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); }
     381
     382        ret = sigismember(&oldset, SIGALRM);
     383        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     384        if(ret == 0) { abort("ERROR SIGALRM is enabled"); }
     385
     386        ret = sigismember(&oldset, SIGTERM);
     387        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     388        if(ret == 1) { abort("ERROR SIGTERM is disabled"); }
    380389}
    381390
     
    548557        __cfaasm_label( check  );
    549558        __cfaasm_label( dsable );
    550         __cfaasm_label( debug  );
     559        // __cfaasm_label( debug  );
    551560
    552561        // Check if preemption is safe
     
    555564        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    556565        if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; };
    557         if( __cfaasm_in( ip, debug  ) ) { ready = false; goto EXIT; };
     566        // if( __cfaasm_in( ip, debug  ) ) { ready = false; goto EXIT; };
    558567        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    559568        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     
    661670
    662671        // Check if it is safe to preempt here
    663         if( !preemption_ready( ip ) ) { return; }
     672        if( !preemption_ready( ip ) ) {
     673                #if !defined(__CFA_NO_STATISTICS__)
     674                        __cfaabi_tls.this_stats->ready.threads.preempt.rllfwd++;
     675                #endif
     676                return;
     677        }
    664678
    665679        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", __cfaabi_tls.this_processor, __cfaabi_tls.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) );
     
    680694
    681695        // Preemption can occur here
     696
     697        #if !defined(__CFA_NO_STATISTICS__)
     698                __cfaabi_tls.this_stats->ready.threads.preempt.yield++;
     699        #endif
    682700
    683701        force_yield( __ALARM_PREEMPTION ); // Do the actual __cfactx_switch
  • libcfa/src/concurrency/stats.cfa

    r21a99cc ra554e5f4  
    2929                stats->ready.threads.threads   = 0;
    3030                stats->ready.threads.cthreads  = 0;
     31                stats->ready.threads.preempt.yield  = 0;
     32                stats->ready.threads.preempt.rllfwd = 0;
    3133                stats->ready.sleep.halts   = 0;
    3234                stats->ready.sleep.cancels = 0;
     
    7779
    7880        void __tally_stats( struct __stats_t * cltr, struct __stats_t * proc ) {
    79                 tally_one( &cltr->ready.push.local.attempt, &proc->ready.push.local.attempt );
    80                 tally_one( &cltr->ready.push.local.success, &proc->ready.push.local.success );
    81                 tally_one( &cltr->ready.push.share.attempt, &proc->ready.push.share.attempt );
    82                 tally_one( &cltr->ready.push.share.success, &proc->ready.push.share.success );
    83                 tally_one( &cltr->ready.push.extrn.attempt, &proc->ready.push.extrn.attempt );
    84                 tally_one( &cltr->ready.push.extrn.success, &proc->ready.push.extrn.success );
    85                 tally_one( &cltr->ready.pop.local .attempt, &proc->ready.pop.local .attempt );
    86                 tally_one( &cltr->ready.pop.local .success, &proc->ready.pop.local .success );
    87                 tally_one( &cltr->ready.pop.help  .attempt, &proc->ready.pop.help  .attempt );
    88                 tally_one( &cltr->ready.pop.help  .success, &proc->ready.pop.help  .success );
    89                 tally_one( &cltr->ready.pop.steal .attempt, &proc->ready.pop.steal .attempt );
    90                 tally_one( &cltr->ready.pop.steal .success, &proc->ready.pop.steal .success );
    91                 tally_one( &cltr->ready.pop.search.attempt, &proc->ready.pop.search.attempt );
    92                 tally_one( &cltr->ready.pop.search.success, &proc->ready.pop.search.success );
    93                 tally_one( &cltr->ready.threads.migration , &proc->ready.threads.migration  );
    94                 tally_one( &cltr->ready.threads.extunpark , &proc->ready.threads.extunpark  );
    95                 tally_one( &cltr->ready.threads.threads   , &proc->ready.threads.threads    );
    96                 tally_one( &cltr->ready.threads.cthreads  , &proc->ready.threads.cthreads   );
    97                 tally_one( &cltr->ready.sleep.halts       , &proc->ready.sleep.halts        );
    98                 tally_one( &cltr->ready.sleep.cancels     , &proc->ready.sleep.cancels      );
    99                 tally_one( &cltr->ready.sleep.early       , &proc->ready.sleep.early        );
    100                 tally_one( &cltr->ready.sleep.wakes       , &proc->ready.sleep.wakes        );
    101                 tally_one( &cltr->ready.sleep.seen        , &proc->ready.sleep.wakes        );
    102                 tally_one( &cltr->ready.sleep.exits       , &proc->ready.sleep.exits        );
     81                tally_one( &cltr->ready.push.local.attempt    , &proc->ready.push.local.attempt     );
     82                tally_one( &cltr->ready.push.local.success    , &proc->ready.push.local.success     );
     83                tally_one( &cltr->ready.push.share.attempt    , &proc->ready.push.share.attempt     );
     84                tally_one( &cltr->ready.push.share.success    , &proc->ready.push.share.success     );
     85                tally_one( &cltr->ready.push.extrn.attempt    , &proc->ready.push.extrn.attempt     );
     86                tally_one( &cltr->ready.push.extrn.success    , &proc->ready.push.extrn.success     );
     87                tally_one( &cltr->ready.pop.local .attempt    , &proc->ready.pop.local .attempt     );
     88                tally_one( &cltr->ready.pop.local .success    , &proc->ready.pop.local .success     );
     89                tally_one( &cltr->ready.pop.help  .attempt    , &proc->ready.pop.help  .attempt     );
     90                tally_one( &cltr->ready.pop.help  .success    , &proc->ready.pop.help  .success     );
     91                tally_one( &cltr->ready.pop.steal .attempt    , &proc->ready.pop.steal .attempt     );
     92                tally_one( &cltr->ready.pop.steal .success    , &proc->ready.pop.steal .success     );
     93                tally_one( &cltr->ready.pop.search.attempt    , &proc->ready.pop.search.attempt     );
     94                tally_one( &cltr->ready.pop.search.success    , &proc->ready.pop.search.success     );
     95                tally_one( &cltr->ready.threads.migration     , &proc->ready.threads.migration      );
     96                tally_one( &cltr->ready.threads.extunpark     , &proc->ready.threads.extunpark      );
     97                tally_one( &cltr->ready.threads.threads       , &proc->ready.threads.threads        );
     98                tally_one( &cltr->ready.threads.cthreads      , &proc->ready.threads.cthreads       );
     99                tally_one( &cltr->ready.threads.preempt.yield , &proc->ready.threads.preempt.yield  );
     100                tally_one( &cltr->ready.threads.preempt.rllfwd, &proc->ready.threads.preempt.rllfwd );
     101                tally_one( &cltr->ready.sleep.halts           , &proc->ready.sleep.halts            );
     102                tally_one( &cltr->ready.sleep.cancels         , &proc->ready.sleep.cancels          );
     103                tally_one( &cltr->ready.sleep.early           , &proc->ready.sleep.early            );
     104                tally_one( &cltr->ready.sleep.wakes           , &proc->ready.sleep.wakes            );
     105                tally_one( &cltr->ready.sleep.seen            , &proc->ready.sleep.wakes            );
     106                tally_one( &cltr->ready.sleep.exits           , &proc->ready.sleep.exits            );
    103107
    104108                #if defined(CFA_HAVE_LINUX_IO_URING_H)
     
    168172                             | eng3(ready.sleep.wakes + ready.sleep.early) | '(' | eng3(ready.sleep.early) | ',' | eng3(ready.sleep.seen) | ')' | " wake(early, seen),"
    169173                             | eng3(ready.sleep.exits) | "exit";
     174                        sstr | "- Preemption : " | eng3(ready.threads.preempt.yield) | "yields," | eng3(ready.threads.preempt.rllfwd) | "delayed";
    170175                        sstr | nl;
    171176                }
  • libcfa/src/concurrency/stats.hfa

    r21a99cc ra554e5f4  
    6565                        volatile  int64_t threads;  // number of threads in the system, includes only local change
    6666                        volatile  int64_t cthreads; // number of threads in the system, includes only local change
     67                        struct {
     68                                volatile uint64_t yield;
     69                                volatile uint64_t rllfwd;
     70                        } preempt;
    6771                } threads;
    6872                struct {
  • libcfa/src/stdhdr/pthread.h

    r21a99cc ra554e5f4  
    1010// Created On       : Wed Jun 16 13:39:06 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 16 13:39:42 2021
    13 // Update Count     : 1
     12// Last Modified On : Thu Feb  3 21:53:26 2022
     13// Update Count     : 13
    1414//
    1515
     16// pthread.h and setjmp.h cannot agree on the type of __sigsetjmp:
     17//
     18//   extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__));
     19//   extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__));
     20//
     21// With -Wall, gcc-11 warns about the disagreement unless the CPP directive
     22//
     23//    # 1 "/usr/include/pthread.h" 1 3 4
     24//
     25// appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the
     26// batchtest fails because of the spurious warning message. Hence, the warning is elided.
     27
    1628extern "C" {
     29#if defined(__GNUC__) && __GNUC__ == 11
     30        #pragma GCC diagnostic push
     31        #pragma GCC diagnostic ignored "-Warray-parameter"
     32#endif // defined(__GNUC__) && __GNUC__ == 11
     33
    1734#include_next <pthread.h>                                                               // has internal check for multiple expansion
     35
     36#if defined(__GNUC__) && __GNUC__ == 11
     37        #pragma GCC diagnostic pop
     38#endif // defined(__GNUC__) && __GNUC__ == 11
    1839} // extern "C"
    1940
    2041// Local Variables: //
    21 // tab-width: 4 //
    2242// mode: c++ //
    23 // compile-command: "make install" //
    2443// End: //
  • libcfa/src/stdhdr/setjmp.h

    r21a99cc ra554e5f4  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul  5 20:38:33 2016
    13 // Update Count     : 12
     12// Last Modified On : Thu Feb  3 21:53:28 2022
     13// Update Count     : 18
    1414//
    1515
     16// pthread.h and setjmp.h cannot agree on the type of __sigsetjmp:
     17//
     18//   extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__));
     19//   extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__));
     20//
     21// With -Wall, gcc-11 warns about the disagreement unless the CPP directive
     22//
     23//    # 1 "/usr/include/pthread.h" 1 3 4
     24//
     25// appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the
     26// batchtest fails because of the spurious warning message. Hence, the warning is elided.
     27
    1628extern "C" {
     29#if defined(__GNUC__) && __GNUC__ == 11
     30        #pragma GCC diagnostic push
     31        #pragma GCC diagnostic ignored "-Warray-parameter"
     32#endif // defined(__GNUC__) && __GNUC__ == 11
     33
    1734#include_next <setjmp.h>                                                                // has internal check for multiple expansion
     35
     36#if defined(__GNUC__) && __GNUC__ == 11
     37        #pragma GCC diagnostic pop
     38#endif // defined(__GNUC__) && __GNUC__ == 11
    1839} // extern "C"
    1940
    2041// Local Variables: //
    21 // tab-width: 4 //
    2242// mode: c++ //
    23 // compile-command: "make install" //
    2443// End: //
  • src/AST/Pass.hpp

    r21a99cc ra554e5f4  
    238238
    239239private:
    240         const ast::Stmt * call_accept( const ast::Stmt * );
    241         const ast::Expr * call_accept( const ast::Expr * );
    242 
    243         // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
    244 
    245         const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
    246 
     240
     241        // Regular nodes
    247242        template< typename node_t >
    248         auto call_accept( const node_t * node ) -> typename std::enable_if<
     243        struct result1 {
     244                bool differs;
     245                const node_t * value;
     246
     247                template< typename object_t, typename super_t, typename field_t >
     248                void apply(object_t *, field_t super_t::* field);
     249        };
     250
     251        result1<ast::Stmt> call_accept( const ast::Stmt * );
     252        result1<ast::Expr> call_accept( const ast::Expr * );
     253
     254        template< typename node_t >
     255        auto call_accept( const node_t * node )
     256                -> typename std::enable_if<
    249257                                !std::is_base_of<ast::Expr, node_t>::value &&
    250258                                !std::is_base_of<ast::Stmt, node_t>::value
    251                         , decltype( node->accept(*this) )
     259                        , result1<
     260                                typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     261                        >
    252262                >::type;
    253263
     264        // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
     265        result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *);
     266
     267        // Container of statements
    254268        template< template <class...> class container_t >
    255         container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
    256 
     269        struct resultNstmt {
     270                struct delta {
     271                        ptr<Stmt> nval;
     272                        ssize_t old_idx;
     273                        bool is_old;
     274
     275                        delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {}
     276                };
     277
     278                bool differs;
     279                container_t< delta > values;
     280
     281                resultNstmt() : differs(false), values{} {}
     282                resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {}
     283
     284                template< typename object_t, typename super_t, typename field_t >
     285                void apply(object_t *, field_t super_t::* field);
     286
     287                template< template <class...> class incontainer_t >
     288                void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) {
     289                        if(!stmts || stmts->empty()) return;
     290
     291                        std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta {
     292                                        return delta( decl.release(), -1, false );
     293                                });
     294                        stmts->clear();
     295                        differs = true;
     296                }
     297
     298                template< template <class...> class incontainer_t >
     299                void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) {
     300                        if(!decls || decls->empty()) return;
     301
     302                        std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto {
     303                                        auto loc = decl->location;
     304                                        auto stmt = new DeclStmt( loc, decl.release() );
     305                                        return delta( stmt, -1, false );
     306                                });
     307                        decls->clear();
     308                        differs = true;
     309                }
     310        };
     311
     312        template< template <class...> class container_t >
     313        resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & );
     314
     315        // Container of something
    257316        template< template <class...> class container_t, typename node_t >
    258         container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
     317        struct resultN {
     318                bool differs;
     319                container_t<ptr<node_t>> values;
     320
     321                template< typename object_t, typename super_t, typename field_t >
     322                void apply(object_t *, field_t super_t::* field);
     323        };
     324
     325        template< template <class...> class container_t, typename node_t >
     326        resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container );
    259327
    260328public:
    261329        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
    262         template<typename node_t, typename parent_t, typename child_t>
    263         void maybe_accept(const node_t * &, child_t parent_t::* child);
    264 
    265         template<typename node_t, typename parent_t, typename child_t>
    266         void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
     330        template<typename node_t, typename parent_t, typename field_t>
     331        void maybe_accept(const node_t * &, field_t parent_t::* field);
     332
     333        template<typename node_t, typename parent_t, typename field_t>
     334        void maybe_accept_as_compound(const node_t * &, field_t parent_t::* field);
    267335
    268336private:
  • src/AST/Pass.impl.hpp

    r21a99cc ra554e5f4  
    7979
    8080                template<typename it_t, template <class...> class container_t>
    81                 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {
    82                         if(empty(decls)) return;
    83 
    84                         std::move(decls->begin(), decls->end(), it);
    85                         decls->clear();
     81                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
     82                        if(empty(stmts)) return;
     83
     84                        std::move(stmts->begin(), stmts->end(), it);
     85                        stmts->clear();
    8686                        if(mutated) *mutated = true;
    8787                }
     
    123123                        return !new_val.empty();
    124124                }
     125        }
     126
     127
     128        template< typename core_t >
     129        template< typename node_t >
     130        template< typename object_t, typename super_t, typename field_t >
     131        void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) {
     132                object->*field = value;
    125133        }
    126134
     
    131139                                !std::is_base_of<ast::Expr, node_t>::value &&
    132140                                !std::is_base_of<ast::Stmt, node_t>::value
    133                         , decltype( node->accept(*this) )
     141                        , ast::Pass< core_t >::result1<
     142                                typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     143                        >
    134144                >::type
    135145        {
     
    140150                static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
    141151
    142                 return node->accept( *this );
     152                auto nval = node->accept( *this );
     153                ast::Pass< core_t >::result1<
     154                        typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     155                > res;
     156                res.differs = nval != node;
     157                res.value = nval;
     158                return res;
    143159        }
    144160
    145161        template< typename core_t >
    146         const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     162        typename ast::Pass< core_t >::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    147163                __pedantic_pass_assert( __visit_children() );
    148164                __pedantic_pass_assert( expr );
     
    153169                }
    154170
    155                 return expr->accept( *this );
     171                auto nval = expr->accept( *this );
     172                return { nval != expr, nval };
    156173        }
    157174
    158175        template< typename core_t >
    159         const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     176        typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    160177                __pedantic_pass_assert( __visit_children() );
    161178                __pedantic_pass_assert( stmt );
    162179
    163                 return stmt->accept( *this );
     180                const ast::Stmt * nval = stmt->accept( *this );
     181                return { nval != stmt, nval };
    164182        }
    165183
    166184        template< typename core_t >
    167         const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     185        typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    168186                __pedantic_pass_assert( __visit_children() );
    169187                __pedantic_pass_assert( stmt );
     
    190208                // If the pass doesn't want to add anything then we are done
    191209                if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
    192                         return nstmt;
     210                        return { nstmt != stmt, nstmt };
    193211                }
    194212
     
    212230                __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
    213231
    214                 return compound;
     232                return {true, compound};
    215233        }
    216234
    217235        template< typename core_t >
    218236        template< template <class...> class container_t >
    219         container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     237        template< typename object_t, typename super_t, typename field_t >
     238        void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
     239                auto & container = object->*field;
     240                __pedantic_pass_assert( container.size() <= values.size() );
     241
     242                auto cit = enumerate(container).begin();
     243
     244                container_t<ptr<Stmt>> nvals;
     245                for(delta & d : values) {
     246                        if( d.is_old ) {
     247                                __pedantic_pass_assert( cit.idx <= d.old_idx );
     248                                std::advance( cit, d.old_idx - cit.idx );
     249                                nvals.push_back( std::move( (*cit).val) );
     250                        } else {
     251                                nvals.push_back( std::move(d.nval) );
     252                        }
     253                }
     254
     255                object->*field = std::move(nvals);
     256        }
     257
     258        template< typename core_t >
     259        template< template <class...> class container_t >
     260        typename ast::Pass< core_t >::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    220261                __pedantic_pass_assert( __visit_children() );
    221262                if( statements.empty() ) return {};
     
    244285                pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    245286
    246                 bool mutated = false;
    247                 container_t< ptr<Stmt> > new_kids;
    248                 for( const Stmt * stmt : statements ) {
     287                resultNstmt<container_t> new_kids;
     288                for( auto value : enumerate( statements ) ) {
    249289                        try {
     290                                size_t i = value.idx;
     291                                const Stmt * stmt = value.val;
    250292                                __pedantic_pass_assert( stmt );
    251293                                const ast::Stmt * new_stmt = stmt->accept( *this );
    252294                                assert( new_stmt );
    253                                 if(new_stmt != stmt ) mutated = true;
     295                                if(new_stmt != stmt ) { new_kids.differs = true; }
    254296
    255297                                // Make sure that it is either adding statements or declartions but not both
     
    261303
    262304                                // Take all the statements which should have gone after, N/A for first iteration
    263                                 __pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated );
    264                                 __pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated );
     305                                new_kids.take_all( decls_before );
     306                                new_kids.take_all( stmts_before );
    265307
    266308                                // Now add the statement if there is one
    267                                 new_kids.emplace_back( new_stmt );
     309                                if(new_stmt != stmt) {
     310                                        new_kids.values.emplace_back( new_stmt, i, false );
     311                                } else {
     312                                        new_kids.values.emplace_back( nullptr, i, true );
     313                                }
    268314
    269315                                // Take all the declarations that go before
    270                                 __pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated );
    271                                 __pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated );
     316                                new_kids.take_all( decls_after );
     317                                new_kids.take_all( stmts_after );
    272318                        }
    273319                        catch ( SemanticErrorException &e ) {
     
    278324                if ( !errors.isEmpty() ) { throw errors; }
    279325
    280                 return mutated ? new_kids : container_t< ptr<Stmt> >();
     326                return new_kids;
    281327        }
    282328
    283329        template< typename core_t >
    284330        template< template <class...> class container_t, typename node_t >
    285         container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     331        template< typename object_t, typename super_t, typename field_t >
     332        void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
     333                auto & container = object->*field;
     334                __pedantic_pass_assert( container.size() == values.size() );
     335
     336                for(size_t i = 0; i < container.size(); i++) {
     337                        // Take all the elements that are different in 'values'
     338                        // and swap them into 'container'
     339                        if( values[i] != nullptr ) std::swap(container[i], values[i]);
     340                }
     341
     342                // Now the original containers should still have the unchanged values
     343                // but also contain the new values
     344        }
     345
     346        template< typename core_t >
     347        template< template <class...> class container_t, typename node_t >
     348        typename ast::Pass< core_t >::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    286349                __pedantic_pass_assert( __visit_children() );
    287350                if( container.empty() ) return {};
     
    293356
    294357                bool mutated = false;
    295                 container_t< ast::ptr<node_t> > new_kids;
     358                container_t<ptr<node_t>> new_kids;
    296359                for ( const node_t * node : container ) {
    297360                        try {
    298361                                __pedantic_pass_assert( node );
    299362                                const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
    300                                 if(new_stmt != node ) mutated = true;
    301 
    302                                 new_kids.emplace_back( new_stmt );
     363                                if(new_stmt != node ) {
     364                                        mutated = true;
     365                                        new_kids.emplace_back( new_stmt );
     366                                } else {
     367                                        new_kids.emplace_back( nullptr );
     368                                }
     369
    303370                        }
    304371                        catch( SemanticErrorException &e ) {
     
    306373                        }
    307374                }
     375
     376                __pedantic_pass_assert( new_kids.size() == container.size() );
    308377                pass_visitor_stats.depth--;
    309378                if ( ! errors.isEmpty() ) { throw errors; }
    310379
    311                 return mutated ? new_kids : container_t< ast::ptr<node_t> >();
     380                return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated,  new_kids };
    312381        }
    313382
     
    327396                auto new_val = call_accept( old_val );
    328397
    329                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    330 
    331                 if( __pass::differs(old_val, new_val) ) {
     398                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
     399
     400                if( new_val.differs ) {
    332401                        auto new_parent = __pass::mutate<core_t>(parent);
    333                         new_parent->*child = new_val;
     402                        new_val.apply(new_parent, child);
    334403                        parent = new_parent;
    335404                }
     
    353422                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    354423
    355                 if( __pass::differs(old_val, new_val) ) {
     424                if( new_val.differs ) {
    356425                        auto new_parent = __pass::mutate<core_t>(parent);
    357                         new_parent->*child = new_val;
     426                        new_val.apply( new_parent, child );
    358427                        parent = new_parent;
    359428                }
     
    9411010                        const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
    9421011                        if(func != clause.target.func) mutated = true;
     1012                        else func = nullptr;
    9431013
    9441014                        std::vector<ptr<Expr>> new_args;
     
    9461016                        for( const auto & arg : clause.target.args ) {
    9471017                                auto a = arg->accept(*this);
    948                                 new_args.push_back( a );
    949                                 if( a != arg ) mutated = true;
     1018                                if( a != arg ) {
     1019                                        mutated = true;
     1020                                        new_args.push_back( a );
     1021                                } else
     1022                                        new_args.push_back( nullptr );
    9501023                        }
    9511024
    9521025                        const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
    9531026                        if(stmt != clause.stmt) mutated = true;
     1027                        else stmt = nullptr;
    9541028
    9551029                        const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
    9561030                        if(cond != clause.cond) mutated = true;
     1031                        else cond = nullptr;
    9571032
    9581033                        new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
     
    9611036                if(mutated) {
    9621037                        auto n = __pass::mutate<core_t>(node);
    963                         n->clauses = std::move( new_clauses );
     1038                        for(size_t i = 0; i < new_clauses.size(); i++) {
     1039                                if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
     1040
     1041                                for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
     1042                                        if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
     1043                                }
     1044
     1045                                if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
     1046                                if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
     1047                        }
    9641048                        node = n;
    9651049                }
     
    9691053                if(node->field) { \
    9701054                        auto nval = call_accept( node->field ); \
    971                         if(nval != node->field ) { \
     1055                        if(nval.differs ) { \
    9721056                                auto nparent = __pass::mutate<core_t>(node); \
    973                                 nparent->field = nval; \
     1057                                nparent->field = nval.value; \
    9741058                                node = nparent; \
    9751059                        } \
  • src/AST/Stmt.cpp

    r21a99cc ra554e5f4  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 15 15:53:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 19:01:20 2022
     13// Update Count     : 3
    1414//
    1515
     
    5656
    5757// --- BranchStmt
    58 BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
    59 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
     58BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, const std::vector<Label>&& labels )
     59                : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
    6060        // Make sure a syntax error hasn't slipped through.
    6161        assert( Goto != kind || !target.empty() );
  • src/AST/Stmt.hpp

    r21a99cc ra554e5f4  
    1010// Created On       : Wed May  8 13:00:00 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 17:44:46 2022
    13 // Update Count     : 24
     12// Last Modified On : Wed Feb  2 20:06:41 2022
     13// Update Count     : 34
    1414//
    1515
     
    3939        std::vector<Label> labels;
    4040
    41         Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
     41        Stmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    4242                : ParseNode(loc), labels(std::move(labels)) {}
    4343
     
    5555        std::list<ptr<Stmt>> kids;
    5656
    57         CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {},
    58                                  std::vector<Label> && labels = {} )
     57        CompoundStmt(const CodeLocation & loc, const std::list<ptr<Stmt>> && ks = {}, const std::vector<Label> && labels = {} )
    5958                : Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
    6059
     
    7473class NullStmt final : public Stmt {
    7574  public:
    76         NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
     75        NullStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    7776                : Stmt(loc, std::move(labels)) {}
    7877
     
    8887        ptr<Expr> expr;
    8988
    90         ExprStmt( const CodeLocation & loc, const Expr* e, std::vector<Label> && labels = {} )
     89        ExprStmt( const CodeLocation & loc, const Expr* e, const std::vector<Label> && labels = {} )
    9190                : Stmt(loc, std::move(labels)), expr(e) {}
    9291
     
    107106
    108107        AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
    109                          std::vector<ptr<Expr>> && output, std::vector<ptr<Expr>> && input,
    110                          std::vector<ptr<ConstantExpr>> && clobber, std::vector<Label> && gotoLabels,
    111                          std::vector<Label> && labels = {})
     108                         const std::vector<ptr<Expr>> && output, const std::vector<ptr<Expr>> && input,
     109                         const std::vector<ptr<ConstantExpr>> && clobber, const std::vector<Label> && gotoLabels,
     110                         const std::vector<Label> && labels = {})
    112111                : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
    113112                  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
     
    144143
    145144        IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * then,
    146                         const Stmt * else_ = nullptr, std::vector<ptr<Stmt>> && inits = {},
    147                         std::vector<Label> && labels = {} )
     145                        const Stmt * else_ = nullptr, const std::vector<ptr<Stmt>> && inits = {},
     146                        const std::vector<Label> && labels = {} )
    148147                : Stmt(loc, std::move(labels)), cond(cond), then(then), else_(else_),
    149148                  inits(std::move(inits)) {}
     
    161160        std::vector<ptr<Stmt>> stmts;
    162161
    163         SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
    164                                 std::vector<Label> && labels = {} )
     162        SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
     163                                const std::vector<Label> && labels = {} )
    165164                : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
    166165
     
    178177        std::vector<ptr<Stmt>> stmts;
    179178
    180         CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
    181                           std::vector<Label> && labels = {} )
     179        CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
     180                          const std::vector<Label> && labels = {} )
    182181                : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
    183182
     
    200199
    201200        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
    202                            std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
     201                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
    203202                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    204203
    205204        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
    206                            std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
     205                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
    207206                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    208207
     
    222221        ptr<Stmt> else_;
    223222
    224         ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
    225                          const Expr * inc, const Stmt * body, std::vector<Label> && label = {} )
     223        ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
     224                         const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
    226225                : Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(nullptr) {}
    227226
    228         ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
    229                          const Expr * inc, const Stmt * body, const Stmt * else_, std::vector<Label> && labels = {} )
     227        ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
     228                         const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} )
    230229                : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(else_) {}
    231230
     
    247246        Kind kind;
    248247
    249         BranchStmt( const CodeLocation & loc, Kind kind, Label target,
    250                                 std::vector<Label> && labels = {} );
    251         BranchStmt( const CodeLocation & loc, const Expr * computedTarget,
    252                                 std::vector<Label> && labels = {} )
    253                 : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
    254                   computedTarget(computedTarget), kind(Goto) {}
     248        BranchStmt( const CodeLocation & loc, Kind kind, Label target, const std::vector<Label> && labels = {} );
     249        BranchStmt( const CodeLocation & loc, const Expr * computedTarget, const std::vector<Label> && labels = {} )
     250                : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), computedTarget(computedTarget), kind(Goto) {}
    255251
    256252        const char * kindName() const { return kindNames[kind]; }
     
    269265        ptr<Expr> expr;
    270266
    271         ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )
     267        ReturnStmt( const CodeLocation & loc, const Expr * expr, const std::vector<Label> && labels = {} )
    272268                : Stmt(loc, std::move(labels)), expr(expr) {}
    273269
     
    288284        ExceptionKind kind;
    289285
    290         ThrowStmt(
    291                 const CodeLocation & loc, ExceptionKind kind, const Expr * expr, const Expr * target,
    292                 std::vector<Label> && labels = {} )
     286        ThrowStmt( const CodeLocation & loc, ExceptionKind kind, const Expr * expr,
     287                           const Expr * target, const std::vector<Label> && labels = {} )
    293288                : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
    294289
     
    306301        ptr<FinallyStmt> finally;
    307302
    308         TryStmt(
    309                 const CodeLocation & loc, const CompoundStmt * body,
    310                 std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
    311                 std::vector<Label> && labels = {} )
     303        TryStmt( const CodeLocation & loc, const CompoundStmt * body,
     304                         const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
     305                         const std::vector<Label> && labels = {} )
    312306                : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
    313307
     
    326320        ExceptionKind kind;
    327321
    328         CatchStmt(
    329                 const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
    330                 const Stmt * body, std::vector<Label> && labels = {} )
     322        CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
     323                           const Stmt * body, const std::vector<Label> && labels = {} )
    331324                : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
    332325
     
    358351        enum Type { None, Coroutine, Generator } type = None;
    359352
    360         SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )
     353        SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )
    361354                : Stmt(loc, std::move(labels)), then(then), type(type) {}
    362355
     
    396389        OrElse orElse;
    397390
    398         WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
     391        WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    399392                : Stmt(loc, std::move(labels)) {}
    400393
     
    410403        ptr<Decl> decl;
    411404
    412         DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )
     405        DeclStmt( const CodeLocation & loc, const Decl * decl, const std::vector<Label> && labels = {} )
    413406                : Stmt(loc, std::move(labels)), decl(decl) {}
    414407
     
    441434
    442435        MutexStmt( const CodeLocation & loc, const Stmt * stmt,
    443                            std::vector<ptr<Expr>> && mutexes, std::vector<Label> && labels = {} )
     436                           const std::vector<ptr<Expr>> && mutexes, const std::vector<Label> && labels = {} )
    444437                : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
    445438
  • src/CodeGen/CodeGenerator.cc

    r21a99cc ra554e5f4  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 16:29:25 2022
    13 // Update Count     : 540
     12// Last Modified On : Wed Feb  2 20:30:30 2022
     13// Update Count     : 541
    1414//
    1515#include "CodeGenerator.h"
     
    10201020                        output << "fallthru";
    10211021                        break;
     1022                  default: ;                                                                    // prevent warning
    10221023                } // switch
    10231024                // print branch target for labelled break/continue/fallthru in debug mode
  • src/Common/CodeLocation.h

    r21a99cc ra554e5f4  
    2626        CodeLocation() = default;
    2727
     28
    2829        /// Create a new CodeLocation with the given values.
    2930        CodeLocation( const char* filename, int lineno )
     
    3334
    3435        CodeLocation( const CodeLocation& rhs ) = default;
     36        CodeLocation( CodeLocation&& rhs ) = default;
     37        CodeLocation& operator=( const CodeLocation & ) = default;
     38        CodeLocation& operator=( CodeLocation && ) = default;
    3539
    3640        bool isSet () const {
  • src/Common/utility.h

    r21a99cc ra554e5f4  
    371371}
    372372
     373template< typename T >
     374struct enumerate_t {
     375        template<typename val_t>
     376        struct value_t {
     377                val_t & val;
     378                size_t idx;
     379        };
     380
     381        template< typename iter_t, typename val_t >
     382        struct iterator_t {
     383                iter_t it;
     384                size_t idx;
     385
     386                iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}
     387
     388                value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }
     389
     390                bool operator==(const iterator_t & o) const { return o.it == it; }
     391                bool operator!=(const iterator_t & o) const { return o.it != it; }
     392
     393                iterator_t & operator++() {
     394                        it++;
     395                        idx++;
     396                        return *this;
     397                }
     398
     399                using difference_type   = typename std::iterator_traits< iter_t >::difference_type;
     400                using value_type        = value_t<val_t>;
     401                using pointer           = value_t<val_t> *;
     402                using reference         = value_t<val_t> &;
     403                using iterator_category = std::forward_iterator_tag;
     404        };
     405
     406        T & ref;
     407
     408        using iterator = iterator_t< typename T::iterator, typename T::value_type >;
     409        using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;
     410
     411        iterator begin() { return iterator( ref.begin(), 0 ); }
     412        iterator end()   { return iterator( ref.end(), ref.size() ); }
     413
     414        const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }
     415        const_iterator end()   const { return const_iterator( ref.cend(), ref.size() ); }
     416
     417        const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }
     418        const_iterator cend()   const { return const_iterator( ref.cend(), ref.size() ); }
     419};
     420
     421template< typename T >
     422enumerate_t<T> enumerate( T & ref ) {
     423        return enumerate_t< T >{ ref };
     424}
     425
     426template< typename T >
     427const enumerate_t< const T > enumerate( const T & ref ) {
     428        return enumerate_t< const T >{ ref };
     429}
     430
    373431template< typename OutType, typename Range, typename Functor >
    374432OutType map_range( const Range& range, Functor&& functor ) {
  • src/ControlStruct/ExceptTranslate.h

    r21a99cc ra554e5f4  
    3131
    3232        void translateTries( std::list< Declaration *> & translationUnit );
     33        void translateTries( ast::TranslationUnit & transUnit );
    3334        /* Replaces all try blocks (and their many clauses) with function definitions and calls.
    3435         * This uses the exception built-ins to produce typed output and should take place after
  • src/ControlStruct/ExceptTranslateNew.cpp

    r21a99cc ra554e5f4  
    2020#include "AST/Stmt.hpp"
    2121#include "AST/TranslationUnit.hpp"
     22#include "AST/DeclReplacer.hpp"
    2223
    2324namespace ControlStruct {
     25
     26namespace {
     27
     28        typedef std::list<ast::CatchStmt*> CatchList;
     29
     30        void split( CatchList& allHandlers, CatchList& terHandlers,
     31                                CatchList& resHandlers ) {
     32                while ( !allHandlers.empty() ) {
     33                        ast::CatchStmt * stmt = allHandlers.front();
     34                        allHandlers.pop_front();
     35                        if (stmt->kind == ast::ExceptionKind::Terminate) {
     36                                terHandlers.push_back(stmt);
     37                        } else {
     38                                resHandlers.push_back(stmt);
     39                        }
     40                }
     41        }
     42
     43        void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
     44                block->push_back(new ast::DeclStmt(block->location, item));
     45        }
    2446
    2547class TranslateThrowsCore : public ast::WithGuards {
     
    126148}
    127149
     150
     151class TryMutatorCore {
     152        // The built in types used in translation.
     153        const ast::StructDecl * except_decl;
     154        const ast::StructDecl * node_decl;
     155        const ast::StructDecl * hook_decl;
     156
     157        // The many helper functions for code/syntree generation.
     158        ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt );
     159        ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body );
     160        ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
     161        ast::CompoundStmt * create_single_matcher(
     162                const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler );
     163        ast::FunctionDecl * create_terminate_match( CatchList &handlers );
     164        ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
     165                ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
     166        ast::FunctionDecl * create_resume_handler( CatchList &handlers );
     167        ast::CompoundStmt * create_resume_wrapper(
     168                const ast::Stmt * wraps, const ast::FunctionDecl * resume_handler );
     169        ast::FunctionDecl * create_finally_wrapper( ast::TryStmt * tryStmt );
     170        ast::ObjectDecl * create_finally_hook( ast::FunctionDecl * finally_wrapper );
     171        ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
     172
     173        // Types used in translation, make sure to use clone.
     174        // void (*function)();
     175        ast::FunctionDecl * try_func_t;
     176        // void (*function)(int, exception);
     177        ast::FunctionDecl * catch_func_t;
     178        // int (*function)(exception);
     179        ast::FunctionDecl * match_func_t;
     180        // bool (*function)(exception);
     181        ast::FunctionDecl * handle_func_t;
     182        // void (*function)(__attribute__((unused)) void *);
     183        ast::FunctionDecl * finally_func_t;
     184
     185        ast::StructInstType * create_except_type() {
     186                assert( except_decl );
     187                return new ast::StructInstType( except_decl );
     188        }
     189        void init_func_types();
     190
     191public:
     192        TryMutatorCore() :
     193                except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr )
     194        {}
     195
     196        void previsit( const ast::StructDecl *structDecl );
     197        ast::Stmt * postvisit( const ast::TryStmt *tryStmt );
     198        ast::Stmt * postvisit( const ast::ThrowStmt *throwStmt );
     199};
     200
     201void TryMutatorCore::init_func_types() {
     202        assert( except_decl );
     203
     204        ast::ObjectDecl index_obj(
     205                {},
     206                "__handler_index",
     207                new ast::BasicType(ast::BasicType::SignedInt)
     208                );
     209        ast::ObjectDecl exception_obj(
     210                {},
     211                "__exception_inst",
     212                new ast::PointerType(
     213                        new ast::StructInstType( except_decl )
     214                        ),
     215                NULL
     216                );
     217        ast::ObjectDecl bool_obj(
     218                {},
     219                "__ret_bool",
     220                new ast::BasicType( ast::BasicType::Bool ),
     221                nullptr, //init
     222                ast::Storage::Classes{},
     223                ast::Linkage::Cforall,
     224                nullptr, //width
     225                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
     226                );
     227        ast::ObjectDecl voidptr_obj(
     228                {},
     229                "__hook",
     230                new ast::PointerType(
     231                        new ast::VoidType()
     232                ),
     233                nullptr, //init
     234                ast::Storage::Classes{},
     235                ast::Linkage::Cforall,
     236                nullptr, //width
     237                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
     238                );
     239
     240        ast::ObjectDecl unused_index_obj(
     241                {},
     242                "__handler_index",
     243                new ast::BasicType(ast::BasicType::SignedInt),
     244                nullptr,
     245                ast::Storage::Classes{},
     246                ast::Linkage::Cforall,
     247                nullptr, //width
     248                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
     249        );
     250        //unused_index_obj->attributes.push_back( new Attribute( "unused" ) );
     251
     252        try_func_t = new ast::FunctionDecl(
     253                {},
     254                "try",
     255                {}, //forall
     256                {}, //no param
     257                {}, //no return
     258                nullptr,
     259                ast::Storage::Classes{},
     260                ast::Linkage::Cforall
     261        );
     262
     263        catch_func_t = new ast::FunctionDecl(
     264                {},
     265                "catch",
     266                {}, //forall
     267                {ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param
     268                {}, //return void
     269                nullptr,
     270                ast::Storage::Classes{},
     271                ast::Linkage::Cforall
     272        );
     273
     274        match_func_t = new ast::FunctionDecl(
     275                {},
     276                "match",
     277                {}, //forall
     278                {ast::deepCopy(&exception_obj)},
     279                {ast::deepCopy(&unused_index_obj)},
     280                nullptr,
     281                ast::Storage::Classes{},
     282                ast::Linkage::Cforall
     283        );
     284
     285        handle_func_t = new ast::FunctionDecl(
     286                {},
     287                "handle",
     288                {}, //forall
     289                {ast::deepCopy(&exception_obj)},
     290                {ast::deepCopy(&bool_obj)},
     291                nullptr,
     292                ast::Storage::Classes{},
     293                ast::Linkage::Cforall
     294        );
     295
     296        finally_func_t = new ast::FunctionDecl(
     297                {},
     298                "finally",
     299                {}, //forall
     300                {ast::deepCopy(&voidptr_obj)},
     301                {}, //return void
     302                nullptr,
     303                ast::Storage::Classes{},
     304                ast::Linkage::Cforall
     305        );
     306
     307        //catch_func_t.get_parameters().push_back( index_obj.clone() );
     308        //catch_func_t.get_parameters().push_back( exception_obj.clone() );
     309        //match_func_t.get_returnVals().push_back( unused_index_obj );
     310        //match_func_t.get_parameters().push_back( exception_obj.clone() );
     311        //handle_func_t.get_returnVals().push_back( bool_obj.clone() );
     312        //handle_func_t.get_parameters().push_back( exception_obj.clone() );
     313        //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
     314}
     315
     316// TryStmt Mutation Helpers
     317
     318/*
     319ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {
     320        ast::CompoundStmt * block = tryStmt->body;
     321        tryStmt->body = nullptr;
     322        return block;
     323}
     324*/
     325
     326ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
     327                const ast::CompoundStmt *body ) {
     328
     329        ast::FunctionDecl * ret = ast::deepCopy(try_func_t);
     330        ret->stmts = body;
     331        return ret;
     332}
     333
     334ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
     335                CatchList &handlers ) {
     336        std::vector<ast::ptr<ast::Stmt>> handler_wrappers;
     337
     338        assert (!handlers.empty());
     339        const CodeLocation loc = handlers.front()->location;
     340
     341        ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);
     342        const ast::DeclWithType * index_obj = func_t->params.front();
     343        const ast::DeclWithType * except_obj = func_t->params.back();
     344
     345        // Index 1..{number of handlers}
     346        int index = 0;
     347        CatchList::iterator it = handlers.begin();
     348        for ( ; it != handlers.end() ; ++it ) {
     349                ++index;
     350                ast::CatchStmt * handler = *it;
     351                const CodeLocation loc = handler->location;
     352
     353                // case `index`:
     354                // {
     355                //     `handler.decl` = { (virtual `decl.type`)`except` };
     356                //     `handler.body`;
     357                // }
     358                // return;
     359                ast::CompoundStmt * block = new ast::CompoundStmt(loc);
     360
     361                // Just copy the exception value. (Post Validation)
     362                const ast::ObjectDecl * handler_decl =
     363                        handler->decl.strict_as<ast::ObjectDecl>();
     364                ast::ObjectDecl * local_except = ast::deepCopy(handler_decl);
     365                ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
     366                        new ast::VariableExpr( loc, except_obj ),
     367                        local_except->get_type()
     368                        );
     369                vcex->location = handler->location;
     370                local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) });
     371                block->push_back( new ast::DeclStmt( loc, local_except ) );
     372
     373                // Add the cleanup attribute.
     374                local_except->attributes.push_back( new ast::Attribute(
     375                        "cleanup",
     376                        { new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) }
     377                        ) );
     378
     379                ast::DeclReplacer::DeclMap mapping;
     380                mapping[handler_decl] = local_except;
     381                const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>(
     382                        ast::DeclReplacer::replace(handler->body, mapping));
     383
     384
     385                block->push_back( mutBody );
     386                // handler->body = nullptr;
     387
     388                handler_wrappers.push_back( new ast::CaseStmt(loc,
     389                        ast::ConstantExpr::from_int(loc, index) ,
     390                        { block, new ast::ReturnStmt( loc, nullptr ) }
     391                        ));
     392        }
     393        // TODO: Some sort of meaningful error on default perhaps?
     394
     395        /*
     396        std::list<Statement*> stmt_handlers;
     397        while ( !handler_wrappers.empty() ) {
     398                stmt_handlers.push_back( handler_wrappers.front() );
     399                handler_wrappers.pop_front();
     400        }
     401        */
     402
     403        ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc,
     404                new ast::VariableExpr( loc, index_obj ),
     405                std::move(handler_wrappers)
     406                );
     407        ast::CompoundStmt * body = new ast::CompoundStmt(loc,
     408                {handler_lookup});
     409
     410        func_t->stmts = body;
     411        return func_t;
     412}
     413
     414// Create a single check from a moddified handler.
     415// except_obj is referenced, modded_handler will be freed.
     416ast::CompoundStmt * TryMutatorCore::create_single_matcher(
     417                const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler ) {
     418        // {
     419        //     `modded_handler.decl`
     420        //     if ( `decl.name = (virtual `decl.type`)`except`
     421        //             [&& `modded_handler.cond`] ) {
     422        //         `modded_handler.body`
     423        //     }
     424        // }
     425
     426        const CodeLocation loc = modded_handler->location;
     427        ast::CompoundStmt * block = new ast::CompoundStmt(loc);
     428
     429        // Local Declaration
     430        const ast::ObjectDecl * local_except =
     431                modded_handler->decl.strict_as<ast::ObjectDecl>();
     432        block->push_back( new ast::DeclStmt( loc,  local_except ) );
     433
     434        // Check for type match.
     435        ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
     436                new ast::VariableExpr(loc, except_obj ),
     437                local_except->get_type()
     438                );
     439        ast::Expr * cond = ast::UntypedExpr::createAssign(loc,
     440                new ast::VariableExpr(loc, local_except ), vcex );
     441
     442        // Add the check on the conditional if it is provided.
     443        if ( modded_handler->cond ) {
     444                cond = new ast::LogicalExpr( loc, cond, modded_handler->cond, ast::LogicalFlag::AndExpr );
     445        }
     446        // Construct the match condition.
     447        block->push_back( new ast::IfStmt(loc,
     448                cond, modded_handler->body, nullptr ) );
     449
     450        // xxx - how does this work in new ast
     451        //modded_handler->set_decl( nullptr );
     452        //modded_handler->set_cond( nullptr );
     453        //modded_handler->set_body( nullptr );
     454        //delete modded_handler;
     455        return block;
     456}
     457
     458ast::FunctionDecl * TryMutatorCore::create_terminate_match(
     459                CatchList &handlers ) {
     460        // int match(exception * except) {
     461        //     HANDLER WRAPPERS { return `index`; }
     462        // }
     463
     464        assert (!handlers.empty());
     465        const CodeLocation loc = handlers.front()->location;
     466
     467        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
     468
     469        ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);
     470        const ast::DeclWithType * except_obj = func_t->params.back();
     471
     472        // Index 1..{number of handlers}
     473        int index = 0;
     474        CatchList::iterator it;
     475        for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
     476                ++index;
     477                ast::CatchStmt * handler = *it;
     478
     479                // Body should have been taken by create_terminate_catch.
     480                // xxx - just ignore it?
     481                // assert( nullptr == handler->get_body() );
     482
     483                // Create new body.
     484                handler->body = new ast::ReturnStmt( handler->location,
     485                        ast::ConstantExpr::from_int( handler->location, index ) );
     486
     487                // Create the handler.
     488                body->push_back( create_single_matcher( except_obj, handler ) );
     489                *it = nullptr;
     490        }
     491
     492        body->push_back( new ast::ReturnStmt(loc,
     493                ast::ConstantExpr::from_int( loc, 0 ) ));
     494
     495        func_t->stmts = body;
     496
     497        return func_t;
     498}
     499
     500ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
     501                CodeLocation loc,
     502                ast::FunctionDecl * try_wrapper,
     503                ast::FunctionDecl * terminate_catch,
     504                ast::FunctionDecl * terminate_match ) {
     505        // { __cfaehm_try_terminate(`try`, `catch`, `match`); }
     506
     507        ast::UntypedExpr * caller = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
     508                "__cfaehm_try_terminate" ) );
     509        caller->args.push_back( new ast::VariableExpr(loc, try_wrapper ) );
     510        caller->args.push_back( new ast::VariableExpr(loc, terminate_catch ) );
     511        caller->args.push_back( new ast::VariableExpr(loc, terminate_match ) );
     512
     513        ast::CompoundStmt * callStmt = new ast::CompoundStmt(loc);
     514        callStmt->push_back( new ast::ExprStmt( loc, caller ) );
     515        return callStmt;
     516}
     517
     518ast::FunctionDecl * TryMutatorCore::create_resume_handler(
     519                CatchList &handlers ) {
     520        // bool handle(exception * except) {
     521        //     HANDLER WRAPPERS { `hander->body`; return true; }
     522        // }
     523        assert (!handlers.empty());
     524        const CodeLocation loc = handlers.front()->location;
     525        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
     526
     527        ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);
     528        const ast::DeclWithType * except_obj = func_t->params.back();
     529
     530        CatchList::iterator it;
     531        for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
     532                ast::CatchStmt * handler = *it;
     533                const CodeLocation loc = handler->location;
     534                // Modifiy body.
     535                ast::CompoundStmt * handling_code;
     536                if (handler->body.as<ast::CompoundStmt>()) {
     537                        handling_code =
     538                        strict_dynamic_cast<ast::CompoundStmt*>( handler->body.get_and_mutate() );
     539                } else {
     540                        handling_code = new ast::CompoundStmt(loc);
     541                        handling_code->push_back( handler->body );
     542                }
     543                handling_code->push_back( new ast::ReturnStmt(loc,
     544                        ast::ConstantExpr::from_bool(loc, true ) ) );
     545                handler->body = handling_code;
     546
     547                // Create the handler.
     548                body->push_back( create_single_matcher( except_obj, handler ) );
     549                *it = nullptr;
     550        }
     551
     552        body->push_back( new ast::ReturnStmt(loc,
     553                ast::ConstantExpr::from_bool(loc, false ) ) );
     554        func_t->stmts = body;
     555
     556        return func_t;
     557}
     558
     559ast::CompoundStmt * TryMutatorCore::create_resume_wrapper(
     560                const ast::Stmt * wraps,
     561                const ast::FunctionDecl * resume_handler ) {
     562        const CodeLocation loc = wraps->location;
     563        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
     564
     565        // struct __try_resume_node __resume_node
     566        //      __attribute__((cleanup( __cfaehm_try_resume_cleanup )));
     567        // ** unwinding of the stack here could cause problems **
     568        // ** however I don't think that can happen currently **
     569        // __cfaehm_try_resume_setup( &__resume_node, resume_handler );
     570
     571        ast::ObjectDecl * obj = new ast::ObjectDecl(
     572                loc,
     573                "__resume_node",
     574                new ast::StructInstType(
     575                        node_decl
     576                        ),
     577                nullptr,
     578                ast::Storage::Classes{},
     579                ast::Linkage::Cforall,
     580                nullptr,
     581                {new ast::Attribute("cleanup", {new ast::NameExpr(loc, "__cfaehm_try_resume_cleanup")})}
     582                );
     583        appendDeclStmt( body, obj );
     584
     585        ast::UntypedExpr *setup = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
     586                "__cfaehm_try_resume_setup" ) );
     587        setup->args.push_back( new ast::AddressExpr( loc, new ast::VariableExpr(loc, obj ) ) );
     588        setup->args.push_back( new ast::VariableExpr( loc, resume_handler ) );
     589
     590        body->push_back( new ast::ExprStmt(loc, setup ) );
     591
     592        body->push_back( wraps );
     593        return body;
     594}
     595
     596ast::FunctionDecl * TryMutatorCore::create_finally_wrapper(
     597                ast::TryStmt * tryStmt ) {
     598        // void finally() { `finally->block` }
     599        const ast::FinallyStmt * finally = tryStmt->finally;
     600        const ast::CompoundStmt * body = finally->body;
     601
     602        ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);
     603        func_t->stmts = body;
     604
     605        // finally->set_block( nullptr );
     606        // delete finally;
     607        tryStmt->finally = nullptr;
     608
     609
     610        return func_t;
     611}
     612
     613ast::ObjectDecl * TryMutatorCore::create_finally_hook(
     614                ast::FunctionDecl * finally_wrapper ) {
     615        // struct __cfaehm_cleanup_hook __finally_hook
     616        //      __attribute__((cleanup( `finally_wrapper` )));
     617
     618        const CodeLocation loc = finally_wrapper->location;
     619        // Make Cleanup Attribute.
     620        /*
     621        std::list< ast::Attribute * > attributes;
     622        {
     623                std::list<  > attr_params;
     624                attr_params.push_back( nameOf( finally_wrapper ) );
     625                attributes.push_back( new Attribute( "cleanup", attr_params ) );
     626        }
     627        */
     628
     629        return new ast::ObjectDecl(
     630                loc,
     631                "__finally_hook",
     632                new ast::StructInstType(
     633                        hook_decl
     634                        ),
     635                nullptr,
     636                ast::Storage::Classes{},
     637                ast::Linkage::Cforall,
     638                nullptr,
     639                {new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})}
     640                );
     641}
     642
     643ast::Stmt * TryMutatorCore::create_resume_rethrow( const ast::ThrowStmt *throwStmt ) {
     644        // return false;
     645        const CodeLocation loc = throwStmt->location;
     646        ast::Stmt * result = new ast::ReturnStmt(loc,
     647                ast::ConstantExpr::from_bool( loc, false )
     648                );
     649        result->labels = throwStmt->labels;
     650        // delete throwStmt; done by postvisit
     651        return result;
     652}
     653
     654// Visiting/Mutating Functions
     655void TryMutatorCore::previsit( const ast::StructDecl *structDecl ) {
     656        if ( !structDecl->body ) {
     657                // Skip children?
     658                return;
     659        } else if ( structDecl->name == "__cfaehm_base_exception_t" ) {
     660                assert( nullptr == except_decl );
     661                except_decl = structDecl;
     662                init_func_types();
     663        } else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
     664                assert( nullptr == node_decl );
     665                node_decl = structDecl;
     666        } else if ( structDecl->name == "__cfaehm_cleanup_hook" ) {
     667                assert( nullptr == hook_decl );
     668                hook_decl = structDecl;
     669        }
     670}
     671
     672ast::Stmt * TryMutatorCore::postvisit( const ast::TryStmt *tryStmt ) {
     673        assert( except_decl );
     674        assert( node_decl );
     675        assert( hook_decl );
     676
     677        const CodeLocation loc = tryStmt->location;
     678        ast::TryStmt * mutStmt = mutate(tryStmt);
     679        // Generate a prefix for the function names?
     680
     681        ast::CompoundStmt * block = new ast::CompoundStmt( loc );
     682        // ast::CompoundStmt * inner = take_try_block( mutStmt );
     683        // this is never mutated so let node deletion do its job?
     684        const ast::CompoundStmt * inner = mutStmt->body;
     685
     686        if ( mutStmt->finally ) {
     687                // Define the helper function.
     688                ast::FunctionDecl * finally_block =
     689                        create_finally_wrapper( mutStmt );
     690                appendDeclStmt( block, finally_block );
     691                // Create and add the finally cleanup hook.
     692                appendDeclStmt( block, create_finally_hook( finally_block ) );
     693        }
     694
     695        CatchList termination_handlers;
     696        CatchList resumption_handlers;
     697
     698        for (auto & handler: mutStmt->handlers) {
     699                // xxx - should always be unique? mutate as safe const-cast
     700                assert(handler->unique());
     701                if (handler->kind == ast::ExceptionKind::Resume) {
     702                        resumption_handlers.push_back(handler.get_and_mutate());
     703                }
     704                else {
     705                        termination_handlers.push_back(handler.get_and_mutate());
     706                }
     707        }
     708        // split( mutStmt->handlers,
     709        //              termination_handlers, resumption_handlers );
     710
     711        if ( resumption_handlers.size() ) {
     712                // Define the helper function.
     713                ast::FunctionDecl * resume_handler =
     714                        create_resume_handler( resumption_handlers );
     715                appendDeclStmt( block, resume_handler );
     716                // Prepare hooks
     717                inner = create_resume_wrapper( inner, resume_handler );
     718        }
     719
     720        if ( termination_handlers.size() ) {
     721                // Define the three helper functions.
     722                ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
     723                appendDeclStmt( block, try_wrapper );
     724                ast::FunctionDecl * terminate_catch =
     725                        create_terminate_catch( termination_handlers );
     726                appendDeclStmt( block, terminate_catch );
     727                ast::FunctionDecl * terminate_match =
     728                        create_terminate_match( termination_handlers );
     729                appendDeclStmt( block, terminate_match );
     730                // Build the call to the try wrapper.
     731                inner = create_terminate_caller(inner->location,
     732                        try_wrapper, terminate_catch, terminate_match );
     733        }
     734
     735        // Embed the try block.
     736        block->push_back( inner );
     737
     738        return block;
     739}
     740
     741ast::Stmt * TryMutatorCore::postvisit( const ast::ThrowStmt *throwStmt ) {
     742        // Only valid `throwResume;` statements should remain. (2/3 checks)
     743        assert( ast::ExceptionKind::Resume == throwStmt->kind && ! throwStmt->expr );
     744        return create_resume_rethrow( throwStmt );
     745}
     746
     747} // namespace
     748
    128749void translateThrows( ast::TranslationUnit & transUnit ) {
    129750        ast::Pass<TranslateThrowsCore>::run( transUnit );
     751}
     752
     753void translateTries( ast::TranslationUnit & transUnit ) {
     754        ast::Pass<TryMutatorCore>::run(transUnit);
    130755}
    131756
  • src/ControlStruct/MLEMutator.cc

    r21a99cc ra554e5f4  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 09:26:28 2022
    13 // Update Count     : 225
     12// Last Modified On : Wed Feb  2 20:18:57 2022
     13// Update Count     : 227
    1414//
    1515
     
    136136                        }
    137137                }
    138                 assertf( false, "Could not find label '%s' on statement %s",
     138                assertf( false, "CFA internal error: could not find label '%s' on statement %s",
    139139                        originalTarget.get_name().c_str(), toString( stmt ).c_str() );
    140140        }
     
    395395                }
    396396                assert( ! enclosingControlStructures.empty() );
    397                 assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), "Control structure enclosing a case clause must be a switch, but is: %s", toCString( enclosingControlStructures.back().get_controlStructure() ) );
     397                assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ),
     398                                 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s",
     399                                 toCString( enclosingControlStructures.back().get_controlStructure() ) );
    398400                if ( caseStmt->isDefault() ) {
    399401                        if ( enclosingControlStructures.back().isFallDefaultUsed() ) {
  • src/ControlStruct/MultiLevelExit.cpp

    r21a99cc ra554e5f4  
    1010// Created On       : Mon Nov  1 13:48:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 18:48:47 2022
    13 // Update Count     : 29
     12// Last Modified On : Wed Feb  2 23:07:54 2022
     13// Update Count     : 33
    1414//
    1515
     
    4949                return target.label;
    5050        }
    51 
    5251  public:
    5352        Entry( const ForStmt * stmt, Label breakExit, Label contExit ) :
     
    168167
    169168        // if the stmt is labelled then generate a label to check in postvisit if the label is used
    170         bool isLabeled = !stmt->labels.empty();
     169        bool isLabeled = ! stmt->labels.empty();
    171170        if ( isLabeled ) {
    172171                Label breakLabel = newLabel( "blockBreak", stmt );
     
    180179
    181180        if ( isLabeled ) {
    182                 assert( !enclosing_control_structures.empty() );
     181                assert( ! enclosing_control_structures.empty() );
    183182                Entry & entry = enclosing_control_structures.back();
    184                 if ( !entry.useBreakExit().empty() ) {
     183                if ( ! entry.useBreakExit().empty() ) {
    185184                        break_label = entry.useBreakExit();
    186185                }
     
    206205                }
    207206        }
    208         assertf( false, "Could not find label '%s' on statement %s",
     207        assertf( false, "CFA internal error: could not find label '%s' on statement %s",
    209208                         originalTarget.name.c_str(), toString( stmt ).c_str() );
    210209}
     
    254253                  }
    255254                  // Ensure that selected target is valid.
    256                   if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && !isContinueTarget( *targetEntry ) ) ) {
     255                  if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
    257256                          SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
    258257                                                        " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
     
    268267                          SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    269268                  }
    270                   if ( !stmt->target.empty() ) {
     269                  if ( ! stmt->target.empty() ) {
    271270                          // Labelled fallthrough: target must be a valid fallthough label.
    272                           if ( !fallthrough_labels.count( stmt->target ) ) {
     271                          if ( ! fallthrough_labels.count( stmt->target ) ) {
    273272                                  SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
    274273                                                                                                                   stmt->originalTarget ) );
    275274                          }
    276                           return new BranchStmt(
    277                                   stmt->location, BranchStmt::Goto, stmt->originalTarget );
     275                          return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
    278276                  }
    279277                  break;
     
    307305        }
    308306
    309         // Branch error checks: get the appropriate label name:
    310         // (This label is always replaced.)
     307        // Branch error checks: get the appropriate label name, which is always replaced.
    311308        Label exitLabel( CodeLocation(), "" );
    312309        switch ( stmt->kind ) {
    313310          case BranchStmt::Break:
    314                 assert( !targetEntry->useBreakExit().empty() );
     311                assert( ! targetEntry->useBreakExit().empty() );
    315312                exitLabel = targetEntry->useBreakExit();
    316313                break;
    317314          case BranchStmt::Continue:
    318                 assert( !targetEntry->useContExit().empty() );
     315                assert( ! targetEntry->useContExit().empty() );
    319316                exitLabel = targetEntry->useContExit();
    320317                break;
    321318          case BranchStmt::FallThrough:
    322                 assert( !targetEntry->useFallExit().empty() );
     319                assert( ! targetEntry->useFallExit().empty() );
    323320                exitLabel = targetEntry->useFallExit();
    324321                break;
    325322          case BranchStmt::FallThroughDefault:
    326                 assert( !targetEntry->useFallDefaultExit().empty() );
     323                assert( ! targetEntry->useFallDefaultExit().empty() );
    327324                exitLabel = targetEntry->useFallDefaultExit();
    328325                // Check that fallthrough default comes before the default clause.
    329                 if ( !targetEntry->isFallDefaultValid() ) {
     326                if ( ! targetEntry->isFallDefaultValid() ) {
    330327                        SemanticError( stmt->location, "'fallthrough default' must precede the 'default' clause" );
    331328                }
     
    373370        // If default, mark seen.
    374371        if ( stmt->isDefault() ) {
    375                 assert( !enclosing_control_structures.empty() );
     372                assert( ! enclosing_control_structures.empty() );
    376373                enclosing_control_structures.back().seenDefault();
    377374        }
     
    399396                Entry & entry = enclosing_control_structures.back();
    400397                if ( entry.isFallUsed() ) {
    401                         mutStmt->stmts.push_back(
    402                                 labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
     398                        mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
    403399                }
    404400        }
     
    406402        Entry & entry = enclosing_control_structures.back();
    407403        assertf( dynamic_cast< const SwitchStmt * >( entry.stmt ),
    408                          "Control structure enclosing a case clause must be a switch, but is: %s",
     404                         "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s",
    409405                         toString( entry.stmt ).c_str() );
    410406        if ( mutStmt->isDefault() ) {
    411407                if ( entry.isFallDefaultUsed() ) {
    412408                        // Add fallthrough default label if necessary.
    413                         push_front( mutStmt->stmts, labelledNullStmt(
    414                                                         stmt->location, entry.useFallDefaultExit()
    415                                                         ) );
     409                        push_front( mutStmt->stmts, labelledNullStmt( stmt->location, entry.useFallDefaultExit() ) );
    416410                }
    417411        }
     
    420414
    421415void MultiLevelExitCore::previsit( const IfStmt * stmt ) {
    422         bool labeledBlock = !stmt->labels.empty();
     416        bool labeledBlock = ! stmt->labels.empty();
    423417        if ( labeledBlock ) {
    424418                Label breakLabel = newLabel( "blockBreak", stmt );
     
    429423
    430424const IfStmt * MultiLevelExitCore::postvisit( const IfStmt * stmt ) {
    431         bool labeledBlock = !stmt->labels.empty();
     425        bool labeledBlock = ! stmt->labels.empty();
    432426        if ( labeledBlock ) {
    433427                auto this_label = enclosing_control_structures.back().useBreakExit();
    434                 if ( !this_label.empty() ) {
     428                if ( ! this_label.empty() ) {
    435429                        break_label = this_label;
    436430                }
     
    448442        auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );
    449443
    450         const CaseStmt * defaultCase = it != stmt->stmts.rend()
    451                 ? (it)->strict_as<CaseStmt>() : nullptr;
    452         Label defaultLabel = defaultCase
    453                 ? newLabel( "fallThroughDefault", defaultCase )
    454                 : Label( stmt->location, "" );
     444        const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr;
     445        Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" );
    455446        enclosing_control_structures.emplace_back( stmt, label, defaultLabel );
    456447        GuardAction( [this]() { enclosing_control_structures.pop_back(); } );
    457448
    458         // Collect valid labels for fallthrough. It starts with all labels at
    459         // this level, then remove as each is seen during traversal.
     449        // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during
     450        // traversal.
    460451        for ( const Stmt * stmt : stmt->stmts ) {
    461452                auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt );
     
    471462
    472463const SwitchStmt * MultiLevelExitCore::postvisit( const SwitchStmt * stmt ) {
    473         assert( !enclosing_control_structures.empty() );
     464        assert( ! enclosing_control_structures.empty() );
    474465        Entry & entry = enclosing_control_structures.back();
    475466        assert( entry.stmt == stmt );
     
    477468        // Only run to generate the break label.
    478469        if ( entry.isBreakUsed() ) {
    479                 // To keep the switch statements uniform (all direct children of a
    480                 // SwitchStmt should be CastStmts), append the exit label and break
    481                 // to the last case, create a default case is there are no cases.
     470                // To keep the switch statements uniform (all direct children of a SwitchStmt should be CastStmts), append the
     471                // exit label and break to the last case, create a default case if no cases.
    482472                SwitchStmt * mutStmt = mutate( stmt );
    483473                if ( mutStmt->stmts.empty() ) {
    484                         mutStmt->stmts.push_back( new CaseStmt(
    485                                                                                   mutStmt->location, nullptr, {} ));
     474                        mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) );
    486475                }
    487476
     
    507496
    508497void MultiLevelExitCore::previsit( const TryStmt * stmt ) {
    509         bool isLabeled = !stmt->labels.empty();
     498        bool isLabeled = ! stmt->labels.empty();
    510499        if ( isLabeled ) {
    511500                Label breakLabel = newLabel( "blockBreak", stmt );
     
    516505
    517506void MultiLevelExitCore::postvisit( const TryStmt * stmt ) {
    518         bool isLabeled = !stmt->labels.empty();
     507        bool isLabeled = ! stmt->labels.empty();
    519508        if ( isLabeled ) {
    520509                auto this_label = enclosing_control_structures.back().useBreakExit();
    521                 if ( !this_label.empty() ) {
     510                if ( ! this_label.empty() ) {
    522511                        break_label = this_label;
    523512                }
     
    526515
    527516void MultiLevelExitCore::previsit( const FinallyStmt * ) {
    528         GuardAction([this, old = move(enclosing_control_structures)](){
    529                                         enclosing_control_structures = move(old);
    530                                 });
     517        GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); });
    531518        enclosing_control_structures = vector<Entry>();
    532519        GuardValue( inFinally ) = true;
     
    575562template<typename LoopNode>
    576563const LoopNode * MultiLevelExitCore::posthandleLoopStmt( const LoopNode * loopStmt ) {
    577         assert( !enclosing_control_structures.empty() );
     564        assert( ! enclosing_control_structures.empty() );
    578565        Entry & entry = enclosing_control_structures.back();
    579566        assert( entry.stmt == loopStmt );
    580567
    581568        // Now check if the labels are used and add them if so.
    582         return mutate_field(
    583                 loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) );
     569        return mutate_field( loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) );
    584570        // this call to mutate_field compares loopStmt->body and the result of mutateLoop
    585571        //              if they are the same the node isn't mutated, if they differ then the new mutated node is returned
     
    609595                }
    610596
    611                 if ( !break_label.empty() ) {
    612                         ret.push_back(
    613                                 labelledNullStmt( ret.back()->location, break_label ) );
     597                if ( ! break_label.empty() ) {
     598                        ret.push_back( labelledNullStmt( ret.back()->location, break_label ) );
    614599                        break_label = Label( CodeLocation(), "" );
    615600                }
    616601        }
    617602
    618         if ( !errors.isEmpty() ) {
     603        if ( ! errors.isEmpty() ) {
    619604                throw errors;
    620605        }
  • src/Parser/StatementNode.cc

    r21a99cc ra554e5f4  
    1111// Created On       : Sat May 16 14:59:41 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Wed Feb  2 12:27:58 2022
    14 // Update Count     : 424
     13// Last Modified On : Wed Feb  2 20:29:30 2022
     14// Update Count     : 425
    1515//
    1616
     
    138138
    139139Statement * build_case( ExpressionNode * ctl ) {
    140         return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // no init
     140        return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
    141141} // build_case
    142142
    143143Statement * build_default() {
    144         return new CaseStmt( nullptr, {}, true );                       // no init
     144        return new CaseStmt( nullptr, {}, true );                       // stmt starts empty and then added to
    145145} // build_default
    146146
  • src/SynTree/Statement.cc

    r21a99cc ra554e5f4  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 11:55:19 2022
    13 // Update Count     : 80
     12// Last Modified On : Wed Feb  2 20:19:33 2022
     13// Update Count     : 90
    1414//
    1515
     
    2929#include "SynTree/Label.h"         // for Label, operator<<
    3030
    31 using std::string;
    32 using std::endl;
    33 
    34 Statement::Statement( const std::list<Label> & labels ) : labels( labels ) {}
    35 
    36 void Statement::print( std::ostream & os, Indenter indent ) const {
     31using namespace std;
     32
     33
     34Statement::Statement( const list<Label> & labels ) : labels( labels ) {}
     35
     36void Statement::print( ostream & os, Indenter indent ) const {
    3737        if ( ! labels.empty() ) {
    3838                os << indent << "... Labels: {";
     
    5454}
    5555
    56 void ExprStmt::print( std::ostream & os, Indenter indent ) const {
    57         os << "Expression Statement:" << endl << indent+1;
    58         expr->print( os, indent+1 );
    59 }
    60 
    61 
    62 AsmStmt::AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
     56void ExprStmt::print( ostream & os, Indenter indent ) const {
     57        os << "Expression Statement:" << endl << indent + 1;
     58        expr->print( os, indent + 1 );
     59}
     60
     61
     62AsmStmt::AsmStmt( bool voltile, Expression * instruction, const list<Expression *> output, const list<Expression *> input, const list<ConstantExpr *> clobber, const list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
    6363
    6464AsmStmt::AsmStmt( const AsmStmt & other ) : Statement( other ), voltile( other.voltile ), instruction( maybeClone( other.instruction ) ), gotolabels( other.gotolabels ) {
     
    7575}
    7676
    77 void AsmStmt::print( std::ostream & os, Indenter indent ) const {
     77void AsmStmt::print( ostream & os, Indenter indent ) const {
    7878        os << "Assembler Statement:" << endl;
    79         os << indent+1 << "instruction: " << endl << indent;
    80         instruction->print( os, indent+1 );
     79        os << indent + 1 << "instruction: " << endl << indent;
     80        instruction->print( os, indent + 1 );
    8181        if ( ! output.empty() ) {
    82                 os << endl << indent+1 << "output: " << endl;
    83                 printAll( output, os, indent+1 );
     82                os << endl << indent + 1 << "output: " << endl;
     83                printAll( output, os, indent + 1 );
    8484        } // if
    8585        if ( ! input.empty() ) {
    86                 os << indent+1 << "input: " << endl;
    87                 printAll( input, os, indent+1 );
     86                os << indent + 1 << "input: " << endl;
     87                printAll( input, os, indent + 1 );
    8888        } // if
    8989        if ( ! clobber.empty() ) {
    90                 os << indent+1 << "clobber: " << endl;
    91                 printAll( clobber, os, indent+1 );
     90                os << indent + 1 << "clobber: " << endl;
     91                printAll( clobber, os, indent + 1 );
    9292        } // if
    9393}
    9494
    9595
    96 DirectiveStmt::DirectiveStmt( const std::string & directive ) : Statement(), directive( directive ) {}
    97 
    98 void DirectiveStmt::print( std::ostream & os, Indenter ) const {
     96DirectiveStmt::DirectiveStmt( const string & directive ) : Statement(), directive( directive ) {}
     97
     98void DirectiveStmt::print( ostream & os, Indenter ) const {
    9999        os << "GCC Directive:" << directive << endl;
    100100}
     
    120120}
    121121
    122 void BranchStmt::print( std::ostream & os, Indenter indent ) const {
    123         assert(type < 5);
     122void BranchStmt::print( ostream & os, Indenter indent ) const {
     123        assertf(type < BranchStmts, "CFA internal error: invalid branch statement" );
    124124        os << "Branch (" << brType[type] << ")" << endl ;
    125         if ( target != "" ) os << indent+1 << "with target: " << target << endl;
    126         if ( originalTarget != "" ) os << indent+1 << "with original target: " << originalTarget << endl;
    127         if ( computedTarget != nullptr ) os << indent+1 << "with computed target: " << computedTarget << endl;
     125        if ( target != "" ) os << indent + 1 << "with target: " << target << endl;
     126        if ( originalTarget != "" ) os << indent + 1 << "with original target: " << originalTarget << endl;
     127        if ( computedTarget != nullptr ) os << indent + 1 << "with computed target: " << computedTarget << endl;
    128128}
    129129
     
    136136}
    137137
    138 void ReturnStmt::print( std::ostream & os, Indenter indent ) const {
     138void ReturnStmt::print( ostream & os, Indenter indent ) const {
    139139        os << "Return Statement, returning: ";
    140140        if ( expr != nullptr ) {
    141                 os << endl << indent+1;
    142                 expr->print( os, indent+1 );
     141                os << endl << indent + 1;
     142                expr->print( os, indent + 1 );
    143143        }
    144144        os << endl;
    145145}
    146146
    147 IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, std::list<Statement *> initialization ):
     147IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, const list<Statement *> initialization ):
    148148        Statement(), condition( condition ), then( then ), else_( else_ ), initialization( initialization ) {}
    149149
     
    160160}
    161161
    162 void IfStmt::print( std::ostream & os, Indenter indent ) const {
     162void IfStmt::print( ostream & os, Indenter indent ) const {
    163163        os << "If on condition: " << endl;
    164         os << indent+1;
    165         condition->print( os, indent+1 );
     164        os << indent + 1;
     165        condition->print( os, indent + 1 );
    166166
    167167        if ( !initialization.empty() ) {
    168168                os << indent << "... with initialization: \n";
    169169                for ( const Statement * stmt : initialization ) {
    170                         os << indent+1;
    171                         stmt->print( os, indent+1 );
     170                        os << indent + 1;
     171                        stmt->print( os, indent + 1 );
    172172                }
    173173                os << endl;
     
    176176        os << indent << "... then: " << endl;
    177177
    178         os << indent+1;
    179         then->print( os, indent+1 );
     178        os << indent + 1;
     179        then->print( os, indent + 1 );
    180180
    181181        if ( else_ != nullptr ) {
    182182                os << indent << "... else: " << endl;
    183                 os << indent+1;
    184                 else_->print( os, indent+1 );
     183                os << indent + 1;
     184                else_->print( os, indent + 1 );
    185185        } // if
    186186}
    187187
    188 SwitchStmt::SwitchStmt( Expression * condition, const std::list<Statement *> & statements ):
     188SwitchStmt::SwitchStmt( Expression * condition, const list<Statement *> & statements ):
    189189        Statement(), condition( condition ), statements( statements ) {
    190190}
     
    201201}
    202202
    203 void SwitchStmt::print( std::ostream & os, Indenter indent ) const {
     203void SwitchStmt::print( ostream & os, Indenter indent ) const {
    204204        os << "Switch on condition: ";
    205205        condition->print( os );
     
    207207
    208208        for ( const Statement * stmt : statements ) {
    209                 stmt->print( os, indent+1 );
    210         }
    211 }
    212 
    213 CaseStmt::CaseStmt( Expression * condition, const std::list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :
    214         Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
     209                stmt->print( os, indent + 1 );
     210        }
     211}
     212
     213CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :
     214                Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
    215215        if ( isDefault() && condition != nullptr ) SemanticError( condition, "default case with condition: " );
    216216}
    217217
    218218CaseStmt::CaseStmt( const CaseStmt & other ) :
    219         Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {
     219                Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {
    220220        cloneAll( other.stmts, stmts );
    221221}
     
    226226}
    227227
    228 CaseStmt * CaseStmt::makeDefault( const std::list<Label> & labels, std::list<Statement *> stmts ) {
     228CaseStmt * CaseStmt::makeDefault( const list<Label> & labels, list<Statement *> stmts ) {
    229229        CaseStmt * stmt = new CaseStmt( nullptr, stmts, true );
    230230        stmt->labels = labels;
     
    232232}
    233233
    234 void CaseStmt::print( std::ostream & os, Indenter indent ) const {
     234void CaseStmt::print( ostream & os, Indenter indent ) const {
    235235        if ( isDefault() ) os << indent << "Default ";
    236236        else {
     
    241241
    242242        for ( Statement * stmt : stmts ) {
    243                 os << indent+1;
    244                 stmt->print( os, indent+1 );
    245         }
    246 }
    247 
    248 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const std::list< Statement * > & initialization, bool isDoWhile ):
     243                os << indent + 1;
     244                stmt->print( os, indent + 1 );
     245        }
     246}
     247
     248WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const list< Statement * > & initialization, bool isDoWhile ):
    249249        Statement(), condition( condition ), body( body ), else_( nullptr ), initialization( initialization ), isDoWhile( isDoWhile) {
    250250}
    251251
    252 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const std::list< Statement * > & initialization, bool isDoWhile ):
     252WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const list< Statement * > & initialization, bool isDoWhile ):
    253253        Statement(), condition( condition), body( body ), else_( else_ ), initialization( initialization ), isDoWhile( isDoWhile) {
    254254}
     
    263263}
    264264
    265 void WhileDoStmt::print( std::ostream & os, Indenter indent ) const {
     265void WhileDoStmt::print( ostream & os, Indenter indent ) const {
    266266        os << "While on condition: " << endl ;
    267         condition->print( os, indent+1 );
     267        condition->print( os, indent + 1 );
    268268
    269269        os << indent << "... with body: " << endl;
    270270
    271         if ( body != nullptr ) body->print( os, indent+1 );
    272 }
    273 
    274 ForStmt::ForStmt( std::list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ):
     271        if ( body != nullptr ) body->print( os, indent + 1 );
     272}
     273
     274ForStmt::ForStmt( const list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ):
    275275        Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ), else_( else_ ) {
    276276}
     
    290290}
    291291
    292 void ForStmt::print( std::ostream & os, Indenter indent ) const {
     292void ForStmt::print( ostream & os, Indenter indent ) const {
    293293        Statement::print( os, indent ); // print labels
    294294
     
    298298                os << indent << "... initialization: \n";
    299299                for ( Statement * stmt : initialization ) {
    300                         os << indent+1;
    301                         stmt->print( os, indent+1 );
     300                        os << indent + 1;
     301                        stmt->print( os, indent + 1 );
    302302                }
    303303        }
    304304
    305305        if ( condition != nullptr ) {
    306                 os << indent << "... condition: \n" << indent+1;
    307                 condition->print( os, indent+1 );
     306                os << indent << "... condition: \n" << indent + 1;
     307                condition->print( os, indent + 1 );
    308308        }
    309309
    310310        if ( increment != nullptr ) {
    311                 os << "\n" << indent << "... increment: \n" << indent+1;
    312                 increment->print( os, indent+1 );
     311                os << "\n" << indent << "... increment: \n" << indent + 1;
     312                increment->print( os, indent + 1 );
    313313        }
    314314
    315315        if ( body != nullptr ) {
    316                 os << "\n" << indent << "... with body: \n" << indent+1;
    317                 body->print( os, indent+1 );
     316                os << "\n" << indent << "... with body: \n" << indent + 1;
     317                body->print( os, indent + 1 );
    318318        }
    319319
    320320        if ( else_ != nullptr ) {
    321                 os << "\n" << indent << "... with body: \n" << indent+1;
    322                 else_->print( os, indent+1 );
     321                os << "\n" << indent << "... with body: \n" << indent + 1;
     322                else_->print( os, indent + 1 );
    323323        }
    324324        os << endl;
     
    339339}
    340340
    341 void ThrowStmt::print( std::ostream & os, Indenter indent) const {
     341void ThrowStmt::print( ostream & os, Indenter indent) const {
    342342        if ( target ) os << "Non-Local ";
    343343        os << "Throw Statement, raising: ";
    344         expr->print(os, indent+1);
     344        expr->print(os, indent + 1);
    345345        if ( target ) {
    346346                os << "... at: ";
    347                 target->print(os, indent+1);
    348         }
    349 }
    350 
    351 TryStmt::TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :
     347                target->print(os, indent + 1);
     348        }
     349}
     350
     351TryStmt::TryStmt( CompoundStmt * tryBlock, const list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :
    352352        Statement(), block( tryBlock ),  handlers( handlers ), finallyBlock( finallyBlock ) {
    353353}
     
    363363}
    364364
    365 void TryStmt::print( std::ostream & os, Indenter indent ) const {
     365void TryStmt::print( ostream & os, Indenter indent ) const {
    366366        os << "Try Statement" << endl;
    367         os << indent << "... with block:" << endl << indent+1;
    368         block->print( os, indent+1 );
     367        os << indent << "... with block:" << endl << indent + 1;
     368        block->print( os, indent + 1 );
    369369
    370370        // handlers
    371371        os << indent << "... and handlers:" << endl;
    372372        for ( const CatchStmt * stmt : handlers ) {
    373                 os << indent+1;
    374                 stmt->print( os, indent+1 );
     373                os << indent + 1;
     374                stmt->print( os, indent + 1 );
    375375        }
    376376
    377377        // finally block
    378378        if ( finallyBlock != nullptr ) {
    379                 os << indent << "... and finally:" << endl << indent+1;
    380                 finallyBlock->print( os, indent+1 );
     379                os << indent << "... and finally:" << endl << indent + 1;
     380                finallyBlock->print( os, indent + 1 );
    381381        } // if
    382382}
     
    396396}
    397397
    398 void CatchStmt::print( std::ostream & os, Indenter indent ) const {
     398void CatchStmt::print( ostream & os, Indenter indent ) const {
    399399        os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
    400400
    401401        os << indent << "... catching: ";
    402         decl->printShort( os, indent+1 );
     402        decl->printShort( os, indent + 1 );
    403403        os << endl;
    404404
    405405        if ( cond ) {
    406                 os << indent << "... with conditional:" << endl << indent+1;
    407                 cond->print( os, indent+1 );
     406                os << indent << "... with conditional:" << endl << indent + 1;
     407                cond->print( os, indent + 1 );
    408408        }
    409409
    410410        os << indent << "... with block:" << endl;
    411         os << indent+1;
    412         body->print( os, indent+1 );
     411        os << indent + 1;
     412        body->print( os, indent + 1 );
    413413}
    414414
     
    424424}
    425425
    426 void FinallyStmt::print( std::ostream & os, Indenter indent ) const {
     426void FinallyStmt::print( ostream & os, Indenter indent ) const {
    427427        os << "Finally Statement" << endl;
    428         os << indent << "... with block:" << endl << indent+1;
    429         block->print( os, indent+1 );
     428        os << indent << "... with block:" << endl << indent + 1;
     429        block->print( os, indent + 1 );
    430430}
    431431
     
    439439}
    440440
    441 void SuspendStmt::print( std::ostream & os, Indenter indent ) const {
     441void SuspendStmt::print( ostream & os, Indenter indent ) const {
    442442        os << "Suspend Statement";
    443443        switch (type) {
     
    496496}
    497497
    498 void WaitForStmt::print( std::ostream & os, Indenter indent ) const {
     498void WaitForStmt::print( ostream & os, Indenter indent ) const {
    499499        os << "Waitfor Statement" << endl;
    500500        indent += 1;
     
    531531
    532532
    533 WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
     533WithStmt::WithStmt( const list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
    534534WithStmt::WithStmt( const WithStmt & other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
    535535        cloneAll( other.exprs, exprs );
     
    540540}
    541541
    542 void WithStmt::print( std::ostream & os, Indenter indent ) const {
     542void WithStmt::print( ostream & os, Indenter indent ) const {
    543543        os << "With statement" << endl;
    544544        os << indent << "... with expressions: " << endl;
    545         printAll( exprs, os, indent+1 );
    546         os << indent << "... with statement:" << endl << indent+1;
    547         stmt->print( os, indent+1 );
    548 }
    549 
    550 
    551 NullStmt::NullStmt( const std::list<Label> & labels ) : Statement( labels ) {
    552 }
    553 
    554 void NullStmt::print( std::ostream & os, Indenter indent ) const {
     545        printAll( exprs, os, indent + 1 );
     546        os << indent << "... with statement:" << endl << indent + 1;
     547        stmt->print( os, indent + 1 );
     548}
     549
     550
     551NullStmt::NullStmt( const list<Label> & labels ) : Statement( labels ) {
     552}
     553
     554void NullStmt::print( ostream & os, Indenter indent ) const {
    555555        os << "Null Statement" << endl;
    556556        Statement::print( os, indent );
     
    568568}
    569569
    570 void ImplicitCtorDtorStmt::print( std::ostream & os, Indenter indent ) const {
     570void ImplicitCtorDtorStmt::print( ostream & os, Indenter indent ) const {
    571571        os << "Implicit Ctor Dtor Statement" << endl;
    572572        os << indent << "... with Ctor/Dtor: ";
    573         callStmt->print( os, indent+1);
     573        callStmt->print( os, indent + 1);
    574574        os << endl;
    575575}
    576576
    577 MutexStmt::MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs )
     577MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs )
    578578        : Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
    579579
     
    587587}
    588588
    589 void MutexStmt::print( std::ostream & os, Indenter indent ) const {
     589void MutexStmt::print( ostream & os, Indenter indent ) const {
    590590        os << "Mutex Statement" << endl;
    591591        os << indent << "... with Expressions: " << endl;
    592592        for (auto * obj : mutexObjs) {
    593                 os << indent+1;
    594                 obj->print( os, indent+1);
     593                os << indent + 1;
     594                obj->print( os, indent + 1);
    595595                os << endl;
    596596        }
    597         os << indent << "... with Statement: " << endl << indent+1;
    598         stmt->print( os, indent+1 );
     597        os << indent << "... with Statement: " << endl << indent + 1;
     598        stmt->print( os, indent + 1 );
    599599}
    600600
  • src/SynTree/Statement.h

    r21a99cc ra554e5f4  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 11:49:17 2022
    13 // Update Count     : 94
     12// Last Modified On : Wed Feb  2 20:15:30 2022
     13// Update Count     : 98
    1414//
    1515
     
    107107        std::list<Label> gotolabels;
    108108
    109         AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
     109        AsmStmt( bool voltile, Expression * instruction, const std::list<Expression *> output, const std::list<Expression *> input, const std::list<ConstantExpr *> clobber, const std::list<Label> gotolabels );
    110110        AsmStmt( const AsmStmt & other );
    111111        virtual ~AsmStmt();
     
    153153
    154154        IfStmt( Expression * condition, Statement * then, Statement * else_,
    155                         std::list<Statement *> initialization = std::list<Statement *>() );
     155                        const std::list<Statement *> initialization = std::list<Statement *>() );
    156156        IfStmt( const IfStmt & other );
    157157        virtual ~IfStmt();
     
    260260        Statement * else_;
    261261
    262         ForStmt( std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr );
     262        ForStmt( const std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr );
    263263        ForStmt( const ForStmt & other );
    264264        virtual ~ForStmt();
     
    281281class BranchStmt : public Statement {
    282282  public:
    283         enum Type { Goto = 0, Break, Continue, FallThrough, FallThroughDefault };
     283        enum Type { Goto, Break, Continue, FallThrough, FallThroughDefault, BranchStmts };
    284284
    285285        // originalTarget kept for error messages.
     
    360360        FinallyStmt * finallyBlock;
    361361
    362         TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );
     362        TryStmt( CompoundStmt * tryBlock, const std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );
    363363        TryStmt( const TryStmt & other );
    364364        virtual ~TryStmt();
     
    543543        std::list<Expression *> mutexObjs; // list of mutex objects to acquire
    544544
    545         MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs );
     545        MutexStmt( Statement * stmt, const std::list<Expression *> mutexObjs );
    546546        MutexStmt( const MutexStmt & other );
    547547        virtual ~MutexStmt();
  • src/main.cc

    r21a99cc ra554e5f4  
    415415                        // Currently not working due to unresolved issues with UniqueExpr
    416416                        PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     417
     418                        PASS( "Translate Tries" , ControlStruct::translateTries( transUnit ) );
     419
    417420                        translationUnit = convert( move( transUnit ) );
    418421                } else {
     
    481484
    482485                        PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     486
     487                        PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    483488                }
    484489
    485                 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
     490               
    486491
    487492                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
  • tests/include/.expect/includes.nast.txt

    r21a99cc ra554e5f4  
    1 include/includes.cfa:154:25: warning: Compiled
     1include/includes.cfa:153:25: warning: Compiled
  • tests/include/includes.cfa

    r21a99cc ra554e5f4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun  5 10:06:46 2021
    13 // Update Count     : 751
     12// Last Modified On : Thu Feb  3 22:06:07 2022
     13// Update Count     : 774
    1414//
    1515
     
    1818#endif // __CFA__
    1919
     20#if 1
    2021//#define _GNU_SOURCE
    2122#include <aio.h>
     
    4041#include <errno.h>
    4142#include <error.h>
    42 //#include <eti.h>                                                                              // may not be installed, comes with ncurses
     43//#include <eti.h>                                                                              // may not be installed, comes with ncurses
    4344#include <execinfo.h>
    4445#include <expat.h>
     
    4950#include <fmtmsg.h>
    5051#include <fnmatch.h>
    51 //#include <form.h>                                                                             // may not be installed, comes with ncurses
     52//#include <form.h>                                                                             // may not be installed, comes with ncurses
    5253#include <fstab.h>
    5354#include <fts.h>
     
    7778#include <mcheck.h>
    7879#include <memory.h>
    79 //#include <menu.h>                                                                             // may not be installed, comes with ncurses
     80//#include <menu.h>                                                                             // may not be installed, comes with ncurses
    8081#include <mntent.h>
    8182#include <monetary.h>
    8283#include <mqueue.h>
    83 //#include <ncurses_dll.h>                                                                      // may not be installed, comes with ncurses
     84//#include <ncurses_dll.h>                                                              // may not be installed, comes with ncurses
    8485#include <netdb.h>
    8586#include <nl_types.h>
    8687#include <nss.h>
    8788#include <obstack.h>
    88 //#include <panel.h>                                                                            // may not be installed, comes with ncurses
     89//#include <panel.h>                                                                            // may not be installed, comes with ncurses
    8990#include <paths.h>
    9091#include <poll.h>
     
    117118#include <syslog.h>
    118119#include <tar.h>
    119 //#include <term.h>                                                                             // may not be installed, comes with ncurses
    120 //#include <termcap.h>                                                                          // may not be installed, comes with ncurses
     120//#include <term.h>                                                                             // may not be installed, comes with ncurses
     121//#include <termcap.h>                                                                  // may not be installed, comes with ncurses
    121122#include <termio.h>
    122123#include <termios.h>
     
    130131#include <ucontext.h>
    131132#include <ulimit.h>
    132 //#include <unctrl.h>                                                                           // may not be installed, comes with ncurses
     133//#include <unctrl.h>                                                                           // may not be installed, comes with ncurses
    133134#include <unistd.h>
    134135#include <utime.h>
     
    143144#include <wctype.h>
    144145#include <wordexp.h>
    145 
    146 #if 0
    147146#endif // 0
    148147
     
    151150#endif // __CFA__
    152151
    153 int main( int argc, char const *argv[] ) {
    154     #pragma GCC warning "Compiled"                      // force non-empty .expect file, NO TABS!!!
     152int main( int argc, char const * argv[] ) {
     153    #pragma GCC warning "Compiled"                                                      // force non-empty .expect file, NO TABS!!!
    155154}
    156155
Note: See TracChangeset for help on using the changeset viewer.