Changeset 6840e7c


Ignore:
Timestamp:
Oct 19, 2017, 12:01:04 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
837ce06
Parents:
b96ec83 (diff), a15b72c (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' into cleanup-dtors

Files:
26 added
4 deleted
148 edited
4 moved

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/lstlang.sty

    rb96ec83 r6840e7c  
    22%%
    33%% Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 %% 
    5 %% lstlang.sty -- 
    6 %% 
     4%%
     5%% lstlang.sty --
     6%%
    77%% Author           : Peter A. Buhr
    88%% Created On       : Sat May 13 16:34:42 2017
     
    110110                __attribute__, auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__,
    111111                __const, __const__, disable, dtype, enable, __extension__, fallthrough, fallthru,
    112                 finally, forall, ftype, _Generic, _Imaginary, inline, __label__, lvalue, _Noreturn, one_t, 
    113                 otype, restrict, _Static_assert, throw, throwResume, trait, try, ttype, typeof, __typeof, 
    114                 __typeof__, virtual, waitfor, when, with, zero_t},
     112                finally, forall, ftype, _Generic, _Imaginary, inline, __label__, lvalue, _Noreturn, one_t,
     113                otype, restrict, _Static_assert, throw, throwResume, trait, try, ttype, typeof, __typeof,
     114                __typeof__, virtual, with, zero_t},
    115115        morekeywords=[2]{
    116                 _Atomic, coroutine, is_coroutine, is_monitor, is_thread, monitor, mutex, nomutex,
    117                 resume, suspend, thread, _Thread_local, yield},
     116                _Atomic, coroutine, is_coroutine, is_monitor, is_thread, monitor, mutex, nomutex, or,
     117                resume, suspend, thread, _Thread_local, waitfor, when, yield},
    118118        moredirectives={defined,include_next}%
    119119}
  • doc/proposals/concurrency/Makefile

    rb96ec83 r6840e7c  
    1616text/basics \
    1717text/concurrency \
     18text/internals \
    1819text/parallelism \
     20text/together \
     21text/future \
    1922}
    2023
     
    2326        ext_monitor \
    2427        int_monitor \
     28        dependency \
    2529}}
    2630
  • doc/proposals/concurrency/annex/glossary.tex

    rb96ec83 r6840e7c  
    1313}
    1414
    15 \longnewglossaryentry{group-acquire}
    16 {name={bulk acquiring}}
     15\longnewglossaryentry{bulk-acq}
     16{name={bulk-acquiring}}
    1717{
    1818Implicitly acquiring several monitors when entering a monitor.
     19}
     20
     21\longnewglossaryentry{multi-acq}
     22{name={multiple-acquisition}}
     23{
     24Any locking technique which allow any single thread to acquire a lock multiple times.
    1925}
    2026
     
    101107\newacronym{api}{API}{Application Program Interface}
    102108\newacronym{raii}{RAII}{Ressource Acquisition Is Initialization}
     109\newacronym{numa}{NUMA}{Non-Uniform Memory Access}
  • doc/proposals/concurrency/figures/ext_monitor.fig

    rb96ec83 r6840e7c  
    14144 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
    1515-6
    16 6 5850 1650 6150 1950
    17 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
    18 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     166 5100 2100 5400 2400
     171 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
     184 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
    1919-6
    20206 5100 1800 5400 2100
     
    22224 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
    2323-6
    24 6 5100 2100 5400 2400
    25 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
    26 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
     246 5850 1650 6150 1950
     251 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
     264 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
    2727-6
    28 6 3000 5400 7200 5700
     286 3070 5445 7275 5655
    29291 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
    30301 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
     
    32324 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
    33334 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
    34 4 0 -1 0 0 0 12 0.0000 2 180 930 6225 5625 routine ptrs\001
     344 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
    3535-6
    36361 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
     
    43432 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    4444         4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
    45 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    46          5850 2850 6075 3000
    47452 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    4846         3150 3750 3750 3750 3750 4050 3150 4050
     
    66642 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    6765         5850 4200 5850 3300 4350 3300 4350 4200 5850 4200
    68 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    69          5250 2850 5850 2850 5850 1650
    70 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    71          3150 3150 3750 3150 3750 2850 5325 2850
    72662 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
    7367        1 1 1.00 60.00 120.00
    7468        7 1 1.00 60.00 120.00
    7569         5250 3150 5250 2400
     702 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     71         3150 3150 3750 3150 3750 2850 5850 2850 5850 1650
     722 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     73         5850 2850 6150 3000
    76742 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    7775         5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
  • doc/proposals/concurrency/style/cfa-format.tex

    rb96ec83 r6840e7c  
    108108  belowskip=3pt,
    109109  keepspaces=true,
     110  tabsize=4,
    110111  % frame=lines,
    111112  literate=,
     
    133134  belowskip=3pt,
    134135  keepspaces=true,
     136  tabsize=4,
    135137  % frame=lines,
    136138  literate=,
     
    150152  keywordstyle=\bfseries\color{blue},
    151153  keywordstyle=[2]\bfseries\color{Plum},
    152   commentstyle=\itshape\color{OliveGreen},                  % green and italic comments
     154  commentstyle=\sf\itshape\color{OliveGreen},             % green and italic comments
    153155  identifierstyle=\color{identifierCol},
    154156  stringstyle=\sf\color{Mahogany},                                % use sanserif font
     
    158160  belowskip=3pt,
    159161  keepspaces=true,
     162  tabsize=4,
    160163  % frame=lines,
    161164  literate=,
  • doc/proposals/concurrency/text/basics.tex

    rb96ec83 r6840e7c  
    11% ======================================================================
    22% ======================================================================
    3 \chapter{Basics}\label{basics}
     3\chapter{Concurrency Basics}\label{basics}
    44% ======================================================================
    55% ======================================================================
    6 Before any detailed discussion of the concurrency and parallelism in \CFA, it is important to describe the basics of concurrency and how they are expressed in \CFA user code.
     6Before any detailed discussion of the concurrency and parallelism in \CFA, it is important to describe the basics of concurrency and how they are expressed in \CFA user-code.
    77
    88\section{Basics of concurrency}
    9 At its core, concurrency is based on having call-stacks and potentially multiple threads of execution for these stacks. Concurrency without parallelism only requires having multiple call stacks (or contexts) for a single thread of execution, and switching between these call stacks on a regular basis. A minimal concurrency product can be achieved by creating coroutines, which instead of context switching between each other, always ask an oracle where to context switch next. While coroutines do not technically require a stack, stackfull coroutines are the closest abstraction to a practical "naked"" call stack. When writing concurrency in terms of coroutines, the oracle effectively becomes a scheduler and the whole system now follows a cooperative threading-model \cit. The oracle/scheduler can either be a stackless or stackfull entity and correspondingly require one or two context switches to run a different coroutine. In any case, a subset of concurrency related challenges start to appear. For the complete set of concurrency challenges to occur, the only feature missing is preemption. Indeed, concurrency challenges appear with non-determinism. Guaranteeing mutual-exclusion or synchronisation are simply ways of limiting the lack of determinism in a system. A scheduler introduces order of execution uncertainty, while preemption introduces incertainty about where context-switches occur. Now it is important to understand that uncertainty is not necessarily undesireable; uncertainty can often be used by systems to significantly increase performance and is often the basis of giving a user the illusion that tasks are running in parallel. Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows\cit.
     9At its core, concurrency is based on having multiple call-stacks and scheduling among threads of execution executing on these stacks. Concurrency without parallelism only requires having multiple call stacks (or contexts) for a single thread of execution.
     10
     11Indeed, while execution with a single thread and multiple stacks where the thread is self-scheduling deterministically across the stacks is called coroutining, execution with a single and multiple stacks but where the thread is scheduled by an oracle (non-deterministic from the thread perspective) across the stacks is called concurrency.
     12
     13Therefore, a minimal concurrency system can be achieved by creating coroutines, which instead of context switching among each other, always ask an oracle where to context switch next. While coroutines can execute on the caller's stack-frame, stackfull coroutines allow full generality and are sufficient as the basis for concurrency. The aforementioned oracle is a scheduler and the whole system now follows a cooperative threading-model \cit. The oracle/scheduler can either be a stackless or stackfull entity and correspondingly require one or two context switches to run a different coroutine. In any case, a subset of concurrency related challenges start to appear. For the complete set of concurrency challenges to occur, the only feature missing is preemption. Indeed, concurrency challenges appear with non-determinism. Using mutual-exclusion or synchronisation are ways of limiting the lack of determinism in a system. A scheduler introduces order of execution uncertainty, while preemption introduces uncertainty about where context-switches occur. Now it is important to understand that uncertainty is not undesireable; uncertainty can often be used by systems to significantly increase performance and is often the basis of giving a user the illusion that tasks are running in parallel. Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows\cit.
    1014
    1115\section{\protect\CFA 's Thread Building Blocks}
    12 One of the important features that is missing in C is threading. On modern architectures, a lack of threading is becoming less and less forgivable\cite{Sutter05, Sutter05b}, and therefore modern programming languages must have the proper tools to allow users to write performant concurrent and/or parallel programs. As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers used to imperative languages. And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
     16One of the important features that is missing in C is threading. On modern architectures, a lack of threading is unacceptable\cite{Sutter05, Sutter05b}, and therefore modern programming languages must have the proper tools to allow users to write performant concurrent and/or parallel programs. As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages. And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
    1317
    1418\section{Coroutines: A stepping stone}\label{coroutine}
    15 While the main focus of this proposal is concurrency and parallelism, as mentionned above it is important to adress coroutines, which are actually a significant underlying aspect of a concurrency system. Indeed, while having nothing to do with parallelism and arguably little to do with concurrency, coroutines need to deal with context-switchs and other context-management operations. Therefore, this proposal includes coroutines both as an intermediate step for the implementation of threads, and a first class feature of \CFA. Furthermore, many design challenges of threads are at least partially present in designing coroutines, which makes the design effort that much more relevant. The core API of coroutines revolve around two features: independent call stacks and \code{suspend}/\code{resume}.
    16 
    17 Here is an example of a solution to the fibonnaci problem using \CFA coroutines:
    18 \begin{cfacode}
    19         coroutine Fibonacci {
    20               int fn; // used for communication
    21         };
    22 
    23         void ?{}(Fibonacci & this) { // constructor
    24               this.fn = 0;
    25         }
    26 
    27         // main automacically called on first resume
    28         void main(Fibonacci & this) {
    29                 int fn1, fn2;           // retained between resumes
    30                 this.fn = 0;
    31                 fn1 = this.fn;
    32                 suspend(this);          // return to last resume
    33 
    34                 this.fn = 1;
     19While the main focus of this proposal is concurrency and parallelism, it is important to address coroutines, which are actually a significant building block of a concurrency system. Coroutines need to deal with context-switchs and other context-management operations. Therefore, this proposal includes coroutines both as an intermediate step for the implementation of threads, and a first class feature of \CFA. Furthermore, many design challenges of threads are at least partially present in designing coroutines, which makes the design effort that much more relevant. The core \acrshort{api} of coroutines revolve around two features: independent call stacks and \code{suspend}/\code{resume}.
     20
     21A good example of a problem made easier with coroutines is genereting the fibonacci sequence. This problem comes with the challenge of decoupling how a sequence is generated and how it is used. Figure \ref{fig:fibonacci-c} shows conventional approaches to writing generators in C. All three of these approach suffer from strong coupling. The left and center approaches require that the generator have knowledge of how the sequence will be used, while the rightmost approach requires to user to hold internal state between calls on behalf of th sequence generator and makes it much harder to handle corner cases like the Fibonacci seed.
     22\begin{figure}
     23\label{fig:fibonacci-c}
     24\begin{center}
     25\begin{tabular}{c @{\hskip 0.025in}|@{\hskip 0.025in} c @{\hskip 0.025in}|@{\hskip 0.025in} c}
     26\begin{ccode}[tabsize=2]
     27//Using callbacks
     28void fibonacci_func(
     29        int n,
     30        void (*callback)(int)
     31) {
     32        int first = 0;
     33        int second = 1;
     34        int next, i;
     35        for(i = 0; i < n; i++)
     36        {
     37                if(i <= 1)
     38                        next = i;
     39                else {
     40                        next = f1 + f2;
     41                        f1 = f2;
     42                        f2 = next;
     43                }
     44                callback(next);
     45        }
     46}
     47\end{ccode}&\begin{ccode}[tabsize=2]
     48//Using output array
     49void fibonacci_array(
     50        int n,
     51        int * array
     52) {
     53        int f1 = 0; int f2 = 1;
     54        int next, i;
     55        for(i = 0; i < n; i++)
     56        {
     57                if(i <= 1)
     58                        next = i;
     59                else {
     60                        next = f1 + f2;
     61                        f1 = f2;
     62                        f2 = next;
     63                }
     64                *array = next;
     65                array++;
     66        }
     67}
     68\end{ccode}&\begin{ccode}[tabsize=2]
     69//Using external state
     70typedef struct {
     71        int f1, f2;
     72} iterator_t;
     73
     74int fibonacci_state(
     75        iterator_t * it
     76) {
     77        int f;
     78        f = it->f1 + it->f2;
     79        it->f2 = it->f1;
     80        it->f1 = f;
     81        return f;
     82}
     83
     84
     85
     86
     87
     88
     89\end{ccode}
     90\end{tabular}
     91\end{center}
     92\caption{Different implementations of a fibonacci sequence generator in C.}
     93\end{figure}
     94
     95
     96Figure \ref{fig:fibonacci-cfa} is an example of a solution to the fibonnaci problem using \CFA coroutines, using the coroutine stack to hold sufficient state for the generation. This solution has the advantage of having very strong decoupling between how the sequence is generated and how it is used. Indeed, this version is a easy to use as the \code{fibonacci_state} solution, while the imlpementation is very similar to the \code{fibonacci_func} example.
     97
     98\begin{figure}
     99\label{fig:fibonacci-cfa}
     100\begin{cfacode}
     101coroutine Fibonacci {
     102        int fn; //used for communication
     103};
     104
     105void ?{}(Fibonacci & this) { //constructor
     106        this.fn = 0;
     107}
     108
     109//main automacically called on first resume
     110void main(Fibonacci & this) {
     111        int fn1, fn2;           //retained between resumes
     112        this.fn = 0;
     113        fn1 = this.fn;
     114        suspend(this);          //return to last resume
     115
     116        this.fn = 1;
     117        fn2 = fn1;
     118        fn1 = this.fn;
     119        suspend(this);          //return to last resume
     120
     121        for ( ;; ) {
     122                this.fn = fn1 + fn2;
    35123                fn2 = fn1;
    36124                fn1 = this.fn;
    37                 suspend(this);          // return to last resume
    38 
    39                 for ( ;; ) {
    40                         this.fn = fn1 + fn2;
    41                         fn2 = fn1;
    42                         fn1 = this.fn;
    43                         suspend(this);  // return to last resume
    44                 }
    45         }
    46 
    47         int next(Fibonacci & this) {
    48                 resume(this); // transfer to last suspend
    49                 return this.fn;
    50         }
    51 
    52         void main() { // regular program main
    53                 Fibonacci f1, f2;
    54                 for ( int i = 1; i <= 10; i += 1 ) {
    55                         sout | next( f1 ) | next( f2 ) | endl;
    56                 }
    57         }
    58 \end{cfacode}
     125                suspend(this);  //return to last resume
     126        }
     127}
     128
     129int next(Fibonacci & this) {
     130        resume(this); //transfer to last suspend
     131        return this.fn;
     132}
     133
     134void main() { //regular program main
     135        Fibonacci f1, f2;
     136        for ( int i = 1; i <= 10; i += 1 ) {
     137                sout | next( f1 ) | next( f2 ) | endl;
     138        }
     139}
     140\end{cfacode}
     141\caption{Implementation of fibonacci using coroutines}
     142\end{figure}
    59143
    60144\subsection{Construction}
    61 One important design challenge for coroutines and threads (shown in section \ref{threads}) is that the runtime system needs to run code after the user-constructor runs. In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling. However, the underlying challenge remains the same for coroutines and threads.
    62 
    63 The runtime system needs to create the coroutine's stack and more importantly prepare it for the first resumption. The timing of the creation is non-trivial since users both expect to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor. Like for regular objects, constructors can still leak coroutines before they are ready. There are several solutions to this problem but the chosen options effectively forces the design of the coroutine.
     145One important design challenge for coroutines and threads (shown in section \ref{threads}) is that the runtime system needs to run code after the user-constructor runs to connect the object into the system. In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling. However, the underlying challenge remains the same for coroutines and threads.
     146
     147The runtime system needs to create the coroutine's stack and more importantly prepare it for the first resumption. The timing of the creation is non-trivial since users both expect to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor. As regular objects, constructors can leak coroutines before they are ready. There are several solutions to this problem but the chosen options effectively forces the design of the coroutine.
    64148
    65149Furthermore, \CFA faces an extra challenge as polymorphic routines create invisible thunks when casted to non-polymorphic routines and these thunks have function scope. For example, the following code, while looking benign, can run into undefined behaviour because of thunks:
     
    78162}
    79163\end{cfacode}
     164
    80165The generated C code\footnote{Code trimmed down for brevity} creates a local thunk to hold type information:
    81166
     
    95180}
    96181\end{ccode}
    97 The problem in this example is a race condition between the start of the execution of \code{noop} on the other thread and the stack frame of \code{bar} being destroyed. This extra challenge limits which solutions are viable because storing the function pointer for too long only increases the chances that the race will end in undefined behavior; i.e. the stack based thunk being destroyed before it was used. This challenge is an extension of challenges that come with second-class routines. Indeed, GCC nested routines also have the limitation that the routines cannot be passed outside of the scope of the functions these were declared in. The case of coroutines and threads is simply an extension of this problem to multiple call-stacks.
     182The problem in this example is a storage management issue, the function pointer \code{_thunk0} is only valid until the end of the block. This extra challenge limits which solutions are viable because storing the function pointer for too long causes undefined behavior; i.e. the stack based thunk being destroyed before it was used. This challenge is an extension of challenges that come with second-class routines. Indeed, GCC nested routines also have the limitation that the routines cannot be passed outside of the scope of the functions these were declared in. The case of coroutines and threads is simply an extension of this problem to multiple call-stacks.
    98183
    99184\subsection{Alternative: Composition}
    100 One solution to this challenge would be to use composition/containement,
    101 
    102 \begin{cfacode}
    103         struct Fibonacci {
    104               int fn; // used for communication
    105               coroutine c; //composition
    106         };
    107 
    108         void ?{}(Fibonacci & this) {
    109               this.fn = 0;
    110                 (this.c){};
    111         }
    112 \end{cfacode}
    113 There are two downsides to this approach. The first, which is relatively minor, is that the base class needs to be made aware of the main routine pointer, regardless of whether a parameter or a virtual pointer is used, this means the coroutine data must be made larger to store a value that is actually a compile time constant (address of the main routine). The second problem, which is both subtle and significant, is that now users can get the initialisation order of there coroutines wrong. Indeed, every field of a \CFA struct is constructed but in declaration order, unless users explicitly write otherwise. This semantics means that users who forget to initialize a the coroutine may resume the coroutine with an uninitilized object. For coroutines, this is unlikely to be a problem, for threads however, this is a significant problem.
     185One solution to this challenge is to use composition/containement, where uses add insert a coroutine field which contains the necessary information to manage the coroutine.
     186
     187\begin{cfacode}
     188struct Fibonacci {
     189        int fn; //used for communication
     190        coroutine c; //composition
     191};
     192
     193void ?{}(Fibonacci & this) {
     194        this.fn = 0;
     195        (this.c){}; //Call constructor to initialize coroutine
     196}
     197\end{cfacode}
     198There are two downsides to this approach. The first, which is relatively minor, made aware of the main routine pointer. This information must either be store in the coroutine runtime data or in its static type structure. When using composition, all coroutine handles have the same static type structure which means the pointer to the main needs to be part of the runtime data. This requirement means the coroutine data must be made larger to store a value that is actually a compile time constant (address of the main routine). The second problem, which is both subtle and significant, is that now users can get the initialisation order of coroutines wrong. Indeed, every field of a \CFA struct is constructed but in declaration order, unless users explicitly write otherwise. This semantics means that users who forget to initialize the coroutine handle may resume the coroutine with an uninitilized object. For coroutines, this is unlikely to be a problem, for threads however, this is a significant problem. Figure \ref{fig:fmt-line} shows the \code{Format} coroutine which rearranges text in order to group characters into blocks of fixed size. This is a good example where the control flow is made much simpler from being able to resume the coroutine from the constructor and highlights the idea that interesting control flow can occor in the constructor.
     199\begin{figure}
     200\label{fig:fmt-line}
     201\begin{cfacode}[tabsize=3]
     202//format characters into blocks of 4 and groups of 5 blocks per line
     203coroutine Format {
     204        char ch;                                                                        //used for communication
     205        int g, b;                                                               //global because used in destructor
     206};
     207
     208void  ?{}(Format & fmt) {
     209        resume( fmt );                                                  //prime (start) coroutine
     210}
     211
     212void ^?{}(Format & fmt) with fmt {
     213        if ( fmt.g != 0 || fmt.b != 0 )
     214        sout | endl;
     215}
     216
     217void main(Format & fmt) with fmt {
     218        for ( ;; ) {                                                    //for as many characters
     219                for(g = 0; g < 5; g++) {                //groups of 5 blocks
     220                        for(b = 0; b < 4; fb++) {       //blocks of 4 characters
     221                                suspend();
     222                                sout | ch;                                      //print character
     223                        }
     224                        sout | "  ";                                    //print block separator
     225                }
     226                sout | endl;                                            //print group separator
     227        }
     228}
     229
     230void prt(Format & fmt, char ch) {
     231        fmt.ch = ch;
     232        resume(fmt);
     233}
     234
     235int main() {
     236        Format fmt;
     237        char ch;
     238        Eof: for ( ;; ) {                                               //read until end of file
     239                sin | ch;                                                       //read one character
     240                if(eof(sin)) break Eof;                 //eof ?
     241                prt(fmt, ch);                                           //push character for formatting
     242        }
     243}
     244\end{cfacode}
     245\caption{Formatting text into lines of 5 blocks of 4 characters.}
     246\end{figure}
     247
    114248
    115249\subsection{Alternative: Reserved keyword}
     
    117251
    118252\begin{cfacode}
    119         coroutine Fibonacci {
    120               int fn; // used for communication
    121         };
    122 \end{cfacode}
    123 This mean the compiler can solve problems by injecting code where needed. The downside of this approach is that it makes coroutine a special case in the language. Users who would want to extend coroutines or build their own for various reasons can only do so in ways offered by the language. Furthermore, implementing coroutines without language supports also displays the power of \CFA.
    124 While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can both be constructed by users without using the language support. The reserved keywords are only present to improve ease of use for the common cases.
     253coroutine Fibonacci {
     254        int fn; //used for communication
     255};
     256\end{cfacode}
     257This mean the compiler can solve problems by injecting code where needed. The downside of this approach is that it makes coroutine a special case in the language. Users who would want to extend coroutines or build their own for various reasons can only do so in ways offered by the language. Furthermore, implementing coroutines without language supports also displays the power of the programming language used. While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can both be constructed by users without using the language support. The reserved keywords are only present to improve ease of use for the common cases.
    125258
    126259\subsection{Alternative: Lamda Objects}
     
    159292      coroutine_desc * get_coroutine(T & this);
    160293};
    161 \end{cfacode}
    162 This ensures an object is not a coroutine until \code{resume} (or \code{prime}) is called on the object. Correspondingly, any object that is passed to \code{resume} is a coroutine since it must satisfy the \code{is_coroutine} trait to compile. The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory foot print of a coroutine is trivial when implementing the \code{get_coroutine} routine. The \CFA keyword \code{coroutine} only has the effect of implementing the getter and forward declarations required for users to only have to implement the main routine.
     294
     295forall( dtype T | is_coroutine(T) ) void suspend(T &);
     296forall( dtype T | is_coroutine(T) ) void resume (T &);
     297\end{cfacode}
     298This ensures an object is not a coroutine until \code{resume} is called on the object. Correspondingly, any object that is passed to \code{resume} is a coroutine since it must satisfy the \code{is_coroutine} trait to compile. The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the \code{get_coroutine} routine. The \CFA keyword \code{coroutine} only has the effect of implementing the getter and forward declarations required for users to only have to implement the main routine.
    163299
    164300\begin{center}
     
    186322\end{center}
    187323
    188 The combination of these two approaches allows users new to concurrency to have a easy and concise method while more advanced users can expose themselves to otherwise hidden pitfalls at the benefit of tighter control on memory layout and initialization.
     324The combination of these two approaches allows users new to coroutinning and concurrency to have an easy and concise specification, while more advanced users have tighter control on memory layout and initialization.
    189325
    190326\section{Thread Interface}\label{threads}
     
    192328
    193329\begin{cfacode}
    194         thread foo {};
     330thread foo {};
    195331\end{cfacode}
    196332
     
    205341\end{cfacode}
    206342
    207 Obviously, for this thread implementation to be usefull it must run some user code. Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}). However, this proposal considers that statically tying a \code{main} routine to a thread superseeds this approach. Since the \code{main} routine is already a special routine in \CFA (where the program begins), it is possible naturally extend the semantics using overloading to declare mains for different threads (the normal main being the main of the initial thread). As such the \code{main} routine of a thread can be defined as
    208 \begin{cfacode}
    209         thread foo {};
    210 
    211         void main(foo & this) {
    212                 sout | "Hello World!" | endl;
    213         }
    214 \end{cfacode}
    215 
    216 In this example, threads of type \code{foo} start execution in the \code{void main(foo*)} routine which prints \code{"Hello World!"}. While this proposoal encourages this approach to enforce strongly-typed programming, users may prefer to use the routine based thread semantics for the sake of simplicity. With these semantics it is trivial to write a thread type that takes a function pointer as parameter and executes it on its stack asynchronously
    217 \begin{cfacode}
    218         typedef void (*voidFunc)(void);
    219 
    220         thread FuncRunner {
    221                 voidFunc func;
    222         };
    223 
    224         //ctor
    225         void ?{}(FuncRunner & this, voidFunc inFunc) {
    226                 this.func = inFunc;
    227         }
    228 
    229         //main
    230         void main(FuncRunner & this) {
    231                 this.func();
    232         }
    233 \end{cfacode}
    234 
    235 An advantage of the overloading approach to main is to clearly highlight where and what memory is required to pass parameters and return values to/from a thread.
    236 
    237 Of course for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution. While using an \acrshort{api} such as \code{fork} and \code{join} is relatively common in the literature, such an interface is unnecessary. Indeed, the simplest approach is to use \acrshort{raii} principles and have threads \code{fork} once the constructor has completed and \code{join} before the destructor runs.
     343Obviously, for this thread implementation to be usefull it must run some user code. Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}). However, this proposal considers that statically tying a \code{main} routine to a thread superseeds this approach. Since the \code{main} routine is already a special routine in \CFA (where the program begins), it is a natural extension of the semantics using overloading to declare mains for different threads (the normal main being the main of the initial thread). As such the \code{main} routine of a thread can be defined as
     344\begin{cfacode}
     345thread foo {};
     346
     347void main(foo & this) {
     348        sout | "Hello World!" | endl;
     349}
     350\end{cfacode}
     351
     352In this example, threads of type \code{foo} start execution in the \code{void main(foo &)} routine, which prints \code{"Hello World!"}. While this thesis encourages this approach to enforce strongly-typed programming, users may prefer to use the routine-based thread semantics for the sake of simplicity. With these semantics it is trivial to write a thread type that takes a function pointer as a parameter and executes it on its stack asynchronously
     353\begin{cfacode}
     354typedef void (*voidFunc)(int);
     355
     356thread FuncRunner {
     357        voidFunc func;
     358        int arg;
     359};
     360
     361void ?{}(FuncRunner & this, voidFunc inFunc, int arg) {
     362        this.func = inFunc;
     363}
     364
     365void main(FuncRunner & this) {
     366        this.func( this.arg );
     367}
     368\end{cfacode}
     369
     370An consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \acrshort{api}.
     371
     372Of course for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution. While using an \acrshort{api} such as \code{fork} and \code{join} is relatively common in the literature, such an interface is unnecessary. Indeed, the simplest approach is to use \acrshort{raii} principles and have threads \code{fork} after the constructor has completed and \code{join} before the destructor runs.
    238373\begin{cfacode}
    239374thread World;
     
    254389\end{cfacode}
    255390
    256 This semantic has several advantages over explicit semantics typesafety is guaranteed, a thread is always started and stopped exaclty once and users cannot make any progamming errors. Another advantage of this semantic is that it naturally scale to multiple threads meaning basic synchronisation is very simple
     391This semantic has several advantages over explicit semantics: a thread is always started and stopped exaclty once and users cannot make any progamming errors and it naturally scales to multiple threads meaning basic synchronisation is very simple
    257392
    258393\begin{cfacode}
     
    276411\end{cfacode}
    277412
    278 However, one of the apparent drawbacks of this system is that threads now always form a lattice, that is they are always destroyed in opposite order of construction because of block structure. However, storage allocation is not limited to blocks; dynamic allocation can create threads that outlive the scope in which the thread is created much like dynamically allocating memory lets objects outlive the scope in which they are created
     413However, one of the drawbacks of this approach is that threads now always form a lattice, that is they are always destroyed in opposite order of construction because of block structure. This restriction is relaxed by using dynamic allocation, so threads can outlive the scope in which they are created, much like dynamically allocating memory lets objects outlive the scope in which they are created
    279414
    280415\begin{cfacode}
     
    283418};
    284419
    285 //main
    286420void main(MyThread & this) {
    287421        //...
     
    291425        MyThread * long_lived;
    292426        {
     427                //Start a thread at the beginning of the scope
    293428                MyThread short_lived;
    294                 //Start a thread at the beginning of the scope
    295 
    296                 DoStuff();
    297429
    298430                //create another thread that will outlive the thread in this scope
    299431                long_lived = new MyThread;
    300432
     433                DoStuff();
     434
    301435                //Wait for the thread short_lived to finish
    302436        }
    303437        DoMoreStuff();
    304438
    305         //Now wait for the short_lived to finish
     439        //Now wait for the long_lived to finish
    306440        delete long_lived;
    307441}
  • doc/proposals/concurrency/text/cforall.tex

    rb96ec83 r6840e7c  
    55% ======================================================================
    66
    7 As mentionned in the introduction, the document presents the design for the concurrency features in \CFA. Since it is a new language here is a quick review of the language specifically tailored to the features needed to support concurrency.
     7This thesis presents the design for a set of concurrency features in \CFA. Since it is a new dialect of C, the following is a quick introduction to the language, specifically tailored to the features needed to support concurrency.
    88
    9 \CFA is a extension of ISO C and therefore supports much of the same paradigms as C. It is a non-object oriented system level language, meaning it has very most of the major abstractions have either no runtime cost or can be opt-out easily. Like C, the basics of \CFA revolve around structures and routines, which are thin abstractions over assembly. The vast majority of the code produced by a \CFA compiler respects memory-layouts and calling-conventions laid out by C. However, while \CFA is not an object-oriented language according to a strict definition. It does have some notion of objects, most importantly construction and destruction of objects. Most of the following pieces of code can be found as is on the \CFA website : \cite{www-cfa}
     9\CFA is a extension of ISO-C and therefore supports all of the same paradigms as C. It is a non-object oriented system language, meaning most of the major abstractions have either no runtime overhead or can be opt-out easily. Like C, the basics of \CFA revolve around structures and routines, which are thin abstractions over machine code. The vast majority of the code produced by the \CFA translator respects memory-layouts and calling-conventions laid out by C. Interestingly, while \CFA is not an object-oriented language, lacking the concept of a received (e.g.: this), it does have some notion of objects\footnote{C defines the term objects as : [Where to I get the C11 reference manual?]}, most importantly construction and destruction of objects. Most of the following pieces of code can be found on the \CFA website \cite{www-cfa}
    1010
    1111\section{References}
    1212
    13 Like \CC, \CFA introduces references as an alternative to pointers. In regards to concurrency, the semantics difference between pointers and references aren't particularly relevant but since this document uses mostly references here is a quick overview of the semantics :
     13Like \CC, \CFA introduces references as an alternative to pointers. In regards to concurrency, the semantics difference between pointers and references are not particularly relevant but since this document uses mostly references here is a quick overview of the semantics :
    1414\begin{cfacode}
    1515int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    1616&r1 = x,    &&r2 = r1,   &&&r3 = r2;
    17 ***p3 = 3;                                      // change x
    18 r3 = 3;                                         // change x, ***r3
    19 **p3 = ...;                                     // change p1
    20 &r3 = ...;                                      // change r1, (&*)**r3
    21 *p3 = ...;                                      // change p2
    22 &&r3 = ...;                                     // change r2, (&(&*)*)*r3
    23 &&&r3 = p3;                                     // change r3 to p3, (&(&(&*)*)*)r3
    24 int y, z, & ar[3] = { x, y, z };                // initialize array of references
    25 &ar[1] = &z;                                    // change reference array element
    26 typeof( ar[1] ) p;                              // is int, i.e., the type of referenced object
    27 typeof( &ar[1] ) q;                             // is int &, i.e., the type of reference
    28 sizeof( ar[1] ) == sizeof( int );               // is true, i.e., the size of referenced object
    29 sizeof( &ar[1] ) == sizeof( int *);             // is true, i.e., the size of a reference
     17***p3 = 3;                                                      //change x
     18r3    = 3;                                                      //change x, ***r3
     19**p3  = ...;                                            //change p1
     20*p3   = ...;                                            //change p2
     21int y, z, & ar[3] = {x, y, z};          //initialize array of references
     22typeof( ar[1]) p;                                       //is int, i.e., the type of referenced object
     23typeof(&ar[1]) q;                                       //is int &, i.e., the type of reference
     24sizeof( ar[1]) == sizeof(int);          //is true, i.e., the size of referenced object
     25sizeof(&ar[1]) == sizeof(int *);        //is true, i.e., the size of a reference
    3026\end{cfacode}
    3127The important thing to take away from this code snippet is that references offer a handle to an object much like pointers but which is automatically derefferenced when convinient.
     
    3329\section{Overloading}
    3430
    35 Another important feature \CFA has in common with \CC is function overloading :
     31Another important feature of \CFA is function overloading as in Java and \CC, where routine with the same name are selected based on the numbers and type of the arguments. As well, \CFA uses the return type as part of the selection criteria, as in Ada\cite{Ada}. For routines with multiple parameters and returns, the selection is complex.
    3632\begin{cfacode}
    37 // selection based on type and number of parameters
    38 void f( void );                                 // (1)
    39 void f( char );                                 // (2)
    40 void f( int, double );                          // (3)
    41 f();                                            // select (1)
    42 f( 'a' );                                       // select (2)
    43 f( 3, 5.2 );                                    // select (3)
     33//selection based on type and number of parameters
     34void f(void);                   //(1)
     35void f(char);                   //(2)
     36void f(int, double);    //(3)
     37f();                                    //select (1)
     38f('a');                                 //select (2)
     39f(3, 5.2);                              //select (3)
    4440
    45 // selection based on  type and number of returns
    46 char f( int );                                  // (1)
    47 double f( int );                                // (2)
    48 [ int, double ] f( int );                       // (3)
    49 char c = f( 3 );                                // select (1)
    50 double d = f( 4 );                              // select (2)
    51 [ int, double ] t = f( 5 );                     // select (3)
     41//selection based on  type and number of returns
     42char   f(int);                  //(1)
     43double f(int);                  //(2)
     44char   c = f(3);                //select (1)
     45double d = f(4);                //select (2)
    5246\end{cfacode}
    53 This feature is particularly important for concurrency since the runtime system relies on creating different types do represent concurrency objects. Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent clashes. As seen in chapter \ref{basics}, the main is an example of routine that benefits from overloading when concurrency in introduced.
     47This feature is particularly important for concurrency since the runtime system relies on creating different types to represent concurrency objects. Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent name clashes. As seen in chapter \ref{basics}, routines main is an example that benefits from overloading.
    5448
    5549\section{Operators}
    5650Overloading also extends to operators. The syntax for denoting operator-overloading is to name a routine with the symbol of the operator and question marks where the arguments of the operation would be, like so :
    5751\begin{cfacode}
    58 int ++?( int op );                              // unary prefix increment
    59 int ?++( int op );                              // unary postfix increment
    60 int ?+?( int op1, int op2 );                    // binary plus
    61 int ?<=?( int op1, int op2 );                   // binary less than
    62 int ?=?( int & op1, int op2 );                  // binary assignment
    63 int ?+=?( int & op1, int op2 );                 // binary plus-assignment
     52int ++? (int op);                       //unary prefix increment
     53int ?++ (int op);                       //unary postfix increment
     54int ?+? (int op1, int op2);             //binary plus
     55int ?<=?(int op1, int op2);             //binary less than
     56int ?=? (int & op1, int op2);           //binary assignment
     57int ?+=?(int & op1, int op2);           //binary plus-assignment
    6458
    65 struct S { int i, j; };
    66 S ?+?( S op1, S op2 ) {                         // add two structures
    67         return (S){ op1.i + op2.i, op1.j + op2.j };
     59struct S {int i, j;};
     60S ?+?(S op1, S op2) {                           //add two structures
     61        return (S){op1.i + op2.i, op1.j + op2.j};
    6862}
    69 S s1 = { 1, 2 }, s2 = { 2, 3 }, s3;
    70 s3 = s1 + s2;                                   // compute sum: s3 == { 2, 5 }
     63S s1 = {1, 2}, s2 = {2, 3}, s3;
     64s3 = s1 + s2;                                           //compute sum: s3 == {2, 5}
    7165\end{cfacode}
    72 
    73 Since concurrency does not use operator overloading, this feature is more important as an introduction for the syntax of constructors.
     66While concurrency does not use operator overloading directly, this feature is more important as an introduction for the syntax of constructors.
    7467
    7568\section{Constructors/Destructors}
    76 \CFA uses the following syntax for constructors and destructors :
     69Object life-time is often a challenge in concurrency. \CFA uses the approach of giving concurrent meaning to object life-time as a mean of synchronization and/or mutual exclusion. Since \CFA relies heavily on the life time of objects, constructors and destructors are a core feature required for concurrency and parallelism. \CFA uses the following syntax for constructors and destructors :
    7770\begin{cfacode}
    7871struct S {
     
    8073        int * ia;
    8174};
    82 void ?{}( S & s, int asize ) with s {           // constructor operator
    83         size = asize;                           // initialize fields
    84         ia = calloc( size, sizeof( S ) );
     75void ?{}(S & s, int asize) {    //constructor operator
     76        s.size = asize;                         //initialize fields
     77        s.ia = calloc(size, sizeof(S));
    8578}
    86 void ^?{}( S & s ) with s {                     // destructor operator
    87         free( ia );                             // de-initialization fields
     79void ^?{}(S & s) {                              //destructor operator
     80        free(ia);                                       //de-initialization fields
    8881}
    8982int main() {
    90         S x = { 10 }, y = { 100 };              // implict calls: ?{}( x, 10 ), ?{}( y, 100 )
    91         ...                                     // use x and y
    92         ^x{};  ^y{};                            // explicit calls to de-initialize
    93         x{ 20 };  y{ 200 };                     // explicit calls to reinitialize
    94         ...                                     // reuse x and y
    95 }                                               // implict calls: ^?{}( y ), ^?{}( x )
     83        S x = {10}, y = {100};          //implict calls: ?{}(x, 10), ?{}(y, 100)
     84        ...                                                     //use x and y
     85        ^x{};  ^y{};                            //explicit calls to de-initialize
     86        x{20};  y{200};                         //explicit calls to reinitialize
     87        ...                                                     //reuse x and y
     88}                                                               //implict calls: ^?{}(y), ^?{}(x)
    9689\end{cfacode}
    97 The language guarantees that every object and all their fields are constructed. Like \CC construction is automatically done on declaration and destruction done when the declared variables reach the end of its scope.
     90The language guarantees that every object and all their fields are constructed. Like \CC, construction of an object is automatically done on allocation and destruction of the object is done on deallocation. Allocation and deallocation can occur on the stack or on the heap.
     91\begin{cfacode}
     92{
     93        struct S s = {10};      //allocation, call constructor
     94        ...
     95}                                               //deallocation, call destructor
     96struct S * s = new();   //allocation, call constructor
     97...
     98delete(s);                              //deallocation, call destructor
     99\end{cfacode}
     100Note that like \CC, \CFA introduces \code{new} and \code{delete}, which behave like \code{malloc} and \code{free} in addition to constructing and destructing objects, after calling \code{malloc} and before calling \code{free} respectively.
    98101
    99 For more information see \cite{cforall-ug,rob-thesis,www-cfa}.
     102\section{Parametric Polymorphism}
     103Routines in \CFA can also be reused for multiple types. This is done using the \code{forall} clause which gives \CFA it's name. \code{forall} clauses allow seperatly compiled routines to support generic usage over multiple types. For example, the following sum function will work for any type which support construction from 0 and addition :
     104\begin{cfacode}
     105//constraint type, 0 and +
     106forall(otype T | { void ?{}(T *, zero_t); T ?+?(T, T); })
     107T sum(T a[ ], size_t size) {
     108        T total = 0;                            //construct T from 0
     109        for(size_t i = 0; i < size; i++)
     110                total = total + a[i];   //select appropriate +
     111        return total;
     112}
     113
     114S sa[5];
     115int i = sum(sa, 5);                             //use S's 0 construction and +
     116\end{cfacode}
     117
     118Since writing constraints on types can become cumbersome for more constrained functions, \CFA also has the concept of traits. Traits are named collection of constraints which can be used both instead and in addition to regular constraints:
     119\begin{cfacode}
     120trait sumable( otype T ) {
     121        void ?{}(T *, zero_t);          //constructor from 0 literal
     122        T ?+?(T, T);                            //assortment of additions
     123        T ?+=?(T *, T);
     124        T ++?(T *);
     125        T ?++(T *);
     126};
     127forall( otype T | sumable(T) )  //use trait
     128T sum(T a[], size_t size);
     129\end{cfacode}
     130
     131\section{with Clause/Statement}
     132Since \CFA lacks the concept of a receiver, certain functions end-up needing to repeat variable names often, to solve this \CFA offers the \code{with} statement which opens an aggregate scope making its fields directly accessible (like Pascal).
     133\begin{cfacode}
     134struct S { int i, j; };
     135int mem(S & this) with this             //with clause
     136        i = 1;                                          //this->i
     137        j = 2;                                          //this->j
     138}
     139int foo() {
     140        struct S1 { ... } s1;
     141        struct S2 { ... } s2;
     142        with s1                                         //with statement
     143        {
     144                //access fields of s1
     145                //without qualification
     146                with s2                                 //nesting
     147                {
     148                        //access fields of s1 and s2
     149                        //without qualification
     150                }
     151        }
     152        with s1, s2                             //scopes open in parallel
     153        {
     154                //access fields of s1 and s2
     155                //without qualification
     156        }
     157}
     158\end{cfacode}
     159
     160For more information on \CFA see \cite{cforall-ug,rob-thesis,www-cfa}.
  • doc/proposals/concurrency/text/concurrency.tex

    rb96ec83 r6840e7c  
    44% ======================================================================
    55% ======================================================================
    6 Several tool can be used to solve concurrency challenges. Since many of these challenges appear with the use of mutable shared-state, some languages and libraries simply disallow mutable shared-state (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka (Scala)~\cite{Akka}). In these paradigms, interaction among concurrent objects relies on message passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms that closely relate to networking concepts (channels\cit for example). However, in languages that use routine calls as their core abstraction-mechanism, these approaches force a clear distinction between concurrent and non-concurrent paradigms (i.e., message passing versus routine call). This distinction in turn means that, in order to be effective, programmers need to learn two sets of designs patterns. While this distinction can be hidden away in library code, effective use of the librairy still has to take both paradigms into account.
     6Several tool can be used to solve concurrency challenges. Since many of these challenges appear with the use of mutable shared-state, some languages and libraries simply disallow mutable shared-state (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka (Scala)~\cite{Akka}). In these paradigms, interaction among concurrent objects relies on message passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (channels\cit for example). However, in languages that use routine calls as their core abstraction-mechanism, these approaches force a clear distinction between concurrent and non-concurrent paradigms (i.e., message passing versus routine call). This distinction in turn means that, in order to be effective, programmers need to learn two sets of designs patterns. While this distinction can be hidden away in library code, effective use of the librairy still has to take both paradigms into account.
    77
    88Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on basic constructs like routine calls and shared objects. At the lowest level, concurrent paradigms are implemented as atomic operations and locks. Many such mechanisms have been proposed, including semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}. However, for productivity reasons it is desireable to have a higher-level construct be the core concurrency paradigm~\cite{HPP:Study}.
    99
    10 An approach that is worth mentionning because it is gaining in popularity is transactionnal memory~\cite{Dice10}[Check citation]. While this approach is even pursued by system languages like \CC\cit, the performance and feature set is currently too restrictive to be the main concurrency paradigm for general purpose language, which is why it was rejected as the core paradigm for concurrency in \CFA.
    11 
    12 One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared memory systems, is the \emph{monitor}. Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. Many programming languages---e.g., Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}---provide monitors as explicit language constructs. In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors. For these reasons, this project proposes monitors as the core concurrency-construct.
     10An approach that is worth mentionning because it is gaining in popularity is transactionnal memory~\cite{Dice10}[Check citation]. While this approach is even pursued by system languages like \CC\cit, the performance and feature set is currently too restrictive to be the main concurrency paradigm for systems language, which is why it was rejected as the core paradigm for concurrency in \CFA.
     11
     12One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared-memory systems, is the \emph{monitor}. Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. Many programming languages---e.g., Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}---provide monitors as explicit language constructs. In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors. For these reasons, this project proposes monitors as the core concurrency-construct.
    1313
    1414\section{Basics}
    15 Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronisation. Mutual-exclusion is the concept that only a fixed number of threads can access a critical section at any given time, where a critical section is a group of instructions on an associated portion of data that requires the restricted access. On the other hand, synchronization enforces relative ordering of execution and synchronization tools numerous mechanisms to establish timing relationships among threads.
     15Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronisation. Mutual-exclusion is the concept that only a fixed number of threads can access a critical section at any given time, where a critical section is a group of instructions on an associated portion of data that requires the restricted access. On the other hand, synchronization enforces relative ordering of execution and synchronization tools provide numerous mechanisms to establish timing relationships among threads.
    1616
    1717\subsection{Mutual-Exclusion}
    18 As mentionned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once. However, many solution exists for mutual exclusion which vary in terms of performance, flexibility and ease of use. Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to  higher-level mutual-exclusion methods, which sacrifice some performance in order to improve ease of use. Ease of use comes by either guaranteeing some problems cannot occur (e.g., being deadlock free) or by offering a more explicit coupling between data and corresponding critical section. For example, the \CC \code{std::atomic<T>} which offer an easy way to express mutual-exclusion on a restricted set of operations (.e.g: reading/writing large types atomically). Another challenge with low-level locks is composability. Locks are not composable because it takes careful organising for multiple locks to be used while preventing deadlocks. Easing composability is another feature higher-level mutual-exclusion mechanisms often offer.
     18As mentionned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once. However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use. Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to  higher-level mutual-exclusion methods, which sacrifice some performance in order to improve ease of use. Ease of use comes by either guaranteeing some problems cannot occur (e.g., being deadlock free) or by offering a more explicit coupling between data and corresponding critical section. For example, the \CC \code{std::atomic<T>} offers an easy way to express mutual-exclusion on a restricted set of operations (e.g.: reading/writing large types atomically). Another challenge with low-level locks is composability. Locks have restricted composability because it takes careful organising for multiple locks to be used while preventing deadlocks. Easing composability is another feature higher-level mutual-exclusion mechanisms often offer.
    1919
    2020\subsection{Synchronization}
    21 As for mutual-exclusion, low level synchronisation primitive often offer good performance and good flexibility at the cost of ease of use. Again, higher-level mechanism often simplify usage by adding better coupling between synchronization and data, .eg., message passing, or offering simple solution to otherwise involved challenges. An example of this is barging. As mentionned above synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}. Most of the time synchronisation happens around a critical section, where threads most acquire said critical section in a certain order. However, it may also be desired to be able to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}. This is called barging, where event \textit{X} tries to effect event \textit{Y} but anoter thread races to grab the critical section and emits \textit{Z} before \textit{Y}. Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
     21As for mutual-exclusion, low-level synchronisation primitives often offer good performance and good flexibility at the cost of ease of use. Again, higher-level mechanism often simplify usage by adding better coupling between synchronization and data, e.g.: message passing, or offering simple solution to otherwise involved challenges. An example is barging. As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}. Most of the time, synchronisation happens around a critical section, where threads must acquire critical sections in a certain order. However, it may also be desirable to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}. Not satisfying this property called barging. For example, where event \textit{X} tries to effect event \textit{Y} but another thread acquires the critical section and emits \textit{Z} before \textit{Y}. Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs. This challenge is often split into two different methods, barging avoidance and barging prevention. Algorithms that use status flags and other flag variables to detect barging threads are said to be using barging avoidance while algorithms that baton-passing locks between threads instead of releasing the locks are said to be using barging prevention.
    2222
    2323% ======================================================================
     
    2828A monitor is a set of routines that ensure mutual exclusion when accessing shared state. This concept is generally associated with Object-Oriented Languages like Java~\cite{Java} or \uC~\cite{uC++book} but does not strictly require OO semantics. The only requirements is the ability to declare a handle to a shared object and a set of routines that act on it :
    2929\begin{cfacode}
    30         typedef /*some monitor type*/ monitor;
    31         int f(monitor & m);
    32 
    33         int main() {
    34                 monitor m;  //Handle m
    35                 f(m);       //Routine using handle
    36         }
     30typedef /*some monitor type*/ monitor;
     31int f(monitor & m);
     32
     33int main() {
     34        monitor m;  //Handle m
     35        f(m);       //Routine using handle
     36}
    3737\end{cfacode}
    3838
     
    4747
    4848\begin{cfacode}
    49         monitor counter_t { /*...see section $\ref{data}$...*/ };
    50 
    51         void ?{}(counter_t & nomutex this); //constructor
    52         size_t ++?(counter_t & mutex this); //increment
    53 
    54         //need for mutex is platform dependent
    55         void ?{}(size_t * this, counter_t & mutex cnt); //conversion
    56 \end{cfacode}
    57 
    58 Here, the constructor(\code{?\{\}}) uses the \code{nomutex} keyword to signify that it does not acquire the monitor mutual-exclusion when constructing. This semantics is because an object not yet constructed should never be shared and therefore does not require mutual exclusion. The prefix increment operator uses \code{mutex} to protect the incrementing process from race conditions. Finally, there is a conversion operator from \code{counter_t} to \code{size_t}. This conversion may or may not require the \code{mutex} keyword depending on whether or not reading an \code{size_t} is an atomic operation.
    59 
    60 Having both \code{mutex} and \code{nomutex} keywords is redundant based on the meaning of a routine having neither of these keywords. For example, given a routine without qualifiers \code{void foo(counter_t & this)}, then it is reasonable that it should default to the safest option \code{mutex}, whereas assuming \code{nomutex} is unsafe and may cause subtle errors. In fact, \code{nomutex} is the "normal" parameter behaviour, with the \code{nomutex} keyword effectively stating explicitly that "this routine is not special". Another alternative is to make having exactly one of these keywords mandatory, which would provide the same semantics but without the ambiguity of supporting routines neither keyword. Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing. While there are several benefits to mandatory keywords, they do bring a few challenges. Mandatory keywords in \CFA would imply that the compiler must know without a doubt wheter or not a parameter is a monitor or not. Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred. For this reason, \CFA only has the \code{mutex} keyword.
    61 
    62 
    63 The next semantic decision is to establish when \code{mutex} may be used as a type qualifier. Consider the following declarations:
    64 \begin{cfacode}
    65 int f1(monitor & mutex m);
    66 int f2(const monitor & mutex m);
    67 int f3(monitor ** mutex m);
    68 int f4(monitor * mutex m []);
    69 int f5(graph(monitor*) & mutex m);
    70 \end{cfacode}
    71 The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In the case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entry. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To keep everyone as sane as possible~\cite{Chicken}, this projects imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with one level of indirection (ignoring potential qualifiers). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. This is specially true for non-copyable objects like monitors, where an array of pointers is simplest way to express a group of monitors. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
    72 
    73 \begin{cfacode}
    74 int f1(monitor & mutex m);   //Okay : recommanded case
    75 int f2(monitor * mutex m);   //Okay : could be an array but probably not
    76 int f3(monitor mutex m []);  //Not Okay : Array of unkown length
    77 int f4(monitor ** mutex m);  //Not Okay : Could be an array
    78 int f5(monitor * mutex m []); //Not Okay : Array of unkown length
    79 \end{cfacode}
    80 
    81 Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion, \CFA uses an explicit mechanism to acquire mutual-exclusion. A consequence of this approach is that it extends naturally to multi-monitor calls.
    82 \begin{cfacode}
    83 int f(MonitorA & mutex a, MonitorB & mutex b);
    84 
    85 MonitorA a;
    86 MonitorB b;
    87 f(a,b);
    88 \end{cfacode}
    89 The capacity to acquire multiple locks before entering a critical section is called \emph{\gls{group-acquire}}. In practice, writing multi-locking routines that do not lead to deadlocks is tricky. Having language support for such a feature is therefore a significant asset for \CFA. In the case presented above, \CFA guarantees that the order of aquisition is consistent across calls to routines using the same monitors as arguments. However, since \CFA monitors use multi-acquisition locks, users can effectively force the acquiring order. For example, notice which routines use \code{mutex}/\code{nomutex} and how this affects aquiring order:
    90 \begin{cfacode}
    91         void foo(A & mutex a, B & mutex b) { //acquire a & b
    92                 ...
    93         }
    94 
    95         void bar(A & mutex a, B & /*nomutex*/ b) { //acquire a
    96                 ... foo(a, b); ... //acquire b
    97         }
    98 
    99         void baz(A & /*nomutex*/ a, B & mutex b) { //acquire b
    100                 ... foo(a, b); ... //acquire a
    101         }
    102 \end{cfacode}
    103 The multi-acquisition monitor lock allows a monitor lock to be acquired by both \code{bar} or \code{baz} and acquired again in \code{foo}. In the calls to \code{bar} and \code{baz} the monitors are acquired in opposite order.
    104 
    105 However, such use leads the lock acquiring order problem. In the example above, the user uses implicit ordering in the case of function \code{foo} but explicit ordering in the case of \code{bar} and \code{baz}. This subtle mistake means that calling these routines concurrently may lead to deadlock and is therefore undefined behavior. As shown on several occasion\cit, solving this problem requires:
    106 \begin{enumerate}
    107         \item Dynamically tracking of the monitor-call order.
    108         \item Implement rollback semantics.
    109 \end{enumerate}
    110 While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is prohibitively complex \cit. In \CFA, users simply need to be carefull when acquiring multiple monitors at the same time.
    111 
    112 Finally, for convenience, monitors support multiple acquiring, that is acquiring a monitor while already holding it does not cause a deadlock. It simply increments an internal counter which is then used to release the monitor after the number of acquires and releases match up. This is particularly usefull when monitor routines use other monitor routines as helpers or for recursions. For example:
    113 \begin{cfacode}
    114 monitor bank {
    115         int money;
    116         log_t usr_log;
    117 };
    118 
    119 void deposit( bank & mutex b, int deposit ) {
    120         b.money += deposit;
    121         b.usr_log | "Adding" | deposit | endl;
    122 }
    123 
    124 void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
    125         deposit( mybank, -me2you );
    126         deposit( yourbank, me2you );
    127 }
    128 \end{cfacode}
    129 
    130 % ======================================================================
    131 % ======================================================================
    132 \subsection{Data semantics} \label{data}
    133 % ======================================================================
    134 % ======================================================================
    135 Once the call semantics are established, the next step is to establish data semantics. Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data. This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection. For example, here is a complete version of the counter showed in section \ref{call}:
    136 \begin{cfacode}
    137 monitor counter_t {
    138         int value;
    139 };
    140 
    141 void ?{}(counter_t & this) {
    142         this.cnt = 0;
    143 }
    144 
    145 int ?++(counter_t & mutex this) {
    146         return ++this.value;
    147 }
    148 
    149 //need for mutex is platform dependent here
    150 void ?{}(int * this, counter_t & mutex cnt) {
    151         *this = (int)cnt;
    152 }
    153 \end{cfacode}
    154 
     49monitor counter_t { /*...see section $\ref{data}$...*/ };
     50
     51void ?{}(counter_t & nomutex this); //constructor
     52size_t ++?(counter_t & mutex this); //increment
     53
     54//need for mutex is platform dependent
     55void ?{}(size_t * this, counter_t & mutex cnt); //conversion
     56\end{cfacode}
    15557This counter is used as follows:
    15658\begin{center}
     
    17173Notice how the counter is used without any explicit synchronisation and yet supports thread-safe semantics for both reading and writting.
    17274
    173 % ======================================================================
    174 % ======================================================================
    175 \subsection{Implementation Details: Interaction with polymorphism}
    176 % ======================================================================
    177 % ======================================================================
    178 Depending on the choice of semantics for when monitor locks are acquired, interaction between monitors and \CFA's concept of polymorphism can be complex to support. However, it is shown that entry-point locking solves most of the issues.
    179 
    180 First of all, interaction between \code{otype} polymorphism and monitors is impossible since monitors do not support copying. Therefore, the main question is how to support \code{dtype} polymorphism. Since a monitor's main purpose is to ensure mutual exclusion when accessing shared data, this implies that mutual exclusion is only required for routines that do in fact access shared data. However, since \code{dtype} polymorphism always handles incomplete types (by definition), no \code{dtype} polymorphic routine can access shared data since the data requires knowledge about the type. Therefore, the only concern when combining \code{dtype} polymorphism and monitors is to protect access to routines.
    181 
    182 Before looking into complex control-flow, it is important to present the difference between the two acquiring options : callsite and entry-point locking, i.e. acquiring the monitors before making a mutex routine call or as the first operation of the mutex routine-call. For example:
     75Here, the constructor(\code{?\{\}}) uses the \code{nomutex} keyword to signify that it does not acquire the monitor mutual-exclusion when constructing. This semantics is because an object not yet constructed should never be shared and therefore does not require mutual exclusion. The prefix increment operator uses \code{mutex} to protect the incrementing process from race conditions. Finally, there is a conversion operator from \code{counter_t} to \code{size_t}. This conversion may or may not require the \code{mutex} keyword depending on whether or not reading a \code{size_t} is an atomic operation.
     76
     77For maximum usability, monitors use \gls{multi-acq} semantics, which means a single thread can acquire multiple times the same monitor without deadlock. For example, figure \ref{fig:search} uses recursion and \gls{multi-acq} to print values inside a binary tree.
     78\begin{figure}
     79\label{fig:search}
     80\begin{cfacode}
     81monitor printer { ... };
     82struct tree {
     83        tree * left, right;
     84        char * value;
     85};
     86void print(printer & mutex p, char * v);
     87
     88void print(printer & mutex p, tree * t) {
     89        print(p, t->value);
     90        print(p, t->left );
     91        print(p, t->right);
     92}
     93\end{cfacode}
     94\caption{Recursive printing algorithm using \gls{multi-acq}.}
     95\end{figure}
     96
     97Having both \code{mutex} and \code{nomutex} keywords is redundant based on the meaning of a routine having neither of these keywords. For example, given a routine without qualifiers \code{void foo(counter_t & this)}, then it is reasonable that it should default to the safest option \code{mutex}, whereas assuming \code{nomutex} is unsafe and may cause subtle errors. In fact, \code{nomutex} is the "normal" parameter behaviour, with the \code{nomutex} keyword effectively stating explicitly that "this routine is not special". Another alternative is making exactly one of these keywords mandatory, which would provide the same semantics but without the ambiguity of supporting routines with neither keyword. Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing. While there are several benefits to mandatory keywords, they do bring a few challenges. Mandatory keywords in \CFA would imply that the compiler must know without doubt whether or not a parameter is a monitor or not. Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred. For this reason, \CFA only has the \code{mutex} keyword and uses no keyword to mean \code{nomutex}.
     98
     99The next semantic decision is to establish when \code{mutex} may be used as a type qualifier. Consider the following declarations:
     100\begin{cfacode}
     101int f1(monitor & mutex m);
     102int f2(const monitor & mutex m);
     103int f3(monitor ** mutex m);
     104int f4(monitor * mutex m []);
     105int f5(graph(monitor*) & mutex m);
     106\end{cfacode}
     107The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In the case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entry. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This problem can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To make the issue tractable, this project imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with at most one level of indirection (ignoring potential qualifiers). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
     108\begin{cfacode}
     109int f1(monitor & mutex m);   //Okay : recommanded case
     110int f2(monitor * mutex m);   //Okay : could be an array but probably not
     111int f3(monitor mutex m []);  //Not Okay : Array of unkown length
     112int f4(monitor ** mutex m);  //Not Okay : Could be an array
     113int f5(monitor * mutex m []); //Not Okay : Array of unkown length
     114\end{cfacode}
     115Note that not all array functions are actually distinct in the type system sense. However, even the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
     116
     117Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion often receives an object, \CFA uses an explicit mechanism to acquire mutual-exclusion. A consequence of this approach is that it extends naturally to multi-monitor calls.
     118\begin{cfacode}
     119int f(MonitorA & mutex a, MonitorB & mutex b);
     120
     121MonitorA a;
     122MonitorB b;
     123f(a,b);
     124\end{cfacode}
     125The capacity to acquire multiple locks before entering a critical section is called \emph{\gls{bulk-acq}}. In practice, writing multi-locking routines that do not lead to deadlocks is tricky. Having language support for such a feature is therefore a significant asset for \CFA. In the case presented above, \CFA guarantees that the order of aquisition is consistent across calls to routines using the same monitors as arguments. However, since \CFA monitors use \gls{multi-acq} locks, users can effectively force the acquiring order. For example, notice which routines use \code{mutex}/\code{nomutex} and how this affects aquiring order:
     126\begin{cfacode}
     127void foo(A & mutex a, B & mutex b) { //acquire a & b
     128        ...
     129}
     130
     131void bar(A & mutex a, B & /*nomutex*/ b) { //acquire a
     132        ... foo(a, b); ... //acquire b
     133}
     134
     135void baz(A & /*nomutex*/ a, B & mutex b) { //acquire b
     136        ... foo(a, b); ... //acquire a
     137}
     138\end{cfacode}
     139The \gls{multi-acq} monitor lock allows a monitor lock to be acquired by both \code{bar} or \code{baz} and acquired again in \code{foo}. In the calls to \code{bar} and \code{baz} the monitors are acquired in opposite order.
     140
     141However, such use leads to the lock acquiring order problem. In the example above, the user uses implicit ordering in the case of function \code{foo} but explicit ordering in the case of \code{bar} and \code{baz}. This subtle mistake means that calling these routines concurrently may lead to deadlock and is therefore undefined behavior. As shown on several occasion\cit, solving this problem requires:
     142\begin{enumerate}
     143        \item Dynamically tracking of the monitor-call order.
     144        \item Implement rollback semantics.
     145\end{enumerate}
     146While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is prohibitively complex \cit. In \CFA, users simply need to be carefull when acquiring multiple monitors at the same time or only use \gls{bulk-acq} of all the monitors.
     147
     148\Gls{multi-acq} and \gls{bulk-acq} can be used together in interesting ways, for example:
     149\begin{cfacode}
     150monitor bank { ... };
     151
     152void deposit( bank & mutex b, int deposit );
     153
     154void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
     155        deposit( mybank, -me2you );
     156        deposit( yourbank, me2you );
     157}
     158\end{cfacode}
     159This example shows a trivial solution to the bank account transfer problem\cit. Without \gls{multi-acq} and \gls{bulk-acq}, the solution to this problem is much more involved and requires carefull engineering.
     160
     161\subsubsection{\code{mutex} statement} \label{mutex-stmt}
     162
     163The call semantics discussed aboved have one software engineering issue, only a named routine can acquire the mutual-exclusion of a set of monitor. \CFA offers the \code{mutex} statement to workaround the need for unnecessary names, avoiding a major software engineering problem\cit. Listing \ref{lst:mutex-stmt} shows an example of the \code{mutex} statement, which introduces a new scope in which the mutual-exclusion of a set of monitor is acquired. Beyond naming, the \code{mutex} statement has no semantic difference from a routine call with \code{mutex} parameters.
     164
     165\begin{figure}
    183166\begin{center}
    184 \setlength\tabcolsep{1.5pt}
    185 \begin{tabular}{|c|c|c|}
    186 Code & \gls{callsite-locking} & \gls{entry-point-locking} \\
    187 \CFA & pseudo-code & pseudo-code \\
     167\begin{tabular}{|c|c|}
     168function call & \code{mutex} statement \\
    188169\hline
    189170\begin{cfacode}[tabsize=3]
    190 void foo(monitor& mutex a){
    191 
    192 
    193 
    194         //Do Work
    195         //...
    196 
    197 }
    198 
    199 void main() {
    200         monitor a;
    201 
    202 
    203 
    204         foo(a);
    205 
    206 }
    207 \end{cfacode} & \begin{pseudo}[tabsize=3]
    208 foo(& a) {
    209 
    210 
    211 
    212         //Do Work
    213         //...
    214 
    215 }
    216 
    217 main() {
    218         monitor a;
    219         //calling routine
    220         //handles concurrency
    221         acquire(a);
    222         foo(a);
    223         release(a);
    224 }
    225 \end{pseudo} & \begin{pseudo}[tabsize=3]
    226 foo(& a) {
    227         //called routine
    228         //handles concurrency
    229         acquire(a);
    230         //Do Work
    231         //...
    232         release(a);
    233 }
    234 
    235 main() {
    236         monitor a;
    237 
    238 
    239 
    240         foo(a);
    241 
    242 }
    243 \end{pseudo}
     171monitor M {};
     172void foo( M & mutex m ) {
     173        //critical section
     174}
     175
     176void bar( M & m ) {
     177        foo( m );
     178}
     179\end{cfacode}&\begin{cfacode}[tabsize=3]
     180monitor M {};
     181void bar( M & m ) {
     182        mutex(m) {
     183                //critical section
     184        }
     185}
     186
     187
     188\end{cfacode}
    244189\end{tabular}
    245190\end{center}
    246 
    247 \Gls{callsite-locking} is inefficient, since any \code{dtype} routine may have to obtain some lock before calling a routine, depending on whether or not the type passed is a monitor. However, with \gls{entry-point-locking} calling a monitor routine becomes exactly the same as calling it from anywhere else.
    248 
    249 Note the \code{mutex} keyword relies on the resolver, which means that in cases where a generic monitor routine is actually desired, writing a mutex routine is possible with the proper trait. This is possible because monitors are designed in terms a trait. For example:
    250 \begin{cfacode}
    251 //Incorrect
    252 //T is not a monitor
    253 forall(dtype T)
    254 void foo(T * mutex t);
    255 
    256 //Correct
    257 //this function only works on monitors
    258 //(any monitor)
    259 forall(dtype T | is_monitor(T))
    260 void bar(T * mutex t));
     191\caption{Regular call semantics vs. \code{mutex} statement}
     192\label{lst:mutex-stmt}
     193\end{figure}
     194
     195% ======================================================================
     196% ======================================================================
     197\subsection{Data semantics} \label{data}
     198% ======================================================================
     199% ======================================================================
     200Once the call semantics are established, the next step is to establish data semantics. Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data. This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection. For example, here is a complete version of the counter showed in section \ref{call}:
     201\begin{cfacode}
     202monitor counter_t {
     203        int value;
     204};
     205
     206void ?{}(counter_t & this) {
     207        this.cnt = 0;
     208}
     209
     210int ?++(counter_t & mutex this) {
     211        return ++this.value;
     212}
     213
     214//need for mutex is platform dependent here
     215void ?{}(int * this, counter_t & mutex cnt) {
     216        *this = (int)cnt;
     217}
    261218\end{cfacode}
    262219
     
    267224% ======================================================================
    268225% ======================================================================
    269 In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronisation. With monitors, this is generally achieved with internal or external scheduling as in\cit. Since internal scheduling of single monitors is mostly a solved problem, this proposal concentraits on extending internal scheduling to multiple monitors at once. Indeed, like the \gls{group-acquire} semantics, internal scheduling extends to multiple monitors at once in a way that is natural to the user but requires additional complexity on the implementation side.
     226In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronisation. With monitors, this capability is generally achieved with internal or external scheduling as in\cit. Since internal scheduling within a single monitor is mostly a solved problem, this thesis concentrates on extending internal scheduling to multiple monitors. Indeed, like the \gls{bulk-acq} semantics, internal scheduling extends to multiple monitors in a way that is natural to the user but requires additional complexity on the implementation side.
    270227
    271228First, here is a simple example of such a technique:
    272229
    273230\begin{cfacode}
    274         monitor A {
    275                 condition e;
    276         }
    277 
    278         void foo(A & mutex a) {
    279                 ...
    280                 // Wait for cooperation from bar()
    281                 wait(a.e);
    282                 ...
    283         }
    284 
    285         void bar(A & mutex a) {
    286                 // Provide cooperation for foo()
    287                 ...
    288                 // Unblock foo at scope exit
    289                 signal(a.e);
    290         }
    291 \end{cfacode}
    292 
    293 There are two details to note here. First, there \code{signal} is a delayed operation, it only unblocks the waiting thread when it reaches the end of the critical section. This is needed to respect mutual-exclusion. Second, in \CFA, \code{condition} have no particular need to be stored inside a monitor, beyond any software engineering reasons. Here routine \code{foo} waits for the \code{signal} from \code{bar} before making further progress, effectively ensuring a basic ordering.
    294 
    295 An important aspect to take into account here is that \CFA does not allow barging, which means that once function \code{bar} releases the monitor, foo is guaranteed to resume immediately after (unless some other thread waited on the same condition). This guarantees offers the benefit of not having to loop arount waits in order to guarantee that a condition is still met. The main reason \CFA offers this guarantee is that users can easily introduce barging if it becomes a necessity but adding barging prevention or barging avoidance is more involved without language support. Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design of \CFA concurrency.
     231monitor A {
     232        condition e;
     233}
     234
     235void foo(A & mutex a) {
     236        ...
     237        //Wait for cooperation from bar()
     238        wait(a.e);
     239        ...
     240}
     241
     242void bar(A & mutex a) {
     243        //Provide cooperation for foo()
     244        ...
     245        //Unblock foo
     246        signal(a.e);
     247}
     248\end{cfacode}
     249
     250There are two details to note here. First, the \code{signal} is a delayed operation, it only unblocks the waiting thread when it reaches the end of the critical section. This semantic is needed to respect mutual-exclusion. Second, in \CFA, a \code{condition} variable can be stored/created independently of a monitor. Here routine \code{foo} waits for the \code{signal} from \code{bar} before making further progress, effectively ensuring a basic ordering.
     251
     252An important aspect of the implementation is that \CFA does not allow barging, which means that once function \code{bar} releases the monitor, foo is guaranteed to resume immediately after (unless some other thread waited on the same condition). This guarantees offers the benefit of not having to loop arount waits in order to guarantee that a condition is still met. The main reason \CFA offers this guarantee is that users can easily introduce barging if it becomes a necessity but adding barging prevention or barging avoidance is more involved without language support. Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design of \CFA concurrency.
    296253
    297254% ======================================================================
     
    300257% ======================================================================
    301258% ======================================================================
    302 It is easier to understand the problem of multi-monitor scheduling using a series of pseudo-code. Note that for simplicity in the following snippets of pseudo-code, waiting and signalling is done using an implicit condition variable, like Java built-in monitors.
     259It is easier to understand the problem of multi-monitor scheduling using a series of pseudo-code. Note that for simplicity in the following snippets of pseudo-code, waiting and signalling is done using an implicit condition variable, like Java built-in monitors. Indeed, \code{wait} statements always use a single condition as paremeter and waits on the monitors associated with the condition.
    303260
    304261\begin{multicols}{2}
     
    319276\end{pseudo}
    320277\end{multicols}
    321 The example shows the simple case of having two threads (one for each column) and a single monitor A. One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling. There is an important thing to note here, both \code{wait} and \code{signal} must be called with the proper monitor(s) already acquired. This restriction is hidden on the user side in \uC, as it is a logical requirement for barging prevention.
    322 
    323 A direct extension of the previous example is the \gls{group-acquire} version:
     278The example shows the simple case of having two threads (one for each column) and a single monitor A. One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling. It is important to note here that both \code{wait} and \code{signal} must be called with the proper monitor(s) already acquired. This semantic is a logical requirement for barging prevention.
     279
     280A direct extension of the previous example is a \gls{bulk-acq} version:
    324281
    325282\begin{multicols}{2}
     
    338295\end{pseudo}
    339296\end{multicols}
    340 This version uses \gls{group-acquire} (denoted using the \& symbol), but the presence of multiple monitors does not add a particularly new meaning. Synchronization happens between the two threads in exactly the same way and order. The only difference is that mutual exclusion covers more monitors. On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
    341 
    342 While deadlock issues can occur when nesting monitors, these issues are only a symptom of the fact that locks, and by extension monitors, are not perfectly composable. However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nested is done correctly. For example, the next pseudo-code snippet acquires monitors A then B before waiting while only acquiring B when signalling, effectively avoiding the nested monitor problem.
    343 
     297This version uses \gls{bulk-acq} (denoted using the \& symbol), but the presence of multiple monitors does not add a particularly new meaning. Synchronization happens between the two threads in exactly the same way and order. The only difference is that mutual exclusion covers more monitors. On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
     298
     299While deadlock issues can occur when nesting monitors, these issues are only a symptom of the fact that locks, and by extension monitors, are not perfectly composable. For monitors, a well known deadlock problem is the Nested Monitor Problem\cit, which occurs when a \code{wait} is made on a thread that holds more than one monitor. For example, the following pseudo-code will run into the nested monitor problem :
    344300\begin{multicols}{2}
    345301\begin{pseudo}
     
    354310
    355311\begin{pseudo}
     312acquire A
     313        acquire B
     314                signal B
     315        release B
     316release A
     317\end{pseudo}
     318\end{multicols}
     319However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly. For example, the next pseudo-code snippet acquires monitors {\sf A} then {\sf B} before waiting, while only acquiring {\sf B} when signalling, effectively avoiding the nested monitor problem.
     320
     321\begin{multicols}{2}
     322\begin{pseudo}
     323acquire A
     324        acquire B
     325                wait B
     326        release B
     327release A
     328\end{pseudo}
     329
     330\columnbreak
     331
     332\begin{pseudo}
    356333
    357334acquire B
     
    362339\end{multicols}
    363340
    364 The next example is where \gls{group-acquire} adds a significant layer of complexity to the internal signalling semantics.
    365 
     341Listing \ref{lst:int-bulk-pseudo} shows an example where \gls{bulk-acq} adds a significant layer of complexity to the internal signalling semantics. Listing \ref{lst:int-bulk-cfa} shows the corresponding \CFA code which implements the pseudo-code in listing \ref{lst:int-bulk-pseudo}. Note that listing \ref{lst:int-bulk-cfa} uses non-\code{mutex} parameter to introduce monitor \code{b} into context. However, for the purpose of translating the given pseudo-code into \CFA-code any method of introducing new monitors into context, other than a \code{mutex} parameter, is acceptable, e.g. global variables, pointer parameters or using locals with the \code{mutex}-statement.
     342
     343\begin{figure}[!b]
    366344\begin{multicols}{2}
    367345Waiting thread
    368346\begin{pseudo}[numbers=left]
    369347acquire A
    370         // Code Section 1
     348        //Code Section 1
    371349        acquire A & B
    372                 // Code Section 2
     350                //Code Section 2
    373351                wait A & B
    374                 // Code Section 3
     352                //Code Section 3
    375353        release A & B
    376         // Code Section 4
     354        //Code Section 4
    377355release A
    378356\end{pseudo}
     
    383361\begin{pseudo}[numbers=left, firstnumber=10]
    384362acquire A
    385         // Code Section 5
     363        //Code Section 5
    386364        acquire A & B
    387                 // Code Section 6
     365                //Code Section 6
    388366                signal A & B
    389                 // Code Section 7
     367                //Code Section 7
    390368        release A & B
    391         // Code Section 8
    392 release A
    393 \end{pseudo}
    394 \end{multicols}
    395 \begin{center}
    396 Listing 1
    397 \end{center}
    398 
    399 It is particularly important to pay attention to code sections 8 and 4, which are where the existing semantics of internal scheduling need to be extended for multiple monitors. The root of the problem is that \gls{group-acquire} is used in a context where one of the monitors is already acquired and is why it is important to define the behaviour of the previous pseudo-code. When the signaller thread reaches the location where it should "release A \& B" (line 16), it must actually transfer ownership of monitor B to the waiting thread. This ownership trasnfer is required in order to prevent barging. Since the signalling thread still needs the monitor A, simply waking up the waiting thread is not an option because it would violate mutual exclusion. There are three options:
     369        //Code Section 8
     370release A
     371\end{pseudo}
     372\end{multicols}
     373\caption{Internal scheduling with \gls{bulk-acq}}
     374\label{lst:int-bulk-pseudo}
     375\end{figure}
     376
     377\begin{figure}[!b]
     378\begin{multicols}{2}
     379Waiting thread
     380\begin{cfacode}
     381monitor A;
     382monitor B;
     383extern condition c;
     384void foo(A & mutex a, B & b) {
     385        //Code Section 1
     386        mutex(a, b) {
     387                //Code Section 2
     388                wait(c);
     389                //Code Section 3
     390        }
     391        //Code Section 4
     392}
     393\end{cfacode}
     394
     395\columnbreak
     396
     397Signalling thread
     398\begin{cfacode}
     399monitor A;
     400monitor B;
     401extern condition c;
     402void foo(A & mutex a, B & b) {
     403        //Code Section 5
     404        mutex(a, b) {
     405                //Code Section 6
     406                signal(c);
     407                //Code Section 7
     408        }
     409        //Code Section 8
     410}
     411\end{cfacode}
     412\end{multicols}
     413\caption{Equivalent \CFA code for listing \ref{lst:int-bulk-pseudo}}
     414\label{lst:int-bulk-cfa}
     415\end{figure}
     416
     417It is particularly important to pay attention to code sections 4 and 8, which are where the existing semantics of internal scheduling need to be extended for multiple monitors. The root of the problem is that \gls{bulk-acq} is used in a context where one of the monitors is already acquired and is why it is important to define the behaviour of the previous pseudo-code. When the signaller thread reaches the location where it should "release A \& B" (line 16), it must actually transfer ownership of monitor B to the waiting thread. This ownership trasnfer is required in order to prevent barging. Since the signalling thread still needs monitor A, simply waking up the waiting thread is not an option because it would violate mutual exclusion. There are three options.
    400418
    401419\subsubsection{Delaying signals}
    402 The first more obvious solution to solve the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred. It can be argued that that moment is the correct time to transfer ownership when the last lock is no longer needed because this semantics fits most closely to the behaviour of single monitor scheduling. This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from mutiple objects to a single group of object, effectively making the existing single monitor semantic viable by simply changing monitors to monitor collections.
     420The first more obvious solution to solve the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred. It can be argued that that moment is the correct time to transfer ownership when the last lock is no longer needed because this semantics fits most closely to the behaviour of single monitor scheduling. This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from mutiple objects to a single group of objects, effectively making the existing single monitor semantic viable by simply changing monitors to monitor groups.
    403421\begin{multicols}{2}
    404422Waiter
     
    424442\end{pseudo}
    425443\end{multicols}
    426 However, this solution can become much more complicated depending on what is executed while secretly holding B (at line 10). Indeed, nothing prevents a user from signalling monitor A on a different condition variable:
    427 \newpage
     444However, this solution can become much more complicated depending on what is executed while secretly holding B (at line 10). Indeed, nothing prevents signalling monitor A on a different condition variable:
    428445\begin{multicols}{2}
    429446Thread 1
     
    446463
    447464Thread 3
    448 \begin{pseudo}[numbers=left, firstnumber=10]
     465\begin{pseudo}[numbers=left, firstnumber=9]
    449466acquire A
    450467        acquire A & B
     
    467484Note that ordering is not determined by a race condition but by whether signalled threads are enqueued in FIFO or FILO order. However, regardless of the answer, users can move line 15 before line 11 and get the reverse effect.
    468485
    469 In both cases, the threads need to be able to distinguish on a per monitor basis which ones need to be released and which ones need to be transferred. Which means monitors cannot be handled as a single homogenous group.
     486In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means monitors cannot be handled as a single homogenous group and therefore invalidates the main benefit of this approach.
    470487
    471488\subsubsection{Dependency graphs}
    472 In the Listing 1 pseudo-code, there is a solution which statisfies both barging prevention and mutual exclusion. If ownership of both monitors is transferred to the waiter when the signaller releases A and then the waiter transfers back ownership of A when it releases it then the problem is solved. Dynamically finding the correct order is therefore the second possible solution. The problem it encounters is that it effectively boils down to resolving a dependency graph of ownership requirements. Here even the simplest of code snippets requires two transfers and it seems to increase in a manner closer to polynomial. For example, the following code, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions:
     489In the Listing 1 pseudo-code, there is a solution which statisfies both barging prevention and mutual exclusion. If ownership of both monitors is transferred to the waiter when the signaller releases A and then the waiter transfers back ownership of A when it releases it, then the problem is solved. Dynamically finding the correct order is therefore the second possible solution. The problem it encounters is that it effectively boils down to resolving a dependency graph of ownership requirements. Here even the simplest of code snippets requires two transfers and it seems to increase in a manner closer to polynomial. For example, the following code, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions:
    473490
    474491\begin{multicols}{2}
     
    495512\end{pseudo}
    496513\end{multicols}
    497 Resolving dependency graph being a complex and expensive endeavour, this solution is not the preffered one.
    498 
    499 \subsubsection{Partial signalling} \label{partial-sig}
    500 Finally, the solution that is chosen for \CFA is to use partial signalling. Consider the following case:
    501 
    502 \begin{multicols}{2}
    503 \begin{pseudo}[numbers=left]
     514
     515\begin{figure}
     516\begin{multicols}{3}
     517Thread $\alpha$
     518\begin{pseudo}[numbers=left, firstnumber=1]
    504519acquire A
    505520        acquire A & B
     
    511526\columnbreak
    512527
    513 \begin{pseudo}[numbers=left, firstnumber=6]
     528Thread $\gamma$
     529\begin{pseudo}[numbers=left, firstnumber=1]
    514530acquire A
    515531        acquire A & B
    516532                signal A & B
    517533        release A & B
    518         // ... More code
    519 release A
    520 \end{pseudo}
    521 \end{multicols}
    522 The partial signalling solution transfers ownership of monitor B at lines 10 but does not wake the waiting thread since it is still using monitor A. Only when it reaches line 11 does it actually wakeup the waiting thread. This solution has the benefit that complexity is encapsulated into only two actions, passing monitors to the next owner when they should be release and conditionnaly waking threads if all conditions are met. Contrary to the other solutions, this solution quickly hits an upper bound on complexity of implementation.
     534        signal A
     535release A
     536\end{pseudo}
     537
     538\columnbreak
     539
     540Thread $\beta$
     541\begin{pseudo}[numbers=left, firstnumber=1]
     542acquire A
     543        wait A
     544release A
     545\end{pseudo}
     546
     547\end{multicols}
     548\caption{Dependency graph}
     549\label{lst:dependency}
     550\end{figure}
     551
     552\begin{figure}
     553\begin{center}
     554\input{dependency}
     555\end{center}
     556\label{fig:dependency}
     557\caption{Dependency graph of the statements in listing \ref{lst:dependency}}
     558\end{figure}
     559
     560Listing \ref{lst:dependency} is the three thread example rewritten for dependency graphs as well as the corresponding dependency graph. Figure \ref{fig:dependency} shows the corresponding dependency graph that results, where every node is a statement of one of the three threads, and the arrows the dependency of that statement. The extra challenge is that this dependency graph is effectively post-mortem, but the run time system needs to be able to build and solve these graphs as the dependency unfolds. Resolving dependency graph being a complex and expensive endeavour, this solution is not the preffered one.
     561
     562\subsubsection{Partial signalling} \label{partial-sig}
     563Finally, the solution that is chosen for \CFA is to use partial signalling. Consider the following case:
     564
     565\begin{multicols}{2}
     566\begin{pseudo}[numbers=left]
     567acquire A
     568        acquire A & B
     569                wait A & B
     570        release A & B
     571release A
     572\end{pseudo}
     573
     574\columnbreak
     575
     576\begin{pseudo}[numbers=left, firstnumber=6]
     577acquire A
     578        acquire A & B
     579                signal A & B
     580        release A & B
     581        //... More code
     582release A
     583\end{pseudo}
     584\end{multicols}
     585The partial signalling solution transfers ownership of monitor B at lines 10 but does not wake the waiting thread since it is still using monitor A. Only when it reaches line 11 does it actually wakeup the waiting thread. This solution has the benefit that complexity is encapsulated into only two actions, passing monitors to the next owner when they should be release and conditionally waking threads if all conditions are met. This solution has a much simpler implementation than a dependency graph solving algorithm which is why it was chosen.
    523586
    524587% ======================================================================
     
    529592An important note is that, until now, signalling a monitor was a delayed operation. The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the \code{signal} statement. However, in some cases, it may be more convenient for users to immediately transfer ownership to the thread that is waiting for cooperation, which is achieved using the \code{signal_block} routine\footnote{name to be discussed}.
    530593
    531 For example here is an example highlighting the difference in behaviour:
    532 \begin{center}
     594The example in listing \ref{lst:datingservice} highlights the difference in behaviour. As mentioned, \code{signal} only transfers ownership once the current critical section exits, this behaviour cause the need for additional synchronisation when a two-way handshake is needed. To avoid this extraneous synchronisation, the \code{condition} type offers the \code{signal_block} routine which handle two-way handshakes as shown in the example. This removes the need for a second condition variables and simplifies programming. Like every other monitor semantic, \code{signal_block} uses barging prevention which means mutual-exclusion is baton-passed both on the frond-end and the back-end of the call to \code{signal_block}, meaning no other thread can acquire the monitor neither before nor after the call.
     595\begin{figure}
    533596\begin{tabular}{|c|c|}
    534597\code{signal} & \code{signal_block} \\
    535598\hline
    536 \begin{cfacode}
    537 monitor M { int val; };
    538 
    539 void foo(M & mutex m ) {
    540         m.val++;
    541         sout| "Foo:" | m.val |endl;
    542 
    543         wait( c );
    544 
    545         m.val++;
    546         sout| "Foo:" | m.val |endl;
    547 }
    548 
    549 void bar(M & mutex m ) {
    550         m.val++;
    551         sout| "Bar:" | m.val |endl;
    552 
    553         signal( c );
    554 
    555         m.val++;
    556         sout| "Bar:" | m.val |endl;
    557 }
    558 \end{cfacode}&\begin{cfacode}
    559 monitor M { int val; };
    560 
    561 void foo(M & mutex m ) {
    562         m.val++;
    563         sout| "Foo:" | m.val |endl;
    564 
    565         wait( c );
    566 
    567         m.val++;
    568         sout| "Foo:" | m.val |endl;
    569 }
    570 
    571 void bar(M & mutex m ) {
    572         m.val++;
    573         sout| "Bar:" | m.val |endl;
    574 
    575         signal_block( c );
    576 
    577         m.val++;
    578         sout| "Bar:" | m.val |endl;
     599\begin{cfacode}[tabsize=3]
     600monitor DatingService
     601{
     602        //compatibility codes
     603        enum{ CCodes = 20 };
     604
     605        int girlPhoneNo
     606        int boyPhoneNo;
     607};
     608
     609condition girls[CCodes];
     610condition boys [CCodes];
     611condition exchange;
     612
     613int girl(int phoneNo, int ccode)
     614{
     615        //no compatible boy ?
     616        if(empty(boys[ccode]))
     617        {
     618                //wait for boy
     619                wait(girls[ccode]);
     620
     621                //make phone number available
     622                girlPhoneNo = phoneNo;
     623
     624                //wake boy fron chair
     625                signal(exchange);
     626        }
     627        else
     628        {
     629                //make phone number available
     630                girlPhoneNo = phoneNo;
     631
     632                //wake boy
     633                signal(boys[ccode]);
     634
     635                //sit in chair
     636                wait(exchange);
     637        }
     638        return boyPhoneNo;
     639}
     640
     641int boy(int phoneNo, int ccode)
     642{
     643        //same as above
     644        //with boy/girl interchanged
     645}
     646\end{cfacode}&\begin{cfacode}[tabsize=3]
     647monitor DatingService
     648{
     649        //compatibility codes
     650        enum{ CCodes = 20 };
     651
     652        int girlPhoneNo;
     653        int boyPhoneNo;
     654};
     655
     656condition girls[CCodes];
     657condition boys [CCodes];
     658//exchange is not needed
     659
     660int girl(int phoneNo, int ccode)
     661{
     662        //no compatible boy ?
     663        if(empty(boys[ccode]))
     664        {
     665                //wait for boy
     666                wait(girls[ccode]);
     667
     668                //make phone number available
     669                girlPhoneNo = phoneNo;
     670
     671                //wake boy fron chair
     672                signal(exchange);
     673        }
     674        else
     675        {
     676                //make phone number available
     677                girlPhoneNo = phoneNo;
     678
     679                //wake boy
     680                signal_block(boys[ccode]);
     681
     682                //second handshake unnecessary
     683
     684        }
     685        return boyPhoneNo;
     686}
     687
     688int boy(int phoneNo, int ccode)
     689{
     690        //same as above
     691        //with boy/girl interchanged
    579692}
    580693\end{cfacode}
    581694\end{tabular}
    582 \end{center}
    583 Assuming that \code{val} is initialized at 0, that each routine are called from seperate thread and that \code{foo} is always called first. The previous code would yield the following output:
    584 
    585 \begin{center}
    586 \begin{tabular}{|c|c|}
    587 \code{signal} & \code{signal_block} \\
    588 \hline
    589 \begin{pseudo}
    590 Foo: 0
    591 Bar: 1
    592 Bar: 2
    593 Foo: 3
    594 \end{pseudo}&\begin{pseudo}
    595 Foo: 0
    596 Bar: 1
    597 Foo: 2
    598 Bar: 3
    599 \end{pseudo}
    600 \end{tabular}
    601 \end{center}
    602 
    603 As mentionned, \code{signal} only transfers ownership once the current critical section exits, resulting in the second "Bar" line to be printed before the second "Foo" line. On the other hand, \code{signal_block} immediately transfers ownership to \code{bar}, causing an inversion of output. Obviously this means that \code{signal_block} is a blocking call, which will only be resumed once the signalled function exits the critical section.
    604 
    605 % ======================================================================
    606 % ======================================================================
    607 \subsection{Internal scheduling: Implementation} \label{inschedimpl}
    608 % ======================================================================
    609 % ======================================================================
    610 There are several challenges specific to \CFA when implementing internal scheduling. These challenges are direct results of \gls{group-acquire} and loose object definitions. These two constraints are to root cause of most design decisions in the implementation of internal scheduling. Furthermore, to avoid the head-aches of dynamically allocating memory in a concurrent environment, the internal-scheduling design is entirely free of mallocs and other dynamic memory allocation scheme. This is to avoid the chicken and egg problem of having a memory allocator that relies on the threading system and a threading system that relies on the runtime. This extra goal, means that memory management is a constant concern in the design of the system.
    611 
    612 The main memory concern for concurrency is queues. All blocking operations are made by parking threads onto queues. These queues need to be intrinsic\cit to avoid the need memory allocation. This entails that all the fields needed to keep track of all needed information. Since internal scheduling can use an unbound amount of memory (depending on \gls{group-acquire}) statically defining information information in the intrusive fields of threads is insufficient. The only variable sized container that does not require memory allocation is the callstack, which is heavily used in the implementation of internal scheduling. Particularly the GCC extension variable length arrays which is used extensively.
    613 
    614 Since stack allocation is based around scope, the first step of the implementation is to identify the scopes that are available to store the information, and which of these can have a variable length. In the case of external scheduling, the threads and the condition both allow a fixed amount of memory to be stored, while mutex-routines and the actual blocking call allow for an unbound amount (though adding too much to the mutex routine stack size can become expansive faster).
    615 
    616 The following figure is the traditionnal illustration of a monitor :
    617 
    618 \begin{center}
    619 {\resizebox{0.4\textwidth}{!}{\input{monitor}}}
    620 \end{center}
    621 
    622 For \CFA, the previous picture does not have support for blocking multiple monitors on a single condition. To support \gls{group-acquire} two changes to this picture are required. First, it doesn't make sense to tie the condition to a single monitor since blocking two monitors as one would require arbitrarily picking a monitor to hold the condition. Secondly, the object waiting on the conditions and AS-stack cannot simply contain the waiting thread since a single thread can potentially wait on multiple monitors. As mentionned in section \ref{inschedimpl}, the handling in multiple monitors is done by partially passing, which entails that each concerned monitor needs to have a node object. However, for waiting on the condition, since all threads need to wait together, a single object needs to be queued in the condition. Moving out the condition and updating the node types yields :
    623 
    624 \begin{center}
    625 {\resizebox{0.8\textwidth}{!}{\input{int_monitor}}}
    626 \end{center}
    627 
    628 \newpage
    629 
    630 This picture and the proper entry and leave algorithms is the fundamental implementation of internal scheduling.
    631 
    632 \begin{multicols}{2}
    633 Entry
    634 \begin{pseudo}[numbers=left]
    635 if monitor is free
    636         enter
    637 elif I already own the monitor
    638         continue
    639 else
    640         block
    641 increment recursion
    642 
    643 \end{pseudo}
    644 \columnbreak
    645 Exit
    646 \begin{pseudo}[numbers=left, firstnumber=8]
    647 decrement recursion
    648 if recursion == 0
    649         if signal_stack not empty
    650                 set_owner to thread
    651                 if all monitors ready
    652                         wake-up thread
    653 
    654         if entry queue not empty
    655                 wake-up thread
    656 \end{pseudo}
    657 \end{multicols}
    658 
    659 Some important things to notice about the exit routine. The solution discussed in \ref{inschedimpl} can be seen on line 11 of the previous pseudo code. Basically, the solution boils down to having a seperate data structure for the condition queue and the AS-stack, and unconditionally transferring ownership of the monitors but only unblocking the thread when the last monitor has trasnferred ownership. This solution is safe as well as preventing any potential barging.
     695\caption{Dating service example using \code{signal} and \code{signal_block}. }
     696\label{lst:datingservice}
     697\end{figure}
    660698
    661699% ======================================================================
     
    700738\end{tabular}
    701739\end{center}
    702 This method is more constrained and explicit, which may help users tone down the undeterministic nature of concurrency. Indeed, as the following examples demonstrates, external scheduling allows users to wait for events from other threads without the concern of unrelated events occuring. External scheduling can generally be done either in terms of control flow (e.g., \uC) or in terms of data (e.g. Go). Of course, both of these paradigms have their own strenghts and weaknesses but for this project control-flow semantics were chosen to stay consistent with the rest of the languages semantics. Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multi-monitor routines. The previous example shows a simple use \code{_Accept} versus \code{wait}/\code{signal} and its advantages. Note that while other languages often use \code{accept} as the core external scheduling keyword, \CFA uses \code{waitfor} to prevent name collisions with existing socket APIs.
    703 
    704 In the case of internal scheduling, the call to \code{wait} only guarantees that \code{V} is the last routine to access the monitor. This entails that the routine \code{V} may have acquired mutual exclusion several times while routine \code{P} was waiting. On the other hand, external scheduling guarantees that while routine \code{P} was waiting, no routine other than \code{V} could acquire the monitor.
     740This method is more constrained and explicit, which helps users tone down the undeterministic nature of concurrency. Indeed, as the following examples demonstrates, external scheduling allows users to wait for events from other threads without the concern of unrelated events occuring. External scheduling can generally be done either in terms of control flow (e.g., \uC with \code{_Accept}) or in terms of data (e.g. Go with channels). Of course, both of these paradigms have their own strenghts and weaknesses but for this project control-flow semantics were chosen to stay consistent with the rest of the languages semantics. Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multi-monitor routines. The previous example shows a simple use \code{_Accept} versus \code{wait}/\code{signal} and its advantages. Note that while other languages often use \code{accept}/\code{select} as the core external scheduling keyword, \CFA uses \code{waitfor} to prevent name collisions with existing socket \acrshort{api}s.
     741
     742In the case of internal scheduling, the call to \code{wait} only guarantees that \code{V} is the last routine to access the monitor. This entails that a third routine, say \code{isInUse()}, may have acquired mutual exclusion several times while routine \code{P} was waiting. On the other hand, external scheduling guarantees that while routine \code{P} was waiting, no routine other than \code{V} could acquire the monitor.
    705743
    706744% ======================================================================
     
    712750
    713751\begin{cfacode}
    714         monitor A {};
    715 
    716         void f(A & mutex a);
    717         void f(int a, float b);
    718         void g(A & mutex a) {
    719                 waitfor(f); // Less obvious which f() to wait for
    720         }
     752monitor A {};
     753
     754void f(A & mutex a);
     755void g(A & mutex a) {
     756        waitfor(f); //Obvious which f() to wait for
     757}
     758
     759void f(A & mutex a, int); //New different F added in scope
     760void h(A & mutex a) {
     761        waitfor(f); //Less obvious which f() to wait for
     762}
    721763\end{cfacode}
    722764
     
    728770        if monitor is free
    729771                enter
    730         elif I already own the monitor
     772        elif already own the monitor
    731773                continue
    732774        elif monitor accepts me
     
    738780\end{center}
    739781
    740 For the fist two conditions, it is easy to implement a check that can evaluate the condition in a few instruction. However, a fast check for \pscode{monitor accepts me} is much harder to implement depending on the constraints put on the monitors. Indeed, monitors are often expressed as an entry queue and some acceptor queue as in the following figure:
     782For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instruction. However, a fast check for \pscode{monitor accepts me} is much harder to implement depending on the constraints put on the monitors. Indeed, monitors are often expressed as an entry queue and some acceptor queue as in the following figure:
    741783
    742784\begin{center}
     
    744786\end{center}
    745787
    746 There are other alternatives to these pictures but in the case of this picture implementing a fast accept check is relatively easy. Indeed simply updating a bitmask when the acceptor queue changes is enough to have a check that executes in a single instruction, even with a fairly large number (e.g. 128) of mutex members. This technique cannot be used in \CFA because it relies on the fact that the monitor type declares all the acceptable routines. For OO languages this does not compromise much since monitors already have an exhaustive list of member routines. However, for \CFA this is not the case; routines can be added to a type anywhere after its declaration. Its important to note that the bitmask approach does not actually require an exhaustive list of routines, but it requires a dense unique ordering of routines with an upper-bound and that ordering must be consistent across translation units.
    747 The alternative would be to have a picture more like this one:
     788There are other alternatives to these pictures, but in the case of this picture, implementing a fast accept check is relatively easy. Indeed simply updating a bitmask when the acceptor queue changes is enough to have a check that executes in a single instruction, even with a fairly large number (e.g. 128) of mutex members. This technique cannot be used in \CFA because it relies on the fact that the monitor type declares all the acceptable routines. For OO languages this does not compromise much since monitors already have an exhaustive list of member routines. However, for \CFA this is not the case; routines can be added to a type anywhere after its declaration. Its important to note that the bitmask approach does not actually require an exhaustive list of routines, but it requires a dense unique ordering of routines with an upper-bound and that ordering must be consistent across translation units.
     789The alternative is to have a picture like this one:
    748790
    749791\begin{center}
     
    751793\end{center}
    752794
    753 Not storing the queues inside the monitor means that the storage can vary between routines, allowing for more flexibility and extensions. Storing an array of function-pointers would solve the issue of uniquely identifying acceptable routines. However, the single instruction bitmask compare has been replaced by dereferencing a pointer followed by a linear search. Furthermore, supporting nested external scheduling may now require additionnal searches on calls to waitfor to check if a routine is already queued in.
    754 
    755 At this point we must make a decision between flexibility and performance. Many design decisions in \CFA achieve both flexibility and performance, for example polymorphic routines add significant flexibility but inlining them means the optimizer can easily remove any runtime cost. Here however, the cost of flexibility cannot be trivially removed. In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be prohibitively hard to write. This is based on the assumption that writing fast but inflexible locks is closer to a solved problems than writing locks that are as flexible as external scheduling in \CFA.
    756 
    757 Another aspect to consider is what happens if multiple overloads of the same routine are used. For the time being it is assumed that multiple overloads of the same routine are considered as distinct routines. However, this could easily be extended in the future.
     795Not storing the mask inside the monitor means that the storage for the mask information can vary between calls to \code{waitfor}, allowing for more flexibility and extensions. Storing an array of function-pointers would solve the issue of uniquely identifying acceptable routines. However, the single instruction bitmask compare has been replaced by dereferencing a pointer followed by a linear search. Furthermore, supporting nested external scheduling may now require additionnal searches on calls to waitfor to check if a routine is already queued in.
     796
     797Note that in the second picture, tasks need to always keep track of through which routine they are attempting to acquire the monitor and the routine mask needs to have both a function pointer and a set of monitors, as will be discussed in the next section. These details where omitted from the picture for the sake of simplifying the representation.
     798
     799At this point we must make a decision between flexibility and performance. Many design decisions in \CFA achieve both flexibility and performance, for example polymorphic routines add significant flexibility but inlining them means the optimizer can easily remove any runtime cost. Here however, the cost of flexibility cannot be trivially removed. In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be prohibitively hard to write. This decision is based on the assumption that writing fast but inflexible locks is closer to a solved problems than writing locks that are as flexible as external scheduling in \CFA.
    758800
    759801% ======================================================================
     
    763805% ======================================================================
    764806
    765 External scheduling, like internal scheduling, becomes orders of magnitude more complex when we start introducing multi-monitor syntax. Even in the simplest possible case some new semantics need to be established:
    766 \begin{cfacode}
    767         mutex struct A {};
    768 
    769         mutex struct B {};
    770 
    771         void g(A & mutex a, B & mutex b) {
    772                 waitfor(f); //ambiguous, which monitor
    773         }
     807External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax. Even in the simplest possible case, some new semantics need to be established:
     808\begin{cfacode}
     809monitor M {};
     810
     811void f(M & mutex a);
     812
     813void g(M & mutex a, M & mutex b) {
     814        waitfor(f); //ambiguous, keep a pass b or other way around?
     815}
    774816\end{cfacode}
    775817
     
    777819
    778820\begin{cfacode}
    779         mutex struct A {};
    780 
    781         mutex struct B {};
    782 
    783         void g(A & mutex a, B & mutex b) {
    784                 waitfor( f, b );
    785         }
    786 \end{cfacode}
    787 
    788 This is unambiguous. Both locks will be acquired and kept, when routine \code{f} is called the lock for monitor \code{b} will be temporarily transferred from \code{g} to \code{f} (while \code{g} still holds lock \code{a}). This behavior can be extended to multi-monitor waitfor statment as follows.
    789 
    790 \begin{cfacode}
    791         mutex struct A {};
    792 
    793         mutex struct B {};
    794 
    795         void g(A & mutex a, B & mutex b) {
    796                 waitfor( f, a, b);
    797         }
    798 \end{cfacode}
    799 
    800 Note that the set of monitors passed to the \code{waitfor} statement must be entirely contained in the set of monitor already acquired in the routine. \code{waitfor} used in any other context is Undefined Behaviour.
    801 
    802 An important behavior to note is that what happens when set of monitors only match partially :
    803 
    804 \begin{cfacode}
    805         mutex struct A {};
    806 
    807         mutex struct B {};
    808 
    809         void g(A & mutex a, B & mutex b) {
    810                 waitfor(f, a, b);
    811         }
    812 
    813         A a1, a2;
    814         B b;
    815 
    816         void foo() {
    817                 g(a1, b);
    818         }
    819 
    820         void bar() {
    821                 f(a2, b);
    822         }
    823 \end{cfacode}
    824 
    825 While the equivalent can happen when using internal scheduling, the fact that conditions are branded on first use means that users have to use two different condition variables. In both cases, partially matching monitor sets will not wake-up the waiting thread. It is also important to note that in the case of external scheduling, as for routine calls, the order of parameters is important; \code{waitfor(f,a,b)} and \code{waitfor(f,b,a)} are to distinct waiting condition.
    826 
    827 % ======================================================================
    828 % ======================================================================
    829 \subsection{Implementation Details: External scheduling queues}
    830 % ======================================================================
    831 % ======================================================================
    832 To support multi-monitor external scheduling means that some kind of entry-queues must be used that is aware of both monitors. However, acceptable routines must be aware of the entry queues which means they must be stored inside at least one of the monitors that will be acquired. This in turn adds the requirement a systematic algorithm of disambiguating which queue is relavant regardless of user ordering. The proposed algorithm is to fall back on monitors lock ordering and specify that the monitor that is acquired first is the lock with the relevant entry queue. This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint. This algorithm choice has two consequences, the entry queue of the highest priority monitor is no longer a true FIFO queue and the queue of the lowest priority monitor is both required and probably unused. The queue can no longer be a FIFO queue because instead of simply containing the waiting threads in order arrival, they also contain the second mutex. Therefore, another thread with the same highest priority monitor but a different lowest priority monitor may arrive first but enter the critical section after a thread with the correct pairing. Secondly, since it may not be known at compile time which monitor will be the lowest priority monitor, every monitor needs to have the correct queues even though it is probable that half the multi-monitor queues will go unused for the entire duration of the program.
    833 
    834 % ======================================================================
    835 % ======================================================================
    836 \section{Other concurrency tools}
    837 % ======================================================================
    838 % ======================================================================
    839 % \TODO
     821monitor M {};
     822
     823void f(M & mutex a);
     824
     825void g(M & mutex a, M & mutex b) {
     826        waitfor( f, b );
     827}
     828\end{cfacode}
     829
     830This syntax is unambiguous. Both locks are acquired and kept. When routine \code{f} is called, the lock for monitor \code{b} is temporarily transferred from \code{g} to \code{f} (while \code{g} still holds lock \code{a}). This behavior can be extended to multi-monitor waitfor statement as follows.
     831
     832\begin{cfacode}
     833monitor M {};
     834
     835void f(M & mutex a, M & mutex b);
     836
     837void g(M & mutex a, M & mutex b) {
     838        waitfor( f, a, b);
     839}
     840\end{cfacode}
     841
     842Note that the set of monitors passed to the \code{waitfor} statement must be entirely contained in the set of monitors already acquired in the routine. \code{waitfor} used in any other context is Undefined Behaviour.
     843
     844An important behavior to note is that what happens when a set of monitors only match partially :
     845
     846\begin{cfacode}
     847mutex struct A {};
     848
     849mutex struct B {};
     850
     851void g(A & mutex a, B & mutex b) {
     852        waitfor(f, a, b);
     853}
     854
     855A a1, a2;
     856B b;
     857
     858void foo() {
     859        g(a1, b); //block on accept
     860}
     861
     862void bar() {
     863        f(a2, b); //fufill cooperation
     864}
     865\end{cfacode}
     866
     867While the equivalent can happen when using internal scheduling, the fact that conditions are specific to a set of monitors means that users have to use two different condition variables. In both cases, partially matching monitor sets does not wake-up the waiting thread. It is also important to note that in the case of external scheduling, as for routine calls, the order of parameters is important; \code{waitfor(f,a,b)} and \code{waitfor(f,b,a)} are to distinct waiting condition.
     868
     869% ======================================================================
     870% ======================================================================
     871\subsection{\code{waitfor} semantics}
     872% ======================================================================
     873% ======================================================================
     874
     875Syntactically, the \code{waitfor} statement takes a function identifier and a set of monitors. While the set of monitors can be any list of expression, the function name is more restricted. This is because the compiler validates at compile time the validity of the waitfor statement. It checks that the set of monitor passed in matches the requirements for a function call. Listing \ref{lst:waitfor} shows various usage of the waitfor statement and which are acceptable. The choice of the function type is made ignoring any non-\code{mutex} parameter. One limitation of the current implementation is that it does not handle overloading.
     876\begin{figure}
     877\begin{cfacode}
     878monitor A{};
     879monitor B{};
     880
     881void f1( A & mutex );
     882void f2( A & mutex, B & mutex );
     883void f3( A & mutex, int );
     884void f4( A & mutex, int );
     885void f4( A & mutex, double );
     886
     887void foo( A & mutex a1, A & mutex a2, B & mutex b1, B & b2 ) {
     888        A * ap = & a1;
     889        void (*fp)( A & mutex ) = f1;
     890
     891        waitfor(f1, a1);     //Correct : 1 monitor case
     892        waitfor(f2, a1, b1); //Correct : 2 monitor case
     893        waitfor(f3, a1);     //Correct : non-mutex arguments are ignored
     894        waitfor(f1, *ap);    //Correct : expression as argument
     895
     896        waitfor(f1, a1, b1); //Incorrect : Too many mutex arguments
     897        waitfor(f2, a1);     //Incorrect : Too few mutex arguments
     898        waitfor(f2, a1, a2); //Incorrect : Mutex arguments don't match
     899        waitfor(f1, 1);      //Incorrect : 1 not a mutex argument
     900        waitfor(f4, a1);     //Incorrect : f9 not a function
     901        waitfor(*fp, a1 );   //Incorrect : fp not a identifier
     902        waitfor(f4, a1);     //Incorrect : f4 ambiguous
     903
     904        waitfor(f2, a1, b2); //Undefined Behaviour : b2 may not acquired
     905}
     906\end{cfacode}
     907\caption{Various correct and incorrect uses of the waitfor statement}
     908\label{lst:waitfor}
     909\end{figure}
     910
     911Finally, for added flexibility, \CFA supports constructing complex waitfor mask using the \code{or}, \code{timeout} and \code{else}. Indeed, multiple \code{waitfor} can be chained together using \code{or}; this chain will form a single statement which will baton-pass to any one function that fits one of the function+monitor set which was passed in. To eanble users to tell which was the accepted function, \code{waitfor}s are followed by a statement (including the null statement \code{;}) or a compound statement. When multiple \code{waitfor} are chained together, only the statement corresponding to the accepted function is executed. A \code{waitfor} chain can also be followed by a \code{timeout}, to signify an upper bound on the wait, or an \code{else}, to signify that the call should be non-blocking, that is only check of a matching function already arrived and return immediately otherwise. Any and all of these clauses can be preceded by a \code{when} condition to dynamically construct the mask based on some current state. Listing \ref{lst:waitfor2}, demonstrates several complex masks and some incorrect ones.
     912
     913\begin{figure}
     914\begin{cfacode}
     915monitor A{};
     916
     917void f1( A & mutex );
     918void f2( A & mutex );
     919
     920void foo( A & mutex a, bool b, int t ) {
     921        //Correct : blocking case
     922        waitfor(f1, a);
     923
     924        //Correct : block with statement
     925        waitfor(f1, a) {
     926                sout | "f1" | endl;
     927        }
     928
     929        //Correct : block waiting for f1 or f2
     930        waitfor(f1, a) {
     931                sout | "f1" | endl;
     932        } or waitfor(f2, a) {
     933                sout | "f2" | endl;
     934        }
     935
     936        //Correct : non-blocking case
     937        waitfor(f1, a); or else;
     938
     939        //Correct : non-blocking case
     940        waitfor(f1, a) {
     941                sout | "blocked" | endl;
     942        } or else {
     943                sout | "didn't block" | endl;
     944        }
     945
     946        //Correct : block at most 10 seconds
     947        waitfor(f1, a) {
     948                sout | "blocked" | endl;
     949        } or timeout( 10`s) {
     950                sout | "didn't block" | endl;
     951        }
     952
     953        //Correct : block only if b == true
     954        //if b == false, don't even make the call
     955        when(b) waitfor(f1, a);
     956
     957        //Correct : block only if b == true
     958        //if b == false, make non-blocking call
     959        waitfor(f1, a); or when(!b) else;
     960
     961        //Correct : block only of t > 1
     962        waitfor(f1, a); or when(t > 1) timeout(t); or else;
     963
     964        //Incorrect : timeout clause is dead code
     965        waitfor(f1, a); or timeout(t); or else;
     966
     967        //Incorrect : order must be
     968        //waitfor [or waitfor... [or timeout] [or else]]
     969        timeout(t); or waitfor(f1, a); or else;
     970}
     971\end{cfacode}
     972\caption{Various correct and incorrect uses of the or, else, and timeout clause around a waitfor statement}
     973\label{lst:waitfor2}
     974\end{figure}
  • doc/proposals/concurrency/text/intro.tex

    rb96ec83 r6840e7c  
    33% ======================================================================
    44
    5 This proposal provides a minimal concurrency API that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of the concurrency, in \CFA. Indeed, for highly productive parallel programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. Therefore a high-level approach is adapted in \CFA
     5This thesis provides a minimal concurrency \acrshort{api} that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of concurrency. Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. The high-level approach and its minimal \acrshort{api} are tested in a dialect of C, call \CFA. [Is there value to say that this thesis is also an early definition of the \CFA language and library in regards to concurrency?]
    66
    7 There are actually two problems that need to be solved in the design of concurrency for a programming language: which concurrency and which parallelism tools are available to the users. While these two concepts are often combined, they are in fact distinct concepts that require different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
     7There are actually two problems that need to be solved in the design of concurrency for a programming language: which concurrency and which parallelism tools are available to the programmer. While these two concepts are often combined, they are in fact distinct, requiring different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
  • doc/proposals/concurrency/text/parallelism.tex

    rb96ec83 r6840e7c  
    1111\section{Paradigm}
    1212\subsection{User-level threads}
    13 A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensives costs of using kernel threads. The down side is that almost none of the low-level threading problems are hidden, users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
     13A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensive costs of kernel threads. The down side is that almost none of the low-level threading problems are hidden; users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
    1414
    1515Examples of languages that support \glspl{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    1616
    1717\subsection{Fibers : user-level threads without preemption}
    18 A popular varient of \glspl{uthread} is what is often reffered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.
     18A popular varient of \glspl{uthread} is what is often refered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial, and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.
    1919
    2020An example of a language that uses fibers is Go~\cite{Go}
    2121
    2222\subsection{Jobs and thread pools}
    23 The approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limits the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
     23An approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work, called jobs, and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limit the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
    2424
    2525The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    2626
    2727\subsection{Paradigm performance}
    28 While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead. However, interactions between jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but context switches will be more expansive and the extra control means users need to tweak more variables to get the desired performance. Furthermore, if the units of uninterrupted work are large enough the paradigm choice is largely amorticised by the actual work done.
     28While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead (i.e., not thread stack per job). However, interactions among jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but a context switch is more expensive and the extra control means users need to tweak more variables to get the desired performance. Finally, if the units of uninterrupted work are large enough the paradigm choice is largely amortised by the actual work done.
    2929
    30 \newpage
    3130\TODO
    32 \subsection{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
     31
     32\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
    3333
    3434
     35\subsection{Future Work: Machine setup}\label{machine}
     36While this was not done in the context of this thesis, another important aspect of clusters is affinity. While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heteregenous setups. For example, system using \acrshort{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certains CPU cores. OS support for CPU affinity is now common \cit, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
     37
    3538\subsection{Paradigms}\label{cfaparadigms}
    36 Given these building blocks we can then reproduce the all three of the popular paradigms. Indeed, we get \glspl{uthread} as the default paradigm in \CFA. However, disabling \glspl{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application.
    37 
    38 % \subsection{High-level options}\label{tasks}
    39 %
    40 % \subsubsection{Thread interface}
    41 % constructors destructors
    42 %       initializer lists
    43 % monitors
    44 %
    45 % \subsubsection{Futures}
    46 %
    47 % \subsubsection{Implicit threading}
    48 % Finally, simpler applications can benefit greatly from having implicit parallelism. That is, parallelism that does not rely on the user to write concurrency. This type of parallelism can be achieved both at the language level and at the system level.
    49 %
    50 % \begin{center}
    51 % \begin{tabular}[t]{|c|c|c|}
    52 % Sequential & System Parallel & Language Parallel \\
    53 % \begin{lstlisting}
    54 % void big_sum(int* a, int* b,
    55 %                int* out,
    56 %                size_t length)
    57 % {
    58 %       for(int i = 0; i < length; ++i ) {
    59 %               out[i] = a[i] + b[i];
    60 %       }
    61 % }
    62 %
    63 %
    64 %
    65 %
    66 %
    67 % int* a[10000];
    68 % int* b[10000];
    69 % int* c[10000];
    70 % //... fill in a and b ...
    71 % big_sum(a, b, c, 10000);
    72 % \end{lstlisting} &\begin{lstlisting}
    73 % void big_sum(int* a, int* b,
    74 %                int* out,
    75 %                size_t length)
    76 % {
    77 %       range ar(a, a + length);
    78 %       range br(b, b + length);
    79 %       range or(out, out + length);
    80 %       parfor( ai, bi, oi,
    81 %       [](int* ai, int* bi, int* oi) {
    82 %               oi = ai + bi;
    83 %       });
    84 % }
    85 %
    86 % int* a[10000];
    87 % int* b[10000];
    88 % int* c[10000];
    89 % //... fill in a and b ...
    90 % big_sum(a, b, c, 10000);
    91 % \end{lstlisting}&\begin{lstlisting}
    92 % void big_sum(int* a, int* b,
    93 %                int* out,
    94 %                size_t length)
    95 % {
    96 %       for (ai, bi, oi) in (a, b, out) {
    97 %               oi = ai + bi;
    98 %       }
    99 % }
    100 %
    101 %
    102 %
    103 %
    104 %
    105 % int* a[10000];
    106 % int* b[10000];
    107 % int* c[10000];
    108 % //... fill in a and b ...
    109 % big_sum(a, b, c, 10000);
    110 % \end{lstlisting}
    111 % \end{tabular}
    112 % \end{center}
    113 %
    114 % \subsection{Machine setup}\label{machine}
    115 % Threads are all good and well but wee still some OS support to fully utilize available hardware.
    116 %
    117 % \textbf{\large{Work in progress...}} Do wee need something beyond specifying the number of kernel threads?
     39Given these building blocks, it is possible to reproduce all three of the popular paradigms. Indeed, \glspl{uthread} is the default paradigm in \CFA. However, disabling \glspl{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application. Finally, it is possible to build executors for thread pools from \glspl{uthread} or \glspl{fiber}.
  • doc/proposals/concurrency/thesis.tex

    rb96ec83 r6840e7c  
    11% requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended
    22
    3 % inline code ©...© (copyright symbol) emacs: C-q M-)
    4 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    5 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    6 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    7 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    8 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     3% inline code �...� (copyright symbol) emacs: C-q M-)
     4% red highlighting �...� (registered trademark symbol) emacs: C-q M-.
     5% blue highlighting �...� (sharp s symbol) emacs: C-q M-_
     6% green highlighting �...� (cent symbol) emacs: C-q M-"
     7% LaTex escape �...� (section symbol) emacs: C-q M-'
     8% keyword escape �...� (pilcrow symbol) emacs: C-q M-^
    99% math escape $...$ (dollar symbol)
    1010
     
    2727\usepackage{multicol}
    2828\usepackage[acronym]{glossaries}
    29 \usepackage{varioref}   
     29\usepackage{varioref}
    3030\usepackage{listings}                                           % format program code
    3131\usepackage[flushmargin]{footmisc}                              % support label/reference in footnote
     
    7070%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    7171
    72 \setcounter{secnumdepth}{3}                           % number subsubsections
    73 \setcounter{tocdepth}{3}                              % subsubsections in table of contents
     72\setcounter{secnumdepth}{2}                           % number subsubsections
     73\setcounter{tocdepth}{2}                              % subsubsections in table of contents
    7474% \linenumbers                                          % comment out to turn off line numbering
    7575\makeindex
     
    103103\input{parallelism}
    104104
    105 \chapter{Putting it all together}
     105\input{internals}
     106
     107\input{together}
     108
     109\input{future}
    106110
    107111\chapter{Conclusion}
    108 
    109 \chapter{Future work}
    110 Concurrency and parallelism is still a very active field that strongly benefits from hardware advances. As such certain features that aren't necessarily mature enough in their current state could become relevant in the lifetime of \CFA.
    111 \subsection{Transactions}
    112112
    113113\section*{Acknowledgements}
  • doc/proposals/concurrency/version

    rb96ec83 r6840e7c  
    1 0.9.180
     10.10.212
  • src/CodeGen/CodeGenerator.cc

    rb96ec83 r6840e7c  
    287287        void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
    288288                assertf( ! genC, "TypeDecls should not reach code generation." );
    289                 output << typeDecl->genTypeString() << " " << typeDecl->get_name();
    290                 if ( typeDecl->get_kind() != TypeDecl::Any && typeDecl->get_sized() ) {
    291                         output << " | sized(" << typeDecl->get_name() << ")";
    292                 }
    293                 if ( ! typeDecl->get_assertions().empty() ) {
     289                output << typeDecl->genTypeString() << " " << typeDecl->name;
     290                if ( typeDecl->get_kind() != TypeDecl::Any && typeDecl->sized ) {
     291                        output << " | sized(" << typeDecl->name << ")";
     292                }
     293                if ( ! typeDecl->assertions.empty() ) {
    294294                        output << " | { ";
    295                         genCommaList( typeDecl->get_assertions().begin(), typeDecl->get_assertions().end() );
     295                        for ( DeclarationWithType * assert :  typeDecl->assertions ) {
     296                                assert->accept( *visitor );
     297                                output << "; ";
     298                        }
    296299                        output << " }";
    297300                }
     
    946949                output << ";";
    947950        }
     951        void CodeGenerator::postvisit( CatchStmt * stmt ) {
     952                assertf( ! genC, "Catch statements should not reach code generation." );
     953
     954                output << ((stmt->get_kind() == CatchStmt::Terminate) ?
     955                "catch" : "catchResume");
     956                output << "( ";
     957                stmt->decl->accept( *visitor );
     958                output << " ) ";
     959
     960                if( stmt->cond ) {
     961                        output << "if/when(?) (";
     962                        stmt->cond->accept( *visitor );
     963                        output << ") ";
     964                }
     965                stmt->body->accept( *visitor );
     966        }
     967
     968        void CodeGenerator::postvisit( WaitForStmt * stmt ) {
     969                assertf( ! genC, "Waitfor statements should not reach code generation." );
     970
     971                bool first = true;
     972                for( auto & clause : stmt->clauses ) {
     973                        if(first) { output << "or "; first = false; }
     974                        if( clause.condition ) {
     975                                output << "when(";
     976                                stmt->timeout.condition->accept( *visitor );
     977                                output << ") ";
     978                        }
     979                        output << "waitfor(";
     980                        clause.target.function->accept( *visitor );
     981                        for( Expression * expr : clause.target.arguments ) {
     982                                output << ",";
     983                                expr->accept( *visitor );
     984                        }
     985                        output << ") ";
     986                        clause.statement->accept( *visitor );
     987                }
     988
     989                if( stmt->timeout.statement ) {
     990                        output << "or ";
     991                        if( stmt->timeout.condition ) {
     992                                output << "when(";
     993                                stmt->timeout.condition->accept( *visitor );
     994                                output << ") ";
     995                        }
     996                        output << "timeout(";
     997                        stmt->timeout.time->accept( *visitor );
     998                        output << ") ";
     999                        stmt->timeout.statement->accept( *visitor );
     1000                }
     1001
     1002                if( stmt->orelse.statement ) {
     1003                        output << "or ";
     1004                        if( stmt->orelse.condition ) {
     1005                                output << "when(";
     1006                                stmt->orelse.condition->accept( *visitor );
     1007                                output << ")";
     1008                        }
     1009                        output << "else ";
     1010                        stmt->orelse.statement->accept( *visitor );
     1011                }
     1012        }
     1013
    9481014
    9491015        void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
     
    10241090        }
    10251091} // namespace CodeGen
     1092
     1093
     1094unsigned Indenter::tabsize = 2;
    10261095
    10271096std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ) {
  • src/CodeGen/CodeGenerator.h

    rb96ec83 r6840e7c  
    100100                void postvisit( ReturnStmt * );
    101101                void postvisit( ThrowStmt * );
     102                void postvisit( CatchStmt * );
     103                void postvisit( WaitForStmt * );
    102104                void postvisit( WhileStmt * );
    103105                void postvisit( ForStmt * );
  • src/CodeGen/FixNames.cc

    rb96ec83 r6840e7c  
    6666                );
    6767
    68                 mainDecl->get_functionType()->get_parameters().push_back(
     68                main_type->get_parameters().push_back(
    6969                        new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr )
    7070                );
    7171
    72                 mainDecl->get_functionType()->get_parameters().push_back(
     72                main_type->get_parameters().push_back(
    7373                        new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
    7474                        new PointerType( Type::Qualifiers(), new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Char ) ) ),
  • src/CodeGen/GenType.cc

    rb96ec83 r6840e7c  
    210210
    211211        std::string GenType::handleGeneric( ReferenceToType * refType ) {
    212                 if ( ! refType->get_parameters().empty() ) {
     212                if ( ! refType->parameters.empty() ) {
    213213                        std::ostringstream os;
    214214                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    215215                        os << "(";
    216                         cg.pass.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );
     216                        cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
    217217                        os << ") ";
    218218                        return os.str();
  • src/Common/Indenter.h

    rb96ec83 r6840e7c  
    1818
    1919struct Indenter {
    20         Indenter( unsigned int amt = 2 ) : amt( amt ) {}
    21         unsigned int amt = 2;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
    22         unsigned int indent = 0;
     20        static unsigned tabsize;
     21
     22        Indenter( unsigned int amt = tabsize, unsigned int indent = 0 ) : amt( amt ), indent( indent ) {}
     23        unsigned int amt;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
     24        unsigned int indent;
    2325
    2426        Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; }
     
    3032};
    3133
    32 inline std::ostream & operator<<( std::ostream & out, Indenter & indent ) {
     34inline std::ostream & operator<<( std::ostream & out, const Indenter & indent ) {
    3335        return out << std::string(indent.indent, ' ');
    3436}
  • src/Common/PassVisitor.h

    rb96ec83 r6840e7c  
    44
    55#include <stack>
     6
     7#include "Common/utility.h"
    68
    79#include "SynTree/Mutator.h"
     
    236238        virtual Attribute * mutate( Attribute * attribute ) override final;
    237239
     240        virtual TypeSubstitution * mutate( TypeSubstitution * sub ) final;
     241
    238242private:
    239243        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    240244        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     245        template< typename TreeType, typename pass_t > friend void maybeAccept_impl( TreeType * tree, PassVisitor< pass_t > & visitor );
     246        template< typename TreeType, typename pass_t > friend void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_t > & mutator );
     247        template< typename Container, typename pass_t > friend void maybeAccept_impl( Container & container, PassVisitor< pass_t > & visitor );
     248        template< typename Container, typename pass_t > friend void maybeMutate_impl( Container & container, PassVisitor< pass_t > & mutator );
    241249
    242250        template<typename node_type> void call_previsit ( node_type * node ) { previsit_impl ( pass, node, 0 ); }
     
    273281        std::list< Declaration* > *     get_afterDecls () { return declsToAddAfter_impl ( pass, 0); }
    274282
    275         void set_visit_children( bool& ref ) { bool_ref * ptr = visit_children_impl(pass, 0); if(ptr) ptr->set( ref ); }
     283        bool       get_visit_children    () { bool_ref * ptr = visit_children_impl(pass, 0); return ptr ? *ptr : true; }
     284        bool_ref * get_visit_children_ptr() { return visit_children_impl(pass, 0); }
    276285
    277286        void indexerScopeEnter  ()                             { indexer_impl_enterScope  ( pass, 0       ); }
  • src/Common/PassVisitor.impl.h

    rb96ec83 r6840e7c  
    22// IWYU pragma: private, include "PassVisitor.h"
    33
    4 #define VISIT_START( node )                     \
    5         __attribute__((unused))                   \
     4#define VISIT_START( node )                                     \
     5        __attribute__((unused))                                   \
     6        ChildrenGuard children_guard( get_visit_children_ptr() ); \
     7        __attribute__((unused))                                   \
    68        guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
    7         bool visit_children = true;               \
    8         set_visit_children( visit_children );   \
    9         call_previsit( node );                    \
    10         if( visit_children ) {                    \
     9        call_previsit( node );                                    \
    1110
    1211#define VISIT_END( node )                       \
    13         }                                         \
    1412        call_postvisit( node );                   \
    1513
    16 #define MUTATE_START( node )                    \
    17         __attribute__((unused))                   \
     14#define MUTATE_START( node )                                    \
     15        __attribute__((unused))                                   \
     16        ChildrenGuard children_guard( get_visit_children_ptr() ); \
     17        __attribute__((unused))                                   \
    1818        guard_value_impl guard( at_cleanup_impl(pass, 0) );       \
    19         bool visit_children = true;               \
    20         set_visit_children( visit_children );   \
    21         call_premutate( node );                   \
    22         if( visit_children ) {                    \
     19        call_premutate( node );                                   \
    2320
    2421#define MUTATE_END( type, node )                \
    25         }                                         \
    2622        return call_postmutate< type * >( node ); \
    2723
    2824
    29 #define VISIT_BODY( node )        \
    30         VISIT_START( node );        \
    31         Visitor::visit( node );     \
    32         VISIT_END( node );          \
    33 
    34 
    35 #define MUTATE_BODY( type, node ) \
    36         MUTATE_START( node );       \
    37         Mutator::mutate( node );    \
    38         MUTATE_END( type, node );   \
     25#define VISIT_BODY( node )          \
     26        VISIT_START( node );          \
     27        if( children_guard ) {        \
     28                Visitor::visit( node ); \
     29        }                             \
     30        VISIT_END( node );            \
     31
     32
     33#define MUTATE_BODY( type, node )    \
     34        MUTATE_START( node );          \
     35        if( children_guard ) {         \
     36                Mutator::mutate( node ); \
     37        }                              \
     38        MUTATE_END( type, node );      \
    3939
    4040
     
    6363template< typename pass_type >
    6464static inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
    65 
    6665        DeclList_t* beforeDecls = visitor.get_beforeDecls();
    6766        DeclList_t* afterDecls  = visitor.get_afterDecls();
     
    7675                try {
    7776                        // run visitor on declaration
    78                         maybeAccept( *i, visitor );
     77                        maybeAccept_impl( *i, visitor );
    7978                } catch( SemanticError &e ) {
    8079                        e.set_location( (*i)->location );
     
    9291template< typename pass_type >
    9392static inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
    94 
    9593        DeclList_t* beforeDecls = mutator.get_beforeDecls();
    9694        DeclList_t* afterDecls  = mutator.get_afterDecls();
     
    104102                try {
    105103                        // run mutator on declaration
    106                         *i = maybeMutate( *i, mutator );
     104                        maybeMutate_impl( *i, mutator );
    107105                } catch( SemanticError &e ) {
    108106                        e.set_location( (*i)->location );
     
    118116}
    119117
    120 template< typename Container, typename VisitorType >
    121 inline void maybeAccept( Container &container, VisitorType &visitor ) {
     118template< typename TreeType, typename pass_type >
     119inline void maybeAccept_impl( TreeType * tree, PassVisitor< pass_type > & visitor ) {
     120        if ( ! visitor.get_visit_children() ) return;
     121        if ( tree ) {
     122                tree->accept( visitor );
     123        }
     124}
     125
     126template< typename Container, typename pass_type >
     127inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
     128        if ( ! visitor.get_visit_children() ) return;
    122129        SemanticError errors;
    123130        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
     
    136143}
    137144
    138 template< typename Container, typename MutatorType >
    139 inline void maybeMutateRef( Container &container, MutatorType &mutator ) {
     145template< typename TreeType, typename pass_type >
     146inline void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_type > & mutator ) {
     147        if ( ! mutator.get_visit_children() ) return;
     148
     149        if ( tree ) {
     150                tree = strict_dynamic_cast< TreeType * >( tree->acceptMutator( mutator ) );
     151        }
     152}
     153
     154template< typename Container, typename pass_type >
     155inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
     156        if ( ! mutator.get_visit_children() ) return;
    140157        SemanticError errors;
    141158        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    142159                try {
    143160                        if ( *i ) {
    144 ///                 *i = (*i)->acceptMutator( mutator );
    145161                                *i = dynamic_cast< typename Container::value_type >( (*i)->acceptMutator( mutator ) );
    146162                                assert( *i );
     
    159175template< typename func_t >
    160176void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
     177        if ( ! get_visit_children() ) return;
    161178        SemanticError errors;
    162179
     
    199216void PassVisitor< pass_type >::visitStatementList( std::list< Statement * > & statements ) {
    200217        handleStatementList( statements, [this]( Statement * stmt) {
    201                 stmt->accept( *this );
     218                maybeAccept_impl( stmt, *this );
    202219        });
    203220}
     
    206223void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
    207224        handleStatementList( statements, [this]( Statement *& stmt) {
    208                 stmt = stmt->acceptMutator( *this );
     225                maybeMutate_impl( stmt, *this );
    209226        });
    210227}
     
    214231template< typename func_t >
    215232Statement * PassVisitor< pass_type >::handleStatement( Statement * stmt, func_t func ) {
     233        if ( ! get_visit_children() ) return stmt;
     234
    216235        // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    217236        ValueGuardPtr< TypeSubstitution * >  oldEnv        ( get_env_ptr    () );
     
    244263Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
    245264        return handleStatement( stmt, [this]( Statement * stmt ) {
    246                 maybeAccept( stmt, *this );
     265                maybeAccept_impl( stmt, *this );
    247266                return stmt;
    248267        });
     
    252271Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
    253272        return handleStatement( stmt, [this]( Statement * stmt ) {
    254                 return maybeMutate( stmt, *this );
     273                maybeMutate_impl( stmt, *this );
     274                return stmt;
    255275        });
    256276}
     
    259279template< typename func_t >
    260280Expression * PassVisitor< pass_type >::handleExpression( Expression * expr, func_t func ) {
     281        if ( ! get_visit_children() ) return expr;
    261282        if( !expr ) return nullptr;
    262283
     
    266287        }
    267288
    268         // should env be cloned (or moved) onto the result of the mutate?
     289        // should env be moved onto the result of the mutate?
    269290        return func( expr );
    270291}
     
    273294Expression * PassVisitor< pass_type >::visitExpression( Expression * expr ) {
    274295        return handleExpression(expr, [this]( Expression * expr ) {
    275                 expr->accept( *this );
     296                maybeAccept_impl( expr, *this );
    276297                return expr;
    277298        });
     
    281302Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
    282303        return handleExpression(expr, [this]( Expression * expr ) {
    283                 return expr->acceptMutator( *this );
     304                maybeMutate_impl( expr, *this );
     305                return expr;
    284306        });
     307}
     308
     309template< typename TreeType, typename VisitorType >
     310inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
     311        if ( ! visitor.get_visit_children() ) return;
     312        auto guard = makeFuncGuard(
     313                [&visitor]() { visitor.indexerScopeEnter(); },
     314                [&visitor]() { visitor.indexerScopeLeave(); }
     315        );
     316        maybeAccept_impl( tree, visitor );
     317}
     318
     319template< typename TreeType, typename MutatorType >
     320inline void indexerScopedMutate( TreeType *& tree, MutatorType & mutator ) {
     321        if ( ! mutator.get_visit_children() ) return;
     322        auto guard = makeFuncGuard(
     323                [&mutator]() { mutator.indexerScopeEnter(); },
     324                [&mutator]() { mutator.indexerScopeLeave(); }
     325        );
     326        maybeMutate_impl( tree, mutator );
    285327}
    286328
     
    319361
    320362        indexerScopedAccept( node->type         , *this );
    321         maybeAccept        ( node->init         , *this );
    322         maybeAccept        ( node->bitfieldWidth, *this );
    323         maybeAccept        ( node->attributes   , *this );
     363        maybeAccept_impl   ( node->init         , *this );
     364        maybeAccept_impl   ( node->bitfieldWidth, *this );
     365        maybeAccept_impl   ( node->attributes   , *this );
    324366
    325367        if ( node->name != "" ) {
     
    335377
    336378        indexerScopedMutate( node->type         , *this );
    337         maybeMutateRef     ( node->init         , *this );
    338         maybeMutateRef     ( node->bitfieldWidth, *this );
    339         maybeMutateRef     ( node->attributes   , *this );
     379        maybeMutate_impl   ( node->init         , *this );
     380        maybeMutate_impl   ( node->bitfieldWidth, *this );
     381        maybeMutate_impl   ( node->attributes   , *this );
    340382
    341383        if ( node->name != "" ) {
     
    358400        {
    359401                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    360                 maybeAccept( node->type, *this );
    361                 maybeAccept( node->statements, *this );
    362                 maybeAccept( node->attributes, *this );
     402                maybeAccept_impl( node->type, *this );
     403                maybeAccept_impl( node->statements, *this );
     404                maybeAccept_impl( node->attributes, *this );
    363405        }
    364406
     
    376418        {
    377419                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    378                 maybeMutateRef( node->type, *this );
    379                 maybeMutateRef( node->statements, *this );
    380                 maybeMutateRef( node->attributes, *this );
     420                maybeMutate_impl( node->type, *this );
     421                maybeMutate_impl( node->statements, *this );
     422                maybeMutate_impl( node->attributes, *this );
    381423        }
    382424
     
    396438        {
    397439                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    398                 maybeAccept( node->parameters, *this );
    399                 maybeAccept( node->members   , *this );
     440                maybeAccept_impl( node->parameters, *this );
     441                maybeAccept_impl( node->members   , *this );
    400442        }
    401443
     
    416458        {
    417459                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    418                 maybeMutateRef( node->parameters, *this );
    419                 maybeMutateRef( node->members   , *this );
     460                maybeMutate_impl( node->parameters, *this );
     461                maybeMutate_impl( node->members   , *this );
    420462        }
    421463
     
    437479        {
    438480                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    439                 maybeAccept( node->parameters, *this );
    440                 maybeAccept( node->members   , *this );
     481                maybeAccept_impl( node->parameters, *this );
     482                maybeAccept_impl( node->members   , *this );
    441483        }
    442484
     
    455497        {
    456498                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    457                 maybeMutateRef( node->parameters, *this );
    458                 maybeMutateRef( node->members   , *this );
     499                maybeMutate_impl( node->parameters, *this );
     500                maybeMutate_impl( node->members   , *this );
    459501        }
    460502
     
    473515
    474516        // unlike structs, traits, and unions, enums inject their members into the global scope
    475         maybeAccept( node->parameters, *this );
    476         maybeAccept( node->members   , *this );
     517        maybeAccept_impl( node->parameters, *this );
     518        maybeAccept_impl( node->members   , *this );
    477519
    478520        VISIT_END( node );
     
    486528
    487529        // unlike structs, traits, and unions, enums inject their members into the global scope
    488         maybeMutateRef( node->parameters, *this );
    489         maybeMutateRef( node->members   , *this );
     530        maybeMutate_impl( node->parameters, *this );
     531        maybeMutate_impl( node->members   , *this );
    490532
    491533        MUTATE_END( Declaration, node );
     
    500542        {
    501543                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    502                 maybeAccept( node->parameters, *this );
    503                 maybeAccept( node->members   , *this );
     544                maybeAccept_impl( node->parameters, *this );
     545                maybeAccept_impl( node->members   , *this );
    504546        }
    505547
     
    515557        {
    516558                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    517                 maybeMutateRef( node->parameters, *this );
    518                 maybeMutateRef( node->members   , *this );
     559                maybeMutate_impl( node->parameters, *this );
     560                maybeMutate_impl( node->members   , *this );
    519561        }
    520562
     
    532574        {
    533575                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    534                 maybeAccept( node->parameters, *this );
    535                 maybeAccept( node->base      , *this );
     576                maybeAccept_impl( node->parameters, *this );
     577                maybeAccept_impl( node->base      , *this );
    536578        }
    537579
     
    541583        indexerAddType( node );
    542584
    543         maybeAccept( node->assertions, *this );
     585        maybeAccept_impl( node->assertions, *this );
    544586
    545587        indexerScopedAccept( node->init, *this );
     
    554596        {
    555597                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    556                 maybeMutateRef( node->parameters, *this );
    557                 maybeMutateRef( node->base      , *this );
     598                maybeMutate_impl( node->parameters, *this );
     599                maybeMutate_impl( node->base      , *this );
    558600        }
    559601
     
    563605        indexerAddType( node );
    564606
    565         maybeMutateRef( node->assertions, *this );
     607        maybeMutate_impl( node->assertions, *this );
    566608
    567609        indexerScopedMutate( node->init, *this );
     
    578620        {
    579621                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    580                 maybeAccept( node->parameters, *this );
    581                 maybeAccept( node->base      , *this );
     622                maybeAccept_impl( node->parameters, *this );
     623                maybeAccept_impl( node->base      , *this );
    582624        }
    583625
    584626        indexerAddType( node );
    585627
    586         maybeAccept( node->assertions, *this );
     628        maybeAccept_impl( node->assertions, *this );
    587629
    588630        VISIT_END( node );
     
    595637        {
    596638                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    597                 maybeMutateRef     ( node->parameters, *this );
    598                 maybeMutateRef( node->base      , *this );
     639                maybeMutate_impl( node->parameters, *this );
     640                maybeMutate_impl( node->base      , *this );
    599641        }
    600642
    601643        indexerAddType( node );
    602644
    603         maybeMutateRef( node->assertions, *this );
     645        maybeMutate_impl( node->assertions, *this );
    604646
    605647        MUTATE_END( Declaration, node );
     
    612654        VISIT_START( node );
    613655
    614         maybeAccept( node->stmt, *this );
     656        maybeAccept_impl( node->stmt, *this );
    615657
    616658        VISIT_END( node );
     
    621663        MUTATE_START( node );
    622664
    623         maybeMutateRef( node->stmt, *this );
     665        maybeMutate_impl( node->stmt, *this );
    624666
    625667        MUTATE_END( AsmDecl, node );
     
    690732                // if statements introduce a level of scope (for the initialization)
    691733                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    692                 acceptAll( node->get_initialization(), *this );
    693                 visitExpression( node->condition );
     734                maybeAccept_impl( node->get_initialization(), *this );
     735                visitExpression ( node->condition );
    694736                node->thenPart = visitStatement( node->thenPart );
    695737                node->elsePart = visitStatement( node->elsePart );
     
    704746                // if statements introduce a level of scope (for the initialization)
    705747                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    706                 maybeMutateRef( node->get_initialization(), *this );
     748                maybeMutate_impl( node->get_initialization(), *this );
    707749                node->condition = mutateExpression( node->condition );
    708750                node->thenPart  = mutateStatement ( node->thenPart  );
     
    742784                // for statements introduce a level of scope (for the initialization)
    743785                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    744                 maybeAccept( node->initialization, *this );
     786                maybeAccept_impl( node->initialization, *this );
    745787                visitExpression( node->condition );
    746788                visitExpression( node->increment );
     
    756798                // for statements introduce a level of scope (for the initialization)
    757799                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    758                 maybeMutateRef( node->initialization, *this );
     800                maybeMutate_impl( node->initialization, *this );
    759801                node->condition = mutateExpression( node->condition );
    760802                node->increment = mutateExpression( node->increment );
     
    859901        VISIT_START( node );
    860902
    861         maybeAccept( node->block       , *this );
    862         maybeAccept( node->handlers    , *this );
    863         maybeAccept( node->finallyBlock, *this );
     903        maybeAccept_impl( node->block       , *this );
     904        maybeAccept_impl( node->handlers    , *this );
     905        maybeAccept_impl( node->finallyBlock, *this );
    864906
    865907        VISIT_END( node );
     
    870912        MUTATE_START( node );
    871913
    872         maybeMutateRef( node->block       , *this );
    873         maybeMutateRef( node->handlers    , *this );
    874         maybeMutateRef( node->finallyBlock, *this );
     914        maybeMutate_impl( node->block       , *this );
     915        maybeMutate_impl( node->handlers    , *this );
     916        maybeMutate_impl( node->finallyBlock, *this );
    875917
    876918        MUTATE_END( Statement, node );
     
    885927                // catch statements introduce a level of scope (for the caught exception)
    886928                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    887                 maybeAccept( node->decl, *this );
     929                maybeAccept_impl( node->decl, *this );
    888930                node->cond = visitExpression( node->cond );
    889931                node->body = visitStatement ( node->body );
     
    898940                // catch statements introduce a level of scope (for the caught exception)
    899941                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    900                 maybeMutateRef( node->decl, *this );
     942                maybeMutate_impl( node->decl, *this );
    901943                node->cond = mutateExpression( node->cond );
    902944                node->body = mutateStatement ( node->body );
     
    9721014
    9731015        indexerScopedAccept( node->result  , *this );
    974         maybeAccept        ( node->function, *this );
    975         maybeAccept        ( node->args    , *this );
     1016        maybeAccept_impl        ( node->function, *this );
     1017        maybeAccept_impl        ( node->args    , *this );
    9761018
    9771019        VISIT_END( node );
     
    9841026        indexerScopedMutate( node->env     , *this );
    9851027        indexerScopedMutate( node->result  , *this );
    986         maybeMutateRef     ( node->function, *this );
    987         maybeMutateRef     ( node->args    , *this );
     1028        maybeMutate_impl   ( node->function, *this );
     1029        maybeMutate_impl   ( node->args    , *this );
    9881030
    9891031        MUTATE_END( Expression, node );
     
    9961038        VISIT_START( node );
    9971039
    998         // maybeAccept( node->get_env(), *this );
     1040        // maybeAccept_impl( node->get_env(), *this );
    9991041        indexerScopedAccept( node->result, *this );
    10001042
     
    10481090
    10491091        indexerScopedAccept( node->result, *this );
    1050         maybeAccept        ( node->arg   , *this );
     1092        maybeAccept_impl        ( node->arg   , *this );
    10511093
    10521094        VISIT_END( node );
     
    10591101        indexerScopedMutate( node->env   , *this );
    10601102        indexerScopedMutate( node->result, *this );
    1061         maybeMutateRef     ( node->arg   , *this );
     1103        maybeMutate_impl   ( node->arg   , *this );
    10621104
    10631105        MUTATE_END( Expression, node );
     
    10711113
    10721114        indexerScopedAccept( node->result, *this );
    1073         maybeAccept( node->arg, *this );
     1115        maybeAccept_impl( node->arg, *this );
    10741116
    10751117        VISIT_END( node );
     
    10821124        indexerScopedMutate( node->env   , *this );
    10831125        indexerScopedMutate( node->result, *this );
    1084         maybeMutateRef     ( node->arg   , *this );
     1126        maybeMutate_impl   ( node->arg   , *this );
    10851127
    10861128        MUTATE_END( Expression, node );
     
    10941136
    10951137        indexerScopedAccept( node->result, *this );
    1096         maybeAccept        ( node->arg   , *this );
     1138        maybeAccept_impl   ( node->arg   , *this );
    10971139
    10981140        VISIT_END( node );
     
    11051147        indexerScopedMutate( node->env   , *this );
    11061148        indexerScopedMutate( node->result, *this );
    1107         maybeMutateRef     ( node->arg   , *this );
     1149        maybeMutate_impl   ( node->arg   , *this );
    11081150
    11091151        MUTATE_END( Expression, node );
     
    11381180
    11391181        indexerScopedAccept( node->result   , *this );
    1140         maybeAccept        ( node->aggregate, *this );
    1141         maybeAccept        ( node->member   , *this );
     1182        maybeAccept_impl   ( node->aggregate, *this );
     1183        maybeAccept_impl   ( node->member   , *this );
    11421184
    11431185        VISIT_END( node );
     
    11501192        indexerScopedMutate( node->env      , *this );
    11511193        indexerScopedMutate( node->result   , *this );
    1152         maybeMutateRef     ( node->aggregate, *this );
    1153         maybeMutateRef     ( node->member   , *this );
     1194        maybeMutate_impl   ( node->aggregate, *this );
     1195        maybeMutate_impl   ( node->member   , *this );
    11541196
    11551197        MUTATE_END( Expression, node );
     
    11631205
    11641206        indexerScopedAccept( node->result   , *this );
    1165         maybeAccept        ( node->aggregate, *this );
     1207        maybeAccept_impl   ( node->aggregate, *this );
    11661208
    11671209        VISIT_END( node );
     
    11741216        indexerScopedMutate( node->env      , *this );
    11751217        indexerScopedMutate( node->result   , *this );
    1176         maybeMutateRef     ( node->aggregate, *this );
     1218        maybeMutate_impl   ( node->aggregate, *this );
    11771219
    11781220        MUTATE_END( Expression, node );
     
    12071249
    12081250        indexerScopedAccept( node->result   , *this );
    1209         maybeAccept        ( &node->constant, *this );
     1251        maybeAccept_impl   ( &node->constant, *this );
    12101252
    12111253        VISIT_END( node );
     
    12181260        indexerScopedMutate( node->env   , *this );
    12191261        indexerScopedMutate( node->result, *this );
    1220         node->constant = *maybeMutate( &node->constant, *this );
     1262        Constant * ptr = &node->constant;
     1263        maybeMutate_impl( ptr, *this );
     1264        node->constant = *ptr;
    12211265
    12221266        MUTATE_END( Expression, node );
     
    12311275        indexerScopedAccept( node->result, *this );
    12321276        if ( node->get_isType() ) {
    1233                 maybeAccept( node->type, *this );
     1277                maybeAccept_impl( node->type, *this );
    12341278        } else {
    1235                 maybeAccept( node->expr, *this );
     1279                maybeAccept_impl( node->expr, *this );
    12361280        }
    12371281
     
    12461290        indexerScopedMutate( node->result, *this );
    12471291        if ( node->get_isType() ) {
    1248                 maybeMutateRef( node->type, *this );
     1292                maybeMutate_impl( node->type, *this );
    12491293        } else {
    1250                 maybeMutateRef( node->expr, *this );
     1294                maybeMutate_impl( node->expr, *this );
    12511295        }
    12521296
     
    12621306        indexerScopedAccept( node->result, *this );
    12631307        if ( node->get_isType() ) {
    1264                 maybeAccept( node->type, *this );
     1308                maybeAccept_impl( node->type, *this );
    12651309        } else {
    1266                 maybeAccept( node->expr, *this );
     1310                maybeAccept_impl( node->expr, *this );
    12671311        }
    12681312
     
    12771321        indexerScopedMutate( node->result, *this );
    12781322        if ( node->get_isType() ) {
    1279                 maybeMutateRef( node->type, *this );
     1323                maybeMutate_impl( node->type, *this );
    12801324        } else {
    1281                 maybeMutateRef( node->expr, *this );
     1325                maybeMutate_impl( node->expr, *this );
    12821326        }
    12831327
     
    12921336
    12931337        indexerScopedAccept( node->result, *this );
    1294         maybeAccept        ( node->type  , *this );
     1338        maybeAccept_impl   ( node->type  , *this );
    12951339
    12961340        VISIT_END( node );
     
    13031347        indexerScopedMutate( node->env   , *this );
    13041348        indexerScopedMutate( node->result, *this );
    1305         maybeMutateRef     ( node->type  , *this );
     1349        maybeMutate_impl   ( node->type  , *this );
    13061350
    13071351        MUTATE_END( Expression, node );
     
    13151359
    13161360        indexerScopedAccept( node->result, *this );
    1317         maybeAccept        ( node->type  , *this );
    1318         maybeAccept        ( node->member, *this );
     1361        maybeAccept_impl   ( node->type  , *this );
     1362        maybeAccept_impl   ( node->member, *this );
    13191363
    13201364        VISIT_END( node );
     
    13271371        indexerScopedMutate( node->env   , *this );
    13281372        indexerScopedMutate( node->result, *this );
    1329         maybeMutateRef     ( node->type  , *this );
    1330         maybeMutateRef     ( node->member, *this );
     1373        maybeMutate_impl   ( node->type  , *this );
     1374        maybeMutate_impl   ( node->member, *this );
    13311375
    13321376        MUTATE_END( Expression, node );
     
    13401384
    13411385        indexerScopedAccept( node->result, *this );
    1342         maybeAccept        ( node->type  , *this );
     1386        maybeAccept_impl   ( node->type  , *this );
    13431387
    13441388        VISIT_END( node );
     
    13511395        indexerScopedMutate( node->env   , *this );
    13521396        indexerScopedMutate( node->result, *this );
    1353         maybeMutateRef     ( node->type  , *this );
     1397        maybeMutate_impl   ( node->type  , *this );
    13541398
    13551399        MUTATE_END( Expression, node );
     
    13641408        indexerScopedAccept( node->result, *this );
    13651409        if ( node->get_isType() ) {
    1366                 maybeAccept( node->type, *this );
     1410                maybeAccept_impl( node->type, *this );
    13671411        } else {
    1368                 maybeAccept( node->expr, *this );
     1412                maybeAccept_impl( node->expr, *this );
    13691413        }
    13701414
     
    13791423        indexerScopedMutate( node->result, *this );
    13801424        if ( node->get_isType() ) {
    1381                 maybeMutateRef( node->type, *this );
     1425                maybeMutate_impl( node->type, *this );
    13821426        } else {
    1383                 maybeMutateRef( node->expr, *this );
     1427                maybeMutate_impl( node->expr, *this );
    13841428        }
    13851429
     
    13941438
    13951439        indexerScopedAccept( node->result, *this );
    1396         maybeAccept        ( node->arg1  , *this );
    1397         maybeAccept        ( node->arg2  , *this );
     1440        maybeAccept_impl   ( node->arg1  , *this );
     1441        maybeAccept_impl   ( node->arg2  , *this );
    13981442
    13991443        VISIT_END( node );
     
    14061450        indexerScopedMutate( node->env   , *this );
    14071451        indexerScopedMutate( node->result, *this );
    1408         maybeMutateRef     ( node->arg1  , *this );
    1409         maybeMutateRef     ( node->arg2  , *this );
     1452        maybeMutate_impl   ( node->arg1  , *this );
     1453        maybeMutate_impl   ( node->arg2  , *this );
    14101454
    14111455        MUTATE_END( Expression, node );
     
    14191463
    14201464        indexerScopedAccept( node->result, *this );
    1421         maybeAccept        ( node->arg1  , *this );
    1422         maybeAccept        ( node->arg2  , *this );
    1423         maybeAccept        ( node->arg3  , *this );
     1465        maybeAccept_impl        ( node->arg1  , *this );
     1466        maybeAccept_impl        ( node->arg2  , *this );
     1467        maybeAccept_impl        ( node->arg3  , *this );
    14241468
    14251469        VISIT_END( node );
     
    14321476        indexerScopedMutate( node->env   , *this );
    14331477        indexerScopedMutate( node->result, *this );
    1434         maybeMutateRef     ( node->arg1  , *this );
    1435         maybeMutateRef     ( node->arg2  , *this );
    1436         maybeMutateRef     ( node->arg3  , *this );
     1478        maybeMutate_impl   ( node->arg1  , *this );
     1479        maybeMutate_impl   ( node->arg2  , *this );
     1480        maybeMutate_impl   ( node->arg3  , *this );
    14371481
    14381482        MUTATE_END( Expression, node );
     
    14461490
    14471491        indexerScopedAccept( node->result, *this );
    1448         maybeAccept        ( node->arg1  , *this );
    1449         maybeAccept        ( node->arg2  , *this );
     1492        maybeAccept_impl   ( node->arg1  , *this );
     1493        maybeAccept_impl   ( node->arg2  , *this );
    14501494
    14511495        VISIT_END( node );
     
    14581502        indexerScopedMutate( node->env   , *this );
    14591503        indexerScopedMutate( node->result, *this );
    1460         maybeMutateRef     ( node->arg1  , *this );
    1461         maybeMutateRef     ( node->arg2  , *this );
     1504        maybeMutate_impl   ( node->arg1  , *this );
     1505        maybeMutate_impl   ( node->arg2  , *this );
    14621506
    14631507        MUTATE_END( Expression, node );
     
    14711515
    14721516        indexerScopedAccept( node->result, *this );
    1473         maybeAccept        ( node->type, *this );
     1517        maybeAccept_impl   ( node->type, *this );
    14741518
    14751519        VISIT_END( node );
     
    14821526        indexerScopedMutate( node->env   , *this );
    14831527        indexerScopedMutate( node->result, *this );
    1484         maybeMutateRef     ( node->type  , *this );
     1528        maybeMutate_impl   ( node->type  , *this );
    14851529
    14861530        MUTATE_END( Expression, node );
     
    14941538
    14951539        indexerScopedAccept( node->result    , *this );
    1496         maybeAccept        ( node->inout     , *this );
    1497         maybeAccept        ( node->constraint, *this );
    1498         maybeAccept        ( node->operand   , *this );
     1540        maybeAccept_impl   ( node->inout     , *this );
     1541        maybeAccept_impl   ( node->constraint, *this );
     1542        maybeAccept_impl   ( node->operand   , *this );
    14991543
    15001544        VISIT_END( node );
     
    15071551        indexerScopedMutate( node->env       , *this );
    15081552        indexerScopedMutate( node->result    , *this );
    1509         maybeMutateRef     ( node->inout     , *this );
    1510         maybeMutateRef     ( node->constraint, *this );
    1511         maybeMutateRef     ( node->operand   , *this );
     1553        maybeMutate_impl   ( node->inout     , *this );
     1554        maybeMutate_impl   ( node->constraint, *this );
     1555        maybeMutate_impl   ( node->operand   , *this );
    15121556
    15131557        MUTATE_END( Expression, node );
     
    15211565
    15221566        indexerScopedAccept( node->result     , *this );
    1523         maybeAccept        ( node->callExpr   , *this );
    1524         maybeAccept        ( node->tempDecls  , *this );
    1525         maybeAccept        ( node->returnDecls, *this );
    1526         maybeAccept        ( node->dtors      , *this );
     1567        maybeAccept_impl   ( node->callExpr   , *this );
     1568        maybeAccept_impl   ( node->tempDecls  , *this );
     1569        maybeAccept_impl   ( node->returnDecls, *this );
     1570        maybeAccept_impl   ( node->dtors      , *this );
    15271571
    15281572        VISIT_END( node );
     
    15351579        indexerScopedMutate( node->env        , *this );
    15361580        indexerScopedMutate( node->result     , *this );
    1537         maybeMutateRef     ( node->callExpr   , *this );
    1538         maybeMutateRef     ( node->tempDecls  , *this );
    1539         maybeMutateRef     ( node->returnDecls, *this );
    1540         maybeMutateRef     ( node->dtors      , *this );
     1581        maybeMutate_impl   ( node->callExpr   , *this );
     1582        maybeMutate_impl   ( node->tempDecls  , *this );
     1583        maybeMutate_impl   ( node->returnDecls, *this );
     1584        maybeMutate_impl   ( node->dtors      , *this );
    15411585
    15421586        MUTATE_END( Expression, node );
     
    15501594
    15511595        indexerScopedAccept( node->result  , *this );
    1552         maybeAccept        ( node->callExpr, *this );
     1596        maybeAccept_impl   ( node->callExpr, *this );
    15531597
    15541598        VISIT_END( node );
     
    15611605        indexerScopedMutate( node->env     , *this );
    15621606        indexerScopedMutate( node->result  , *this );
    1563         maybeMutateRef     ( node->callExpr, *this );
     1607        maybeMutate_impl   ( node->callExpr, *this );
    15641608
    15651609        MUTATE_END( Expression, node );
     
    15731617
    15741618        indexerScopedAccept( node->result     , *this );
    1575         maybeAccept        ( node->initializer, *this );
     1619        maybeAccept_impl   ( node->initializer, *this );
    15761620
    15771621        VISIT_END( node );
     
    15841628        indexerScopedMutate( node->env        , *this );
    15851629        indexerScopedMutate( node->result     , *this );
    1586         maybeMutateRef     ( node->initializer, *this );
     1630        maybeMutate_impl     ( node->initializer, *this );
    15871631
    15881632        MUTATE_END( Expression, node );
     
    15961640
    15971641        indexerScopedAccept( node->result, *this );
    1598         maybeAccept        ( node->low   , *this );
    1599         maybeAccept        ( node->high  , *this );
     1642        maybeAccept_impl   ( node->low   , *this );
     1643        maybeAccept_impl   ( node->high  , *this );
    16001644
    16011645        VISIT_END( node );
     
    16081652        indexerScopedMutate( node->env   , *this );
    16091653        indexerScopedMutate( node->result, *this );
    1610         maybeMutateRef     ( node->low   , *this );
    1611         maybeMutateRef     ( node->high  , *this );
     1654        maybeMutate_impl   ( node->low   , *this );
     1655        maybeMutate_impl   ( node->high  , *this );
    16121656
    16131657        MUTATE_END( Expression, node );
     
    16211665
    16221666        indexerScopedAccept( node->result, *this );
    1623         maybeAccept        ( node->exprs , *this );
     1667        maybeAccept_impl   ( node->exprs , *this );
    16241668
    16251669        VISIT_END( node );
     
    16321676        indexerScopedMutate( node->env   , *this );
    16331677        indexerScopedMutate( node->result, *this );
    1634         maybeMutateRef     ( node->exprs , *this );
     1678        maybeMutate_impl   ( node->exprs , *this );
    16351679
    16361680        MUTATE_END( Expression, node );
     
    16441688
    16451689        indexerScopedAccept( node->result, *this );
    1646         maybeAccept          ( node->exprs , *this );
     1690        maybeAccept_impl   ( node->exprs , *this );
    16471691
    16481692        VISIT_END( node );
     
    16551699        indexerScopedMutate( node->env   , *this );
    16561700        indexerScopedMutate( node->result, *this );
    1657         maybeMutateRef     ( node->exprs , *this );
     1701        maybeMutate_impl   ( node->exprs , *this );
    16581702
    16591703        MUTATE_END( Expression, node );
     
    16671711
    16681712        indexerScopedAccept( node->result, *this );
    1669         maybeAccept        ( node->tuple , *this );
     1713        maybeAccept_impl   ( node->tuple , *this );
    16701714
    16711715        VISIT_END( node );
     
    16781722        indexerScopedMutate( node->env   , *this );
    16791723        indexerScopedMutate( node->result, *this );
    1680         maybeMutateRef     ( node->tuple , *this );
     1724        maybeMutate_impl   ( node->tuple , *this );
    16811725
    16821726        MUTATE_END( Expression, node );
     
    16901734
    16911735        indexerScopedAccept( node->result  , *this );
    1692         maybeAccept        ( node->stmtExpr, *this );
     1736        maybeAccept_impl   ( node->stmtExpr, *this );
    16931737
    16941738        VISIT_END( node );
     
    17011745        indexerScopedMutate( node->env     , *this );
    17021746        indexerScopedMutate( node->result  , *this );
    1703         maybeMutateRef     ( node->stmtExpr, *this );
     1747        maybeMutate_impl   ( node->stmtExpr, *this );
    17041748
    17051749        MUTATE_END( Expression, node );
     
    17181762
    17191763        indexerScopedAccept( node->result     , *this );
    1720         maybeAccept        ( node->statements , *this );
    1721         maybeAccept        ( node->returnDecls, *this );
    1722         maybeAccept        ( node->dtors      , *this );
     1764        maybeAccept_impl   ( node->statements , *this );
     1765        maybeAccept_impl   ( node->returnDecls, *this );
     1766        maybeAccept_impl   ( node->dtors      , *this );
    17231767
    17241768        VISIT_END( node );
     
    17351779
    17361780        indexerScopedMutate( node->result     , *this );
    1737         maybeMutateRef     ( node->statements , *this );
    1738         maybeMutateRef     ( node->returnDecls, *this );
    1739         maybeMutateRef     ( node->dtors      , *this );
     1781        maybeMutate_impl   ( node->statements , *this );
     1782        maybeMutate_impl   ( node->returnDecls, *this );
     1783        maybeMutate_impl   ( node->dtors      , *this );
    17401784
    17411785        MUTATE_END( Expression, node );
     
    17491793
    17501794        indexerScopedAccept( node->result, *this );
    1751         maybeAccept        ( node->expr  , *this );
     1795        maybeAccept_impl   ( node->expr  , *this );
    17521796
    17531797        VISIT_END( node );
     
    17601804        indexerScopedMutate( node->env   , *this );
    17611805        indexerScopedMutate( node->result, *this );
    1762         maybeMutateRef     ( node->expr  , *this );
     1806        maybeMutate_impl   ( node->expr  , *this );
    17631807
    17641808        MUTATE_END( Expression, node );
     
    18051849        {
    18061850                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1807                 maybeAccept( node->forall    , *this );
    1808                 maybeAccept( node->parameters, *this );
     1851                maybeAccept_impl( node->forall    , *this );
     1852                maybeAccept_impl( node->parameters, *this );
    18091853        }
    18101854
     
    18201864        {
    18211865                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1822                 maybeMutateRef( node->forall    , *this );
    1823                 maybeMutateRef( node->parameters, *this );
     1866                maybeMutate_impl( node->forall    , *this );
     1867                maybeMutate_impl( node->parameters, *this );
    18241868        }
    18251869
     
    18371881        {
    18381882                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1839                 maybeAccept( node->forall    , *this );
    1840                 maybeAccept( node->parameters, *this );
     1883                maybeAccept_impl( node->forall    , *this );
     1884                maybeAccept_impl( node->parameters, *this );
    18411885        }
    18421886
     
    18521896        {
    18531897                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1854                 maybeMutateRef( node->forall    , *this );
    1855                 maybeMutateRef( node->parameters, *this );
     1898                maybeMutate_impl( node->forall    , *this );
     1899                maybeMutate_impl( node->parameters, *this );
    18561900        }
    18571901
     
    18771921        VISIT_START( node );
    18781922
    1879         maybeAccept( node->forall    , *this );
    1880         maybeAccept( node->parameters, *this );
     1923        maybeAccept_impl( node->forall    , *this );
     1924        maybeAccept_impl( node->parameters, *this );
    18811925
    18821926        VISIT_END( node );
     
    18871931        MUTATE_START( node );
    18881932
    1889         maybeMutateRef( node->forall    , *this );
    1890         maybeMutateRef( node->parameters, *this );
     1933        maybeMutate_impl( node->forall    , *this );
     1934        maybeMutate_impl( node->parameters, *this );
    18911935
    18921936        MUTATE_END( Type, node );
     
    19341978        VISIT_START( node );
    19351979
    1936         maybeAccept( node->get_designators(), *this );
     1980        maybeAccept_impl( node->get_designators(), *this );
    19371981
    19381982        VISIT_END( node );
     
    19431987        MUTATE_START( node );
    19441988
    1945         maybeMutateRef( node->get_designators(), *this );
     1989        maybeMutate_impl( node->get_designators(), *this );
    19461990
    19471991        MUTATE_END( Designation, node );
     
    20832127        MUTATE_BODY( Attribute, node );
    20842128}
     2129
     2130template< typename pass_type >
     2131TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
     2132        MUTATE_START( node );
     2133
     2134        for ( auto & p : node->typeEnv ) {
     2135                indexerScopedMutate( p.second, *this );
     2136        }
     2137        for ( auto & p : node->varEnv ) {
     2138                indexerScopedMutate( p.second, *this );
     2139        }
     2140
     2141        MUTATE_END( TypeSubstitution, node );
     2142}
  • src/Common/PassVisitor.proto.h

    rb96ec83 r6840e7c  
    4646        ~bool_ref() = default;
    4747
    48         operator bool() { return *m_ref; }
     48        operator bool() { return m_ref ? *m_ref : true; }
    4949        bool operator=( bool val ) { return *m_ref = val; }
    5050
    5151private:
    5252
    53         template<typename pass>
    54         friend class PassVisitor;
    55 
    56         void set( bool & val ) { m_ref = &val; };
    57 
    58         bool * m_ref;
     53        friend class ChildrenGuard;
     54
     55        bool * set( bool & val ) {
     56                bool * prev = m_ref;
     57                m_ref = &val;
     58                return prev;
     59        }
     60
     61        bool * m_ref = nullptr;
    5962};
    6063
    61 template< typename TreeType, typename VisitorType >
    62 inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
    63         auto guard = makeFuncGuard(
    64                 [&visitor]() { visitor.indexerScopeEnter(); },
    65                 [&visitor]() { visitor.indexerScopeLeave(); }
    66         );
    67         maybeAccept( tree, visitor );
    68 }
    69 
    70 template< typename TreeType, typename MutatorType >
    71 inline void indexerScopedMutate( TreeType *& tree, MutatorType & mutator ) {
    72         auto guard = makeFuncGuard(
    73                 [&mutator]() { mutator.indexerScopeEnter(); },
    74                 [&mutator]() { mutator.indexerScopeLeave(); }
    75         );
    76         tree = maybeMutate( tree, mutator );
    77 }
    78 
    79 template< typename TreeType, typename MutatorType >
    80 inline void maybeMutateRef( TreeType *& tree, MutatorType & mutator ) {
    81         tree = maybeMutate( tree, mutator );
    82 }
     64class ChildrenGuard {
     65public:
     66
     67        ChildrenGuard( bool_ref * ref )
     68                : m_val ( true )
     69                , m_prev( ref ? ref->set( m_val ) : nullptr )
     70                , m_ref ( ref )
     71        {}
     72
     73        ~ChildrenGuard() {
     74                if( m_ref ) {
     75                        m_ref->set( *m_prev );
     76                }
     77        }
     78
     79        operator bool() { return m_val; }
     80
     81private:
     82        bool       m_val;
     83        bool     * m_prev;
     84        bool_ref * m_ref;
     85};
    8386
    8487//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • src/Common/utility.h

    rb96ec83 r6840e7c  
    2828#include <cassert>
    2929
     30#include "Common/Indenter.h"
     31
    3032template< typename T >
    3133static inline T * maybeClone( const T *orig ) {
     
    7577
    7678template< typename Container >
    77 void printAll( const Container &container, std::ostream &os, int indent = 0 ) {
     79void printAll( const Container &container, std::ostream &os, Indenter indent = {} ) {
    7880        for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
    7981                if ( *i ) {
    80                         os << std::string( indent,  ' ' );
    81                         (*i)->print( os, indent + 2 );
     82                        os << indent;
     83                        (*i)->print( os, indent );
    8284                        // need an endl after each element because it's not easy to know when each individual item should end
    8385                        os << std::endl;
     
    351353template< typename T1, typename T2 >
    352354struct group_iterate_t {
     355private:
     356        std::tuple<T1, T2> args;
     357public:
    353358        group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) {
    354359                assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%zd, %zd>.", v1.size(), v2.size());
    355360        };
    356361
     362        typedef std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin())> value_type;
     363        typedef decltype(std::get<0>(args).begin()) T1Iter;
     364        typedef decltype(std::get<1>(args).begin()) T2Iter;
     365
    357366        struct iterator {
    358                 typedef typename std::remove_reference<T1>::type T1val;
    359                 typedef typename std::remove_reference<T2>::type T2val;
    360                 typedef std::tuple<typename T1val::value_type &, typename T2val::value_type &> value_type;
    361                 typedef typename T1val::iterator T1Iter;
    362                 typedef typename T2val::iterator T2Iter;
    363367                typedef std::tuple<T1Iter, T2Iter> IterTuple;
    364368                IterTuple it;
     
    370374                value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it) ); }
    371375        };
     376
    372377        iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); }
    373378        iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); }
    374 
    375 private:
    376         std::tuple<T1, T2> args;
    377379};
    378380
  • src/Concurrency/Keywords.cc

    rb96ec83 r6840e7c  
    196196                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
    197197                void validate( DeclarationWithType * );
     198                void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    198199                void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    199200
     
    206207                StructDecl* monitor_decl = nullptr;
    207208                StructDecl* guard_decl = nullptr;
     209                StructDecl* dtor_guard_decl = nullptr;
    208210
    209211                static std::unique_ptr< Type > generic_func;
     
    229231
    230232                void postvisit( FunctionDecl * decl );
     233                void previsit ( StructDecl   * decl );
    231234
    232235                void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
     
    236239                        acceptAll( translationUnit, impl );
    237240                }
     241
     242          private :
     243                bool thread_ctor_seen = false;
     244                StructDecl * thread_decl = nullptr;
    238245        };
    239246
     
    403410                if( mutexArgs.empty() ) return;
    404411
     412                if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
     413
     414                bool isDtor = CodeGen::isDestructor( decl->name );
     415
     416                if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
     417
    405418                for(auto arg : mutexArgs) {
    406419                        validate( arg );
     
    412425                if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
    413426                if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
    414 
    415                 addStatments( decl, body, mutexArgs );
     427                if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
     428
     429                if( isDtor ) {
     430                        addDtorStatments( decl, body, mutexArgs );
     431                }
     432                else {
     433                        addStatments( decl, body, mutexArgs );
     434                }
    416435        }
    417436
     
    425444                        assert( !guard_decl );
    426445                        guard_decl = decl;
     446                }
     447                else if( decl->name == "monitor_dtor_guard_t" ) {
     448                        assert( !dtor_guard_decl );
     449                        dtor_guard_decl = decl;
    427450                }
    428451        }
     
    457480                //Make sure that typed isn't mutex
    458481                if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
     482        }
     483
     484        void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     485                Type * arg_type = args.front()->get_type()->clone();
     486                arg_type->set_mutex( false );
     487
     488                ObjectDecl * monitors = new ObjectDecl(
     489                        "__monitor",
     490                        noStorage,
     491                        LinkageSpec::Cforall,
     492                        nullptr,
     493                        new PointerType(
     494                                noQualifiers,
     495                                new StructInstType(
     496                                        noQualifiers,
     497                                        monitor_decl
     498                                )
     499                        ),
     500                        new SingleInit( new UntypedExpr(
     501                                new NameExpr( "get_monitor" ),
     502                                {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     503                        ))
     504                );
     505
     506                assert(generic_func);
     507
     508                //in reverse order :
     509                // monitor_guard_t __guard = { __monitors, #, func };
     510                body->push_front(
     511                        new DeclStmt( noLabels, new ObjectDecl(
     512                                "__guard",
     513                                noStorage,
     514                                LinkageSpec::Cforall,
     515                                nullptr,
     516                                new StructInstType(
     517                                        noQualifiers,
     518                                        dtor_guard_decl
     519                                ),
     520                                new ListInit(
     521                                        {
     522                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
     523                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     524                                        },
     525                                        noDesignators,
     526                                        true
     527                                )
     528                        ))
     529                );
     530
     531                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     532                body->push_front( new DeclStmt( noLabels, monitors) );
    459533        }
    460534
     
    523597        // General entry routine
    524598        //=============================================================================================
     599        void ThreadStarter::previsit( StructDecl * decl ) {
     600                if( decl->name == "thread_desc" && decl->body ) {
     601                        assert( !thread_decl );
     602                        thread_decl = decl;
     603                }
     604        }
     605
    525606        void ThreadStarter::postvisit(FunctionDecl * decl) {
    526607                if( ! CodeGen::isConstructor(decl->name) ) return;
     608
     609                Type * typeof_this = InitTweak::getTypeofThis(decl->type);
     610                StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
     611                if( ctored_type && ctored_type->baseStruct == thread_decl ) {
     612                        thread_ctor_seen = true;
     613                }
    527614
    528615                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
    529616                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
    530617                if( type && type->get_baseStruct()->is_thread() ) {
     618                        if( !thread_decl || !thread_ctor_seen ) {
     619                                throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
     620                        }
     621
    531622                        addStartStatement( decl, param );
    532623                }
  • src/Concurrency/Waitfor.cc

    rb96ec83 r6840e7c  
    190190
    191191                Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
    192                         std::unique_ptr< Expression > expr( makeOpAssign(
     192                        Expression * expr = makeOpAssign(
    193193                                makeOpMember(
    194194                                        makeOpIndex(
     
    199199                                ),
    200200                                value
    201                         ) );
    202 
    203                         return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
     201                        );
     202
     203                        ResolvExpr::findVoidExpression( expr, indexer );
     204
     205                        return new ExprStmt( noLabels, expr );
    204206                }
    205207
     
    313315                stmt->push_back( new DeclStmt( noLabels, acceptables) );
    314316
    315                 UntypedExpr * set = new UntypedExpr(
     317                Expression * set = new UntypedExpr(
    316318                        new NameExpr( "__builtin_memset" ),
    317319                        {
     
    322324                );
    323325
    324                 Expression * resolved_set = ResolvExpr::findVoidExpression( set, indexer );
    325                 delete set;
    326 
    327                 stmt->push_back( new ExprStmt( noLabels, resolved_set ) );
     326                ResolvExpr::findVoidExpression( set, indexer );
     327
     328                stmt->push_back( new ExprStmt( noLabels, set ) );
    328329
    329330                return acceptables;
     
    346347
    347348        Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
    348                 Expression * untyped = new UntypedExpr(
     349                Expression * expr = new UntypedExpr(
    349350                        new NameExpr( "?=?" ),
    350351                        {
     
    354355                );
    355356
    356                 Expression * expr = ResolvExpr::findVoidExpression( untyped, indexer );
    357                 delete untyped;
     357                ResolvExpr::findVoidExpression( expr, indexer );
    358358
    359359                return new ExprStmt( noLabels, expr );
     
    379379                        new ListInit(
    380380                                map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
    381                                         Expression * untyped = new CastExpr(
     381                                        Expression * init = new CastExpr(
    382382                                                new UntypedExpr(
    383383                                                        new NameExpr( "get_monitor" ),
     
    393393                                        );
    394394
    395                                         Expression * init = ResolvExpr::findSingleExpression( untyped, indexer );
    396                                         delete untyped;
     395                                        ResolvExpr::findSingleExpression( init, indexer );
    397396                                        return new SingleInit( init );
    398397                                })
  • src/GenPoly/Box.cc

    rb96ec83 r6840e7c  
    600600
    601601                        // add size/align for generic types to parameter list
    602                         if ( ! appExpr->get_function()->has_result() ) return;
     602                        if ( ! appExpr->get_function()->result ) return;
    603603                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
    604604                        assert( funcType );
     
    714714
    715715                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    716                         assertf( arg->has_result(), "arg does not have result: %s", toString( arg ).c_str() );
    717                         if ( isPolyType( param, exprTyVars ) ) {
    718                                 Type * newType = arg->get_result()->clone();
     716                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
     717                        if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
     718
     719                        if ( arg->result->get_lvalue() ) {
     720                                // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
     721                                // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
     722                                //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
     723                                //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
     724                                //              return;
     725                                //      }
     726                                // }
     727                                arg =  generalizedLvalue( new AddressExpr( arg ) );
     728                                if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
     729                                        // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
     730                                        arg = new CastExpr( arg, param->clone() );
     731                                }
     732                        } else {
     733                                // use type computed in unification to declare boxed variables
     734                                Type * newType = param->clone();
    719735                                if ( env ) env->apply( newType );
    720                                 std::unique_ptr<Type> manager( newType );
    721                                 if ( isPolyType( newType ) ) {
    722                                         // if the argument's type is polymorphic, we don't need to box again!
    723                                         return;
    724                                 } else if ( arg->get_result()->get_lvalue() ) {
    725                                         // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
    726                                         // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
    727                                         //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
    728                                         //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
    729                                         //              return;
    730                                         //      }
    731                                         // }
    732                                         arg =  generalizedLvalue( new AddressExpr( arg ) );
    733                                         if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
    734                                                 // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
    735                                                 arg = new CastExpr( arg, param->clone() );
    736                                         }
    737                                 } else {
    738                                         // use type computed in unification to declare boxed variables
    739                                         Type * newType = param->clone();
    740                                         if ( env ) env->apply( newType );
    741                                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
    742                                         newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    743                                         stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
    744                                         UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
    745                                         assign->get_args().push_back( new VariableExpr( newObj ) );
    746                                         assign->get_args().push_back( arg );
    747                                         stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
    748                                         arg = new AddressExpr( new VariableExpr( newObj ) );
    749                                 } // if
     736                                ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
     737                                newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
     738                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
     739                                UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
     740                                assign->get_args().push_back( new VariableExpr( newObj ) );
     741                                assign->get_args().push_back( arg );
     742                                stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
     743                                arg = new AddressExpr( new VariableExpr( newObj ) );
    750744                        } // if
    751745                }
     
    965959                                if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
    966960                                        if ( varExpr->get_var()->get_name() == "?[?]" ) {
    967                                                 assert( appExpr->has_result() );
     961                                                assert( appExpr->result );
    968962                                                assert( appExpr->get_args().size() == 2 );
    969963                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
     
    999993                                                } // if
    1000994                                        } else if ( varExpr->get_var()->get_name() == "*?" ) {
    1001                                                 assert( appExpr->has_result() );
     995                                                assert( appExpr->result );
    1002996                                                assert( ! appExpr->get_args().empty() );
    1003997                                                if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
     
    10161010                                                } // if
    10171011                                        } else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
    1018                                                 assert( appExpr->has_result() );
     1012                                                assert( appExpr->result );
    10191013                                                assert( appExpr->get_args().size() == 1 );
    10201014                                                if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
     
    10361030                                                } // if
    10371031                                        } else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
    1038                                                 assert( appExpr->has_result() );
     1032                                                assert( appExpr->result );
    10391033                                                assert( appExpr->get_args().size() == 1 );
    10401034                                                if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
     
    10421036                                                } // if
    10431037                                        } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
    1044                                                 assert( appExpr->has_result() );
     1038                                                assert( appExpr->result );
    10451039                                                assert( appExpr->get_args().size() == 2 );
    10461040                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
     
    10681062                                                } // if
    10691063                                        } else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
    1070                                                 assert( appExpr->has_result() );
     1064                                                assert( appExpr->result );
    10711065                                                assert( appExpr->get_args().size() == 2 );
    10721066                                                Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
     
    11621156                void Pass1::premutate( AddressExpr * ) { visit_children = false; }
    11631157                Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
    1164                         assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
     1158                        assert( addrExpr->get_arg()->result && ! addrExpr->get_arg()->get_result()->isVoid() );
    11651159
    11661160                        bool needs = false;
    11671161                        if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
    1168                                 if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
     1162                                if ( expr->result && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
    11691163                                        if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
    11701164                                                if ( name->get_name() == "*?" ) {
    11711165                                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
    1172                                                                 assert( appExpr->get_function()->has_result() );
     1166                                                                assert( appExpr->get_function()->result );
    11731167                                                                FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
    11741168                                                                assert( function );
  • src/GenPoly/FindFunction.cc

    rb96ec83 r6840e7c  
    1818#include <utility>                      // for pair
    1919
     20#include "Common/PassVisitor.h"         // for PassVisitor
    2021#include "Common/SemanticError.h"       // for SemanticError
    2122#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
     
    2728
    2829namespace GenPoly {
    29         class FindFunction : public Mutator {
     30        class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {
    3031          public:
    3132                FindFunction( std::list< FunctionType* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
    3233
    33                 virtual Type *mutate( FunctionType *functionType );
    34                 virtual Type *mutate( PointerType *pointerType );
     34                void premutate( FunctionType * functionType );
     35                Type * postmutate( FunctionType * functionType );
     36                void premutate( PointerType * pointerType );
    3537          private:
    3638                void handleForall( const Type::ForallList &forall );
     
    4345
    4446        void findFunction( Type *type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    45                 FindFunction finder( functions, tyVars, false, predicate );
     47                PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );
    4648                type->acceptMutator( finder );
    4749        }
    4850
    4951        void findAndReplaceFunction( Type *&type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    50                 FindFunction finder( functions, tyVars, true, predicate );
     52                PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );
    5153                type = type->acceptMutator( finder );
    5254        }
     
    5759
    5860        void FindFunction::handleForall( const Type::ForallList &forall ) {
    59                 for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
    60                         TyVarMap::iterator var = tyVars.find( (*i)->get_name() );
     61                for ( const Declaration * td : forall ) {
     62                        TyVarMap::iterator var = tyVars.find( td->name );
    6163                        if ( var != tyVars.end() ) {
    6264                                tyVars.erase( var->first );
     
    6567        }
    6668
    67         Type * FindFunction::mutate( FunctionType *functionType ) {
    68                 tyVars.beginScope();
     69        void FindFunction::premutate( FunctionType * functionType ) {
     70                visit_children = false;
     71                GuardScope( tyVars );
    6972                handleForall( functionType->get_forall() );
    70                 mutateAll( functionType->get_returnVals(), *this );
     73                mutateAll( functionType->get_returnVals(), *visitor );
     74        }
     75
     76        Type * FindFunction::postmutate( FunctionType * functionType ) {
    7177                Type *ret = functionType;
    7278                if ( predicate( functionType, tyVars ) ) {
     
    7783                        } // if
    7884                } // if
    79                 tyVars.endScope();
    8085                return ret;
    8186        }
    8287
    83         Type * FindFunction::mutate( PointerType *pointerType ) {
    84                 tyVars.beginScope();
     88        void FindFunction::premutate( PointerType * pointerType ) {
     89                GuardScope( tyVars );
    8590                handleForall( pointerType->get_forall() );
    86                 Type *ret = Mutator::mutate( pointerType );
    87                 tyVars.endScope();
    88                 return ret;
    8991        }
    9092} // namespace GenPoly
  • src/GenPoly/GenPoly.cc

    rb96ec83 r6840e7c  
    432432        }
    433433
     434        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {
     435                // is parameter is not polymorphic, don't need to box
     436                if ( ! isPolyType( param, exprTyVars ) ) return false;
     437                Type * newType = arg->clone();
     438                if ( env ) env->apply( newType );
     439                std::unique_ptr<Type> manager( newType );
     440                // if the argument's type is polymorphic, we don't need to box again!
     441                return ! isPolyType( newType );
     442        }
     443
     444        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {
     445                FunctionType * function = getFunctionType( appExpr->function->result );
     446                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
     447                TyVarMap exprTyVars( TypeDecl::Data{} );
     448                makeTyVarMap( function, exprTyVars );
     449                return needsBoxing( param, arg, exprTyVars, env );
     450        }
     451
    434452        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    435453                // xxx - should this actually be insert?
  • src/GenPoly/GenPoly.h

    rb96ec83 r6840e7c  
    8080        bool typesPolyCompatible( Type *aty, Type *bty );
    8181
     82        /// true if arg requires boxing given exprTyVars
     83        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );
     84
     85        /// true if arg requires boxing in the call to appExpr
     86        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );
     87
    8288        /// Adds the type variable `tyVar` to `tyVarMap`
    8389        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
  • src/GenPoly/Specialize.cc

    rb96ec83 r6840e7c  
    147147
    148148        Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
    149                 assertf( actual->has_result(), "attempting to specialize an untyped expression" );
     149                assertf( actual->result, "attempting to specialize an untyped expression" );
    150150                if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
    151151                        if ( FunctionType *funType = getFunctionType( formalType ) ) {
  • src/GenPoly/module.mk

    rb96ec83 r6840e7c  
    2020       GenPoly/Lvalue.cc \
    2121       GenPoly/Specialize.cc \
    22        GenPoly/CopyParams.cc \
    2322       GenPoly/FindFunction.cc \
    2423       GenPoly/InstantiateGeneric.cc
  • src/InitTweak/FixInit.cc

    rb96ec83 r6840e7c  
    9494                        /// true if type does not need to be copy constructed to ensure correctness
    9595                        bool skipCopyConstruct( Type * type );
    96                         void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     96                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    9797                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    9898
     
    259259
    260260                GenStructMemberCalls::generate( translationUnit );
     261
    261262                // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
    262263                // hack in the way untyped assignments are generated, where the first argument cannot have
     
    288289                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    289290                                try {
    290                                         *i = maybeMutate( *i, fixer );
     291                                        maybeMutate( *i, fixer );
    291292                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    292293                                } catch( SemanticError &e ) {
     
    322323
    323324                Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
    324                         assert( appExpr );
    325 
    326325                        if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
    327                                 if ( LinkageSpec::isBuiltin( function->get_var()->get_linkage() ) ) {
     326                                if ( function->var->linkage.is_builtin ) {
    328327                                        // optimization: don't need to copy construct in order to call intrinsic functions
    329328                                        return appExpr;
     
    331330                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    332331                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
    333                                         if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    334                                                 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    335                                                 Type * t2 = ftype->get_parameters().back()->get_type();
     332                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) {
     333                                                Type * t1 = getPointerBase( ftype->parameters.front()->get_type() );
     334                                                Type * t2 = ftype->parameters.back()->get_type();
    336335                                                assert( t1 );
    337336
     
    366365                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    367366                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
    368                         Expression * untyped = exprStmt->get_expr();
     367                        Expression * resolved = exprStmt->expr;
     368                        exprStmt->expr = nullptr; // take ownership of expr
    369369
    370370                        // resolve copy constructor
    371371                        // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed
    372372                        // (VariableExpr and already resolved expression)
    373                         CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    374                         Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );
     373                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; )
     374                        ResolvExpr::findVoidExpression( resolved, indexer );
    375375                        assert( resolved );
    376376                        if ( resolved->get_env() ) {
     
    380380                                resolved->set_env( nullptr );
    381381                        } // if
    382 
    383382                        delete stmt;
    384383                        return resolved;
    385384                }
    386385
    387                 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     386                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
    388387                        static UniqueName tempNamer("_tmp_cp");
    389388                        assert( env );
    390389                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
    391                         assert( arg->has_result() );
    392                         Type * result = arg->get_result();
     390                        assert( arg->result );
     391                        Type * result = arg->result;
    393392                        if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
    394393
    395                         // type may involve type variables, so apply type substitution to get temporary variable's actual type
     394                        // type may involve type variables, so apply type substitution to get temporary variable's actual type.
     395                        // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
    396396                        result = result->clone();
    397                         env->apply( result );
     397                        env->applyFree( result );
    398398                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    399399                        tmp->get_type()->set_const( false );
     
    406406                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
    407407                                // don't create the temporary and don't call the copy constructor
    408                                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    409                                 assert( function );
    410                                 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
     408                                VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
     409                                if ( function->var->linkage == LinkageSpec::Intrinsic ) {
     410                                        // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
     411                                        // so that the object isn't changed inside of the polymorphic function
     412                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
     413                                }
    411414                        }
    412415
     
    416419                        // replace argument to function call with temporary
    417420                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    418                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    419                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     421                        impCpCtorExpr->tempDecls.push_back( tmp );
     422                        impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    420423                }
    421424
     
    427430                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    428431
    429                         ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     432                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
    430433
    431434                        // take each argument and attempt to copy construct it.
    432                         for ( Expression * & arg : appExpr->get_args() ) {
    433                                 copyConstructArg( arg, impCpCtorExpr );
     435                        FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
     436                        assert( ftype );
     437                        auto & params = ftype->parameters;
     438                        auto iter = params.begin();
     439                        for ( Expression * & arg : appExpr->args ) {
     440                                Type * formal = nullptr;
     441                                if ( iter != params.end() ) {
     442                                        DeclarationWithType * param = *iter++;
     443                                        formal = param->get_type();
     444                                }
     445
     446                                copyConstructArg( arg, impCpCtorExpr, formal );
    434447                        } // for
    435448
     
    437450                        // initialized with the return value and is destructed later
    438451                        // xxx - handle named return values?
    439                         Type * result = appExpr->get_result();
     452                        Type * result = appExpr->result;
    440453                        if ( ! result->isVoid() ) {
    441454                                static UniqueName retNamer("_tmp_cp_ret");
     
    443456                                env->apply( result );
    444457                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    445                                 ret->get_type()->set_const( false );
    446                                 impCpCtorExpr->get_returnDecls().push_back( ret );
     458                                ret->type->set_const( false );
     459                                impCpCtorExpr->returnDecls.push_back( ret );
    447460                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    448461                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
     
    551564                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    552565                                // move env from callExpr to retExpr
    553                                 retExpr->set_env( callExpr->get_env() );
    554                                 callExpr->set_env( nullptr );
     566                                std::swap( retExpr->env, callExpr->env );
    555567                                return retExpr;
    556568                        } else {
     
    754766                                                if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) {
    755767                                                        // clean up intrinsic copy constructor calls by making them into SingleInits
    756                                                         objDecl->init = new SingleInit( ctorCall->args.back() );
     768                                                        Expression * ctorArg = ctorCall->args.back();
     769                                                        std::swap( ctorArg->env, ctorCall->env );
     770                                                        objDecl->init = new SingleInit( ctorArg );
     771
    757772                                                        ctorCall->args.pop_back();
    758773                                                } else {
     
    822837                        GuardValue( labelVars );
    823838                        labelVars.clear();
     839                        // LabelFinder does not recurse into FunctionDecl, so need to visit
     840                        // its children manually.
    824841                        maybeAccept( funcDecl->type, finder );
    825842                        maybeAccept( funcDecl->statements, finder );
     
    10791096                }
    10801097
    1081                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
     1098                DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    10821099                        // add object to the indexer assumes that there will be no name collisions
    10831100                        // in generated code. If this changes, add mutate methods for entities with
     
    10871104                }
    10881105
    1089                 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
    1090                         return strict_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
     1106                Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1107                        Expression * newExpr = untypedExpr;
     1108                        ResolvExpr::findVoidExpression( newExpr, indexer );
     1109                        return newExpr;
    10911110                }
    10921111
     
    10941113                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    10951114                        // xxx - is the size check necessary?
    1096                         assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
     1115                        assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 );
    10971116
    10981117                        // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
     
    11131132
    11141133                        // resolve assignment and dispose of new env
    1115                         Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );
    1116                         delete resolvedAssign->env;
    1117                         resolvedAssign->env = nullptr;
    1118                         delete assign;
     1134                        ResolvExpr::findVoidExpression( assign, indexer );
     1135                        delete assign->env;
     1136                        assign->env = nullptr;
    11191137
    11201138                        // for constructor expr:
     
    11251143                        //   T & tmp;
    11261144                        //   &tmp = &x, ?{}(tmp), tmp
    1127                         CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
     1145                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11281146                        commaExpr->set_env( env );
    11291147                        return commaExpr;
  • src/InitTweak/GenInit.cc

    rb96ec83 r6840e7c  
    8585                // should not have a ConstructorInit generated.
    8686
    87                 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
    88                 bool isManaged( Type * type ) const; // determine if type is managed
    89                 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    90                 GenPoly::ScopedSet< std::string > managedTypes;
     87                ManagedTypes managedTypes;
    9188                bool inFunction = false;
    9289        };
     
    129126                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    130127                // is being returned
    131                 if ( returnStmt->get_expr() && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
     128                if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    132129                        // explicitly construct the return value using the return expression and the retVal object
    133                         assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    134 
    135                         stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
     130                        assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
     131
     132                        ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
     133                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) {
     134                                // return statement has already been mutated - don't need to do it again
     135                                if ( varExpr->var == retVal ) return;
     136                        }
     137                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) );
    136138
    137139                        // return the retVal object
    138                         returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
     140                        returnStmt->expr = new VariableExpr( returnVals.front() );
    139141                } // if
    140142        }
     
    199201        }
    200202
    201         bool CtorDtor::isManaged( Type * type ) const {
     203        bool ManagedTypes::isManaged( Type * type ) const {
    202204                // references are never constructed
    203205                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
     
    215217        }
    216218
    217         bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
     219        bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const {
    218220                Type * type = objDecl->get_type();
    219221                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     
    223225        }
    224226
    225         void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
     227        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    226228                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    227229                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
     
    233235                }
    234236        }
     237
     238        void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) {
     239                // don't construct members, but need to take note if there is a managed member,
     240                // because that means that this type is also managed
     241                for ( Declaration * member : aggregateDecl->get_members() ) {
     242                        if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     243                                if ( isManaged( field ) ) {
     244                                        StructInstType inst( Type::Qualifiers(), aggregateDecl );
     245                                        managedTypes.insert( SymTab::Mangler::mangle( &inst ) );
     246                                        break;
     247                                }
     248                        }
     249                }
     250        }
     251
     252        void ManagedTypes::beginScope() { managedTypes.beginScope(); }
     253        void ManagedTypes::endScope() { managedTypes.endScope(); }
    235254
    236255        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
     
    277296
    278297        void CtorDtor::previsit( ObjectDecl * objDecl ) {
    279                 handleDWT( objDecl );
     298                managedTypes.handleDWT( objDecl );
    280299                // hands off if @=, extern, builtin, etc.
    281300                // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C
    282                 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
     301                if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    283302                        // constructed objects cannot be designated
    284303                        if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
     
    295314                inFunction = true;
    296315
    297                 handleDWT( functionDecl );
     316                managedTypes.handleDWT( functionDecl );
    298317
    299318                GuardScope( managedTypes );
     
    301320                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    302321                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    303                                 handleDWT( assertion );
     322                                managedTypes.handleDWT( assertion );
    304323                        }
    305324                }
     
    311330                visit_children = false; // do not try to construct and destruct aggregate members
    312331
    313                 // don't construct members, but need to take note if there is a managed member,
    314                 // because that means that this type is also managed
    315                 for ( Declaration * member : aggregateDecl->get_members() ) {
    316                         if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
    317                                 if ( isManaged( field ) ) {
    318                                         StructInstType inst( Type::Qualifiers(), aggregateDecl );
    319                                         managedTypes.insert( SymTab::Mangler::mangle( &inst ) );
    320                                         break;
    321                                 }
    322                         }
    323                 }
     332                managedTypes.handleStruct( aggregateDecl );
    324333        }
    325334
  • src/InitTweak/GenInit.h

    rb96ec83 r6840e7c  
    1616#pragma once
    1717
    18 #include <list>               // for list
    19 #include <string>             // for string
     18#include <list>                // for list
     19#include <string>              // for string
    2020
    21 #include "SynTree/SynTree.h"  // for Visitor Nodes
     21#include "SynTree/SynTree.h"   // for Visitor Nodes
     22
     23#include "GenPoly/ScopedSet.h" // for ScopedSet
    2224
    2325namespace InitTweak {
     
    3335        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
    3436        ConstructorInit * genCtorInit( ObjectDecl * objDecl );
     37
     38        class ManagedTypes {
     39        public:
     40                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
     41                bool isManaged( Type * type ) const; // determine if type is managed
     42
     43                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
     44                void handleStruct( StructDecl * aggregateDecl ); // add type to managed if child is managed
     45
     46                void beginScope();
     47                void endScope();
     48        private:
     49                GenPoly::ScopedSet< std::string > managedTypes;
     50        };
    3551} // namespace
    3652
  • src/InitTweak/InitTweak.cc

    rb96ec83 r6840e7c  
    168168                deleteAll( indices );
    169169                indices.clear();
     170        }
     171
     172        bool InitExpander::addReference() {
     173                bool added = false;
     174                for ( Expression *& expr : cur ) {
     175                        expr = new AddressExpr( expr );
     176                        added = true;
     177                }
     178                return added;
    170179        }
    171180
     
    270279        }
    271280
    272         Type * getThisType( FunctionType * ftype ) {
    273                 assertf( ftype, "getThisType: nullptr ftype" );
    274                 ObjectDecl * thisParam = getThisParam( ftype );
     281        Type * getTypeofThis( FunctionType * ftype ) {
     282                assertf( ftype, "getTypeofThis: nullptr ftype" );
     283                ObjectDecl * thisParam = getParamThis( ftype );
    275284                ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type );
    276285                return refType->base;
    277286        }
    278287
    279         ObjectDecl * getThisParam( FunctionType * ftype ) {
    280                 assertf( ftype, "getThisParam: nullptr ftype" );
     288        ObjectDecl * getParamThis( FunctionType * ftype ) {
     289                assertf( ftype, "getParamThis: nullptr ftype" );
    281290                auto & params = ftype->parameters;
    282                 assertf( ! params.empty(), "getThisParam: ftype with 0 parameters: %s", toString( ftype ).c_str() );
     291                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() );
    283292                return strict_dynamic_cast< ObjectDecl * >( params.front() );
    284293        }
     
    353362                        assert( expr );
    354363                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    355                                 return varExpr->get_var();
     364                                return varExpr->var;
    356365                        } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
    357                                 return memberExpr->get_member();
     366                                return memberExpr->member;
    358367                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    359                                 return getCalledFunction( castExpr->get_arg() );
     368                                return getCalledFunction( castExpr->arg );
    360369                        } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
    361370                                return handleDerefCalledFunction( untypedExpr );
     
    363372                                return handleDerefCalledFunction( appExpr );
    364373                        } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
    365                                 return getCalledFunction( addrExpr->get_arg() );
     374                                return getCalledFunction( addrExpr->arg );
     375                        } else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) {
     376                                return getCalledFunction( commaExpr->arg2 );
    366377                        }
    367378                        return nullptr;
     
    578589        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
    579590                FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
    580                 if ( ! function ) return 0;
    581                 if ( function->get_name() != fname ) return 0;
    582                 FunctionType * ftype = function->get_functionType();
    583                 if ( ftype->get_parameters().size() != 2 ) return 0;
     591                if ( ! function ) return nullptr;
     592                if ( function->name != fname ) return nullptr;
     593                FunctionType * ftype = function->type;
     594                if ( ftype->parameters.size() != 2 ) return nullptr;
    584595
    585596                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    586                 Type * t2 = ftype->get_parameters().back()->get_type();
     597                Type * t2 = ftype->parameters.back()->get_type();
    587598                assert( t1 );
    588599
     
    604615        }
    605616        FunctionDecl * isDefaultConstructor( Declaration * decl ) {
    606                 if ( isConstructor( decl->get_name() ) ) {
     617                if ( isConstructor( decl->name ) ) {
    607618                        if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
    608                                 if ( func->get_functionType()->get_parameters().size() == 1 ) {
     619                                if ( func->type->parameters.size() == 1 ) {
    609620                                        return func;
    610621                                }
  • src/InitTweak/InitTweak.h

    rb96ec83 r6840e7c  
    3131
    3232        /// returns the base type of the first parameter to a constructor/destructor/assignment function
    33         Type * getThisType( FunctionType * ftype );
     33        Type * getTypeofThis( FunctionType * ftype );
    3434
    3535        /// returns the first parameter of a constructor/destructor/assignment function
    36         ObjectDecl * getThisParam( FunctionType * ftype );
     36        ObjectDecl * getParamThis( FunctionType * ftype );
    3737
    3838        /// transform Initializer into an argument list that can be passed to a call expression
     
    105105                void addArrayIndex( Expression * index, Expression * dimension );
    106106                void clearArrayIndices();
     107                bool addReference();
    107108
    108109                class ExpanderImpl;
  • src/MakeLibCfa.cc

    rb96ec83 r6840e7c  
    119119                        newDecls.push_back( funcDecl );
    120120
     121                        Statement * stmt = nullptr;
    121122                        switch ( opInfo.type ) {
    122123                          case CodeGen::OT_INDEX:
     
    128129                          case CodeGen::OT_POSTFIXASSIGN:
    129130                          case CodeGen::OT_INFIXASSIGN:
     131                                        // return the recursive call
     132                                        stmt = new ReturnStmt( noLabels, newExpr );
     133                                        break;
    130134                          case CodeGen::OT_CTOR:
    131135                          case CodeGen::OT_DTOR:
    132                                 // return the recursive call
    133                                         funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
     136                                        // execute the recursive call
     137                                        stmt = new ExprStmt( noLabels, newExpr );
    134138                                        break;
    135139                          case CodeGen::OT_CONSTANT:
     
    138142                                assert( false );
    139143                        } // switch
     144                        funcDecl->get_statements()->push_back( stmt );
    140145                }
    141146        } // namespace
  • src/Makefile.in

    rb96ec83 r6840e7c  
    175175        GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT) \
    176176        GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT) \
    177         GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \
    178177        GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
    179178        GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
     
    495494        ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
    496495        GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc \
    497         GenPoly/Specialize.cc GenPoly/CopyParams.cc \
    498         GenPoly/FindFunction.cc GenPoly/InstantiateGeneric.cc \
    499         InitTweak/GenInit.cc InitTweak/FixInit.cc \
    500         InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \
    501         Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
    502         Parser/ParseNode.cc Parser/DeclarationNode.cc \
    503         Parser/ExpressionNode.cc Parser/StatementNode.cc \
    504         Parser/InitializerNode.cc Parser/TypeData.cc \
    505         Parser/LinkageSpec.cc Parser/parserutility.cc \
    506         ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \
    507         ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \
    508         ResolvExpr/CommonType.cc ResolvExpr/ConversionCost.cc \
    509         ResolvExpr/CastCost.cc ResolvExpr/PtrsCastable.cc \
    510         ResolvExpr/AdjustExprType.cc ResolvExpr/AlternativePrinter.cc \
    511         ResolvExpr/Resolver.cc ResolvExpr/ResolveTypeof.cc \
    512         ResolvExpr/RenameVars.cc ResolvExpr/FindOpenVars.cc \
    513         ResolvExpr/PolyCost.cc ResolvExpr/Occurs.cc \
    514         ResolvExpr/TypeEnvironment.cc ResolvExpr/CurrentObject.cc \
    515         SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
    516         SymTab/FixFunction.cc SymTab/ImplementationType.cc \
    517         SymTab/TypeEquality.cc SymTab/Autogen.cc SynTree/Type.cc \
    518         SynTree/VoidType.cc SynTree/BasicType.cc \
    519         SynTree/PointerType.cc SynTree/ArrayType.cc \
    520         SynTree/ReferenceType.cc SynTree/FunctionType.cc \
    521         SynTree/ReferenceToType.cc SynTree/TupleType.cc \
    522         SynTree/TypeofType.cc SynTree/AttrType.cc \
     496        GenPoly/Specialize.cc GenPoly/FindFunction.cc \
     497        GenPoly/InstantiateGeneric.cc InitTweak/GenInit.cc \
     498        InitTweak/FixInit.cc InitTweak/FixGlobalInit.cc \
     499        InitTweak/InitTweak.cc Parser/parser.yy Parser/lex.ll \
     500        Parser/TypedefTable.cc Parser/ParseNode.cc \
     501        Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
     502        Parser/StatementNode.cc Parser/InitializerNode.cc \
     503        Parser/TypeData.cc Parser/LinkageSpec.cc \
     504        Parser/parserutility.cc ResolvExpr/AlternativeFinder.cc \
     505        ResolvExpr/Alternative.cc ResolvExpr/Unify.cc \
     506        ResolvExpr/PtrsAssignable.cc ResolvExpr/CommonType.cc \
     507        ResolvExpr/ConversionCost.cc ResolvExpr/CastCost.cc \
     508        ResolvExpr/PtrsCastable.cc ResolvExpr/AdjustExprType.cc \
     509        ResolvExpr/AlternativePrinter.cc ResolvExpr/Resolver.cc \
     510        ResolvExpr/ResolveTypeof.cc ResolvExpr/RenameVars.cc \
     511        ResolvExpr/FindOpenVars.cc ResolvExpr/PolyCost.cc \
     512        ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \
     513        ResolvExpr/CurrentObject.cc SymTab/Indexer.cc \
     514        SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \
     515        SymTab/ImplementationType.cc SymTab/TypeEquality.cc \
     516        SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \
     517        SynTree/BasicType.cc SynTree/PointerType.cc \
     518        SynTree/ArrayType.cc SynTree/ReferenceType.cc \
     519        SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
     520        SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
    523521        SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \
    524522        SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \
     
    718716        GenPoly/$(DEPDIR)/$(am__dirstamp)
    719717GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT): GenPoly/$(am__dirstamp) \
    720         GenPoly/$(DEPDIR)/$(am__dirstamp)
    721 GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT): GenPoly/$(am__dirstamp) \
    722718        GenPoly/$(DEPDIR)/$(am__dirstamp)
    723719GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
     
    997993@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Po@am__quote@
    998994@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po@am__quote@
    999 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Po@am__quote@
    1000995@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
    1001996@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
     
    14791474@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Specialize.obj `if test -f 'GenPoly/Specialize.cc'; then $(CYGPATH_W) 'GenPoly/Specialize.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Specialize.cc'; fi`
    14801475
    1481 GenPoly/driver_cfa_cpp-CopyParams.o: GenPoly/CopyParams.cc
    1482 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-CopyParams.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Tpo -c -o GenPoly/driver_cfa_cpp-CopyParams.o `test -f 'GenPoly/CopyParams.cc' || echo '$(srcdir)/'`GenPoly/CopyParams.cc
    1483 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Po
    1484 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/CopyParams.cc' object='GenPoly/driver_cfa_cpp-CopyParams.o' libtool=no @AMDEPBACKSLASH@
    1485 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1486 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-CopyParams.o `test -f 'GenPoly/CopyParams.cc' || echo '$(srcdir)/'`GenPoly/CopyParams.cc
    1487 
    1488 GenPoly/driver_cfa_cpp-CopyParams.obj: GenPoly/CopyParams.cc
    1489 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-CopyParams.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Tpo -c -o GenPoly/driver_cfa_cpp-CopyParams.obj `if test -f 'GenPoly/CopyParams.cc'; then $(CYGPATH_W) 'GenPoly/CopyParams.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/CopyParams.cc'; fi`
    1490 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Po
    1491 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/CopyParams.cc' object='GenPoly/driver_cfa_cpp-CopyParams.obj' libtool=no @AMDEPBACKSLASH@
    1492 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1493 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-CopyParams.obj `if test -f 'GenPoly/CopyParams.cc'; then $(CYGPATH_W) 'GenPoly/CopyParams.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/CopyParams.cc'; fi`
    1494 
    14951476GenPoly/driver_cfa_cpp-FindFunction.o: GenPoly/FindFunction.cc
    14961477@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-FindFunction.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Tpo -c -o GenPoly/driver_cfa_cpp-FindFunction.o `test -f 'GenPoly/FindFunction.cc' || echo '$(srcdir)/'`GenPoly/FindFunction.cc
  • src/Parser/DeclarationNode.cc

    rb96ec83 r6840e7c  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 12:34:05 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Aug 10 17:02:00 2017
    13 // Update Count     : 1021
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Sep 23 18:16:48 2017
     13// Update Count     : 1024
    1414//
    1515
     
    4040using namespace std;
    4141
    42 // These must remain in the same order as the corresponding DeclarationNode enumerations.
    43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "NoBasicTypeNames" };
     42// These must harmonize with the corresponding DeclarationNode enumerations.
     43const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "int128", "float80", "float128", "NoBasicTypeNames" };
    4444const char * DeclarationNode::complexTypeNames[] = { "_Complex", "_Imaginary", "NoComplexTypeNames" };
    4545const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
  • src/Parser/ExpressionNode.cc

    rb96ec83 r6840e7c  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Sep 14 23:09:34 2017
    13 // Update Count     : 690
     12// Last Modified On : Wed Sep 27 22:51:55 2017
     13// Update Count     : 781
    1414//
    1515
     
    6060static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
    6161
     62static const char * lnthsInt[2][6] = {
     63        { "int8_t", "int16_t", "int32_t", "int64_t", "size_t", },
     64        { "uint8_t", "uint16_t", "uint32_t", "uint64_t", "size_t", }
     65}; // lnthsInt
     66
     67static inline void checkLNInt( string & str, int & lnth, int & size ) {
     68        string::size_type posn = str.find_first_of( "lL" ), start = posn;
     69  if ( posn == string::npos ) return;
     70        size = 4;                                                                                       // assume largest size
     71        posn += 1;                                                                                      // advance to size
     72        if ( str[posn] == '8' ) {                                                       // 8
     73                lnth = 0;
     74        } else if ( str[posn] == '1' ) {
     75                posn += 1;
     76                if ( str[posn] == '6' ) {                                               // 16
     77                        lnth = 1;
     78                } else {                                                                                // 128
     79                        posn += 1;
     80                        lnth = 5;
     81                } // if
     82        } else {
     83                if ( str[posn] == '3' ) {                                               // 32
     84                        lnth = 2;
     85                } else if ( str[posn] == '6' ) {                                // 64
     86                        lnth = 3;
     87                } else {
     88                        assertf( false, "internal error, bad integral length %s", str.c_str() );
     89                } // if
     90                posn += 1;
     91        } // if
     92        str.erase( start, posn - start + 1 );                           // remove length suffix
     93} // checkLNInt
     94
    6295static void sepNumeric( string & str, string & units ) {
    6396        string::size_type posn = str.find_first_of( "`" );
     
    69102
    70103Expression * build_constantInteger( string & str ) {
    71         static const BasicType::Kind kind[2][5] = {
     104        static const BasicType::Kind kind[2][6] = {
    72105                // short (h) must be before char (hh)
    73                 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt },
    74                 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt },
     106                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
     107                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
    75108        };
    76109
    77         string units;                                                                           // units
     110        string units;
    78111        sepNumeric( str, units );                                                       // separate constant from units
    79112
    80113        bool dec = true, Unsigned = false;                                      // decimal, unsigned constant
    81         int size;                                                                                       // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => size_t
     114        int size;                                                                                       // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     115        int lnth = -1;                                                                          // literal length
     116
    82117        unsigned long long int v;                                                       // converted integral value
    83118        size_t last = str.length() - 1;                                         // last character of constant
     
    140175                        } // if
    141176                        str.erase( last - size - 1, size + 1 );         // remove 'h'/"hh"
     177                } else {                                                                                // suffix "ln" ?
     178                        checkLNInt( str, lnth, size );
    142179                } // if
    143180        } else if ( checkL( str[ last ] ) ) {                           // suffix 'l' ?
     
    163200                str.erase( last - size, size + 1 );                             // remove 'h'/"hh"
    164201        } else if ( checkZ( str[last] ) ) {                                     // suffix 'z' ?
    165                 size = 5;
     202                lnth = 4;
    166203                str.erase( last, 1 );                                                   // remove 'z'
    167         } // if
    168 
     204        } else {                                                                                        // suffix "ln" ?
     205                checkLNInt( str, lnth, size );
     206        } // if
     207
     208        assert( 0 <= size && size < 6 );
     209        // Constant type is correct for overload resolving.
    169210        ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) );
    170         if ( Unsigned && size < 2 ) {                                           // less than int ?
    171                 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which eliminates warnings for large values.
     211        if ( Unsigned && size < 2 ) {                                           // hh or h, less than int ?
     212                // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    172213                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ) );
    173         } else if ( size == 5 ) {                                                       // explicit cast to size_t
    174                 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), "size_t", false ) );
     214        } else if ( lnth != -1 ) {                                                      // explicit length ?
     215                if ( lnth == 5 ) {                                                              // int128 ?
     216                        size = 5;
     217                        ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ) );
     218                } else {
     219                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][lnth], false ) );
     220                } // if
    175221        } // if
    176222  CLEANUP:
     
    182228        return ret;
    183229} // build_constantInteger
     230
     231
     232static inline void checkLNFloat( string & str, int & lnth, int & size ) {
     233        string::size_type posn = str.find_first_of( "lL" ), start = posn;
     234  if ( posn == string::npos ) return;
     235        size = 2;                                                                                       // assume largest size
     236        lnth = 0;
     237        posn += 1;                                                                                      // advance to size
     238        if ( str[posn] == '3' ) {                                                       // 32
     239                size = 0;
     240        } else if ( str[posn] == '6' ) {                                        // 64
     241                size = 1;
     242        } else if ( str[posn] == '8' || str[posn] == '1' ) { // 80, 128
     243                size = 2;
     244                if ( str[posn] == '1' ) posn += 1;
     245        } else {
     246                assertf( false, "internal error, bad floating point length %s", str.c_str() );
     247        } // if
     248        posn += 1;
     249        str.erase( start, posn - start + 1 );                           // remove length suffix
     250} // checkLNFloat
     251
    184252
    185253Expression * build_constantFloat( string & str ) {
     
    189257        };
    190258
    191         string units;                                                                           // units
     259        string units;
    192260        sepNumeric( str, units );                                                       // separate constant from units
    193261
    194262        bool complx = false;                                                            // real, complex
    195         int size = 1;                                                                           // 0 => float, 1 => double (default), 2 => long double
     263        int size = 1;                                                                           // 0 => float, 1 => double, 2 => long double
     264        int lnth = -1;                                                                          // literal length
    196265        // floating-point constant has minimum of 2 characters: 1. or .1
    197266        size_t last = str.length() - 1;
     
    211280        } else if ( checkL( str[last] ) ) {                                     // long double ?
    212281                size = 2;
     282        } else {
     283                size = 1;                                                                               // double (default)
     284                checkLNFloat( str, lnth, size );
    213285        } // if
    214286        if ( ! complx && checkI( str[last - 1] ) ) {            // imaginary ?
     
    216288        } // if
    217289
     290        assert( 0 <= size && size < 3 );
    218291        Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][size] ), str, v ) );
     292        if ( lnth != -1 ) {                                                                     // explicit length ?
     293                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][size] ) );
     294        } // if
    219295        if ( units.length() != 0 ) {
    220296                ret = new UntypedExpr( new NameExpr( units ), { ret } );
     
    321397
    322398NameExpr * build_varref( const string * name ) {
    323         NameExpr * expr = new NameExpr( *name, nullptr );
     399        NameExpr * expr = new NameExpr( *name );
    324400        delete name;
    325401        return expr;
     
    412488        list< Expression * > args;
    413489        buildMoveList( expr_node, args );
    414         return new UntypedExpr( maybeMoveBuild< Expression >(function), args, nullptr );
     490        return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
    415491} // build_func
    416492
  • src/Parser/ParseNode.h

    rb96ec83 r6840e7c  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Sep 14 23:09:39 2017
    13 // Update Count     : 815
     12// Last Modified On : Sat Sep 23 18:11:22 2017
     13// Update Count     : 821
    1414//
    1515
     
    4747#define YYLTYPE_IS_DECLARED 1 /* alert the parser that we have our own definition */
    4848
    49 extern char * yyfilename;
    50 extern int yylineno;
    5149extern YYLTYPE yylloc;
    5250
     
    197195class DeclarationNode : public ParseNode {
    198196  public:
    199         enum BasicType { Void, Bool, Char, Int, Float, Double, LongDouble, NoBasicType };
     197        // These enumerations must harmonize with their names.
     198        enum BasicType { Void, Bool, Char, Int, Float, Double, LongDouble, Int128, Float80, Float128, NoBasicType };
     199        static const char * basicTypeNames[];
    200200        enum ComplexType { Complex, Imaginary, NoComplexType };
     201        static const char * complexTypeNames[];
    201202        enum Signedness { Signed, Unsigned, NoSignedness };
     203        static const char * signednessNames[];
    202204        enum Length { Short, Long, LongLong, NoLength };
     205        static const char * lengthNames[];
    203206        enum Aggregate { Struct, Union, Trait, Coroutine, Monitor, Thread, NoAggregate };
     207        static const char * aggregateNames[];
    204208        enum TypeClass { Otype, Dtype, Ftype, Ttype, NoTypeClass };
     209        static const char * typeClassNames[];
    205210        enum BuiltinType { Valist, Zero, One, NoBuiltinType };
    206 
    207         static const char * basicTypeNames[];
    208         static const char * complexTypeNames[];
    209         static const char * signednessNames[];
    210         static const char * lengthNames[];
    211         static const char * aggregateNames[];
    212         static const char * typeClassNames[];
    213211        static const char * builtinTypeNames[];
    214212
  • src/Parser/TypeData.cc

    rb96ec83 r6840e7c  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep  1 23:13:38 2017
    13 // Update Count     : 569
     12// Last Modified On : Mon Sep 25 18:33:41 2017
     13// Update Count     : 587
    1414//
    1515
     
    9898} // TypeData::TypeData
    9999
     100
    100101TypeData::~TypeData() {
    101102        delete base;
     
    161162        } // switch
    162163} // TypeData::~TypeData
     164
    163165
    164166TypeData * TypeData::clone() const {
     
    235237} // TypeData::clone
    236238
     239
    237240void TypeData::print( ostream &os, int indent ) const {
    238241        for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) {
     
    398401        } // switch
    399402} // TypeData::print
     403
    400404
    401405template< typename ForallList >
     
    430434                } // if
    431435        } // for
    432 }
     436} // buildForall
     437
    433438
    434439Type * typebuild( const TypeData * td ) {
     
    477482} // typebuild
    478483
     484
    479485TypeData * typeextractAggregate( const TypeData * td, bool toplevel ) {
    480486        TypeData * ret = nullptr;
     
    504510} // typeextractAggregate
    505511
     512
    506513Type::Qualifiers buildQualifiers( const TypeData * td ) {
    507514        return td->qualifiers;
    508515} // buildQualifiers
    509516
     517
     518static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
     519        throw SemanticError( string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
     520} // genTSError
     521
    510522Type * buildBasicType( const TypeData * td ) {
    511523        BasicType::Kind ret;
     
    513525        switch ( td->basictype ) {
    514526          case DeclarationNode::Void:
    515                 if ( td->signedness != DeclarationNode::NoSignedness && td->length != DeclarationNode::NoLength ) {
    516                         throw SemanticError( "invalid type specifier \"void\" in type: ", td );
    517                 } // if
    518 
     527                if ( td->signedness != DeclarationNode::NoSignedness ) {
     528                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     529                } // if
     530                if ( td->length != DeclarationNode::NoLength ) {
     531                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     532                } // if
    519533                return new VoidType( buildQualifiers( td ) );
    520534                break;
     
    522536          case DeclarationNode::Bool:
    523537                if ( td->signedness != DeclarationNode::NoSignedness ) {
    524                         throw SemanticError( string( "invalid type specifier " ) + DeclarationNode::signednessNames[ td->signedness ] + " in type: ", td );
     538                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
    525539                } // if
    526540                if ( td->length != DeclarationNode::NoLength ) {
    527                         throw SemanticError( string( "invalid type specifier " ) + DeclarationNode::lengthNames[ td->length ] + " in type: ", td );
     541                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    528542                } // if
    529543
     
    538552
    539553                if ( td->length != DeclarationNode::NoLength ) {
    540                         throw SemanticError( string( "invalid type specifier " ) + DeclarationNode::lengthNames[ td->length ] + " in type: ", td );
     554                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    541555                } // if
    542556
     
    557571                break;
    558572
     573          case DeclarationNode::Int128:
     574                ret = td->signedness == 1 ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
     575                if ( td->length != DeclarationNode::NoLength ) {
     576                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     577                } // if
     578                break;
     579
    559580          case DeclarationNode::Float:
     581          case DeclarationNode::Float80:
     582          case DeclarationNode::Float128:
    560583          case DeclarationNode::Double:
    561584          case DeclarationNode::LongDouble:                                     // not set until below
     
    568591          FloatingPoint: ;
    569592                if ( td->signedness != DeclarationNode::NoSignedness ) {
    570                         throw SemanticError( string( "invalid type specifier " ) + DeclarationNode::signednessNames[ td->signedness ] + " in type: ", td );
     593                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
    571594                } // if
    572595                if ( td->length == DeclarationNode::Short || td->length == DeclarationNode::LongLong ) {
    573                         throw SemanticError( string( "invalid type specifier " ) + DeclarationNode::lengthNames[ td->length ] + " in type: ", td );
     596                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    574597                } // if
    575598                if ( td->basictype == DeclarationNode::Float && td->length == DeclarationNode::Long ) {
    576                         throw SemanticError( "invalid type specifier \"long\" in type: ", td );
     599                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    577600                } // if
    578601                if ( td->length == DeclarationNode::Long ) {
     
    593616                goto Integral;
    594617          default:
    595                 assert(false);
     618                assertf( false, "unknown basic type" );
    596619                return nullptr;
    597620        } // switch
     
    601624        return bt;
    602625} // buildBasicType
     626
    603627
    604628PointerType * buildPointer( const TypeData * td ) {
     
    612636        return pt;
    613637} // buildPointer
     638
    614639
    615640ArrayType * buildArray( const TypeData * td ) {
     
    626651} // buildArray
    627652
     653
    628654ReferenceType * buildReference( const TypeData * td ) {
    629655        ReferenceType * rt;
     
    637663} // buildReference
    638664
     665
    639666AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
    640667        assert( td->kind == TypeData::Aggregate );
     
    665692        return at;
    666693} // buildAggregate
     694
    667695
    668696ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
     
    722750} // buildAggInst
    723751
     752
    724753ReferenceToType * buildAggInst( const TypeData * td ) {
    725754        assert( td->kind == TypeData::AggregateInst );
     
    761790} // buildAggInst
    762791
     792
    763793NamedTypeDecl * buildSymbolic( const TypeData * td, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
    764794        assert( td->kind == TypeData::Symbolic );
     
    775805} // buildSymbolic
    776806
     807
    777808EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
    778809        assert( td->kind == TypeData::Enum );
     
    790821} // buildEnum
    791822
     823
    792824TypeInstType * buildSymbolicInst( const TypeData * td ) {
    793825        assert( td->kind == TypeData::SymbolicInst );
     
    797829        return ret;
    798830} // buildSymbolicInst
     831
    799832
    800833TupleType * buildTuple( const TypeData * td ) {
     
    807840} // buildTuple
    808841
     842
    809843TypeofType * buildTypeof( const TypeData * td ) {
    810844        assert( td->kind == TypeData::Typeof );
     
    813847        return new TypeofType( buildQualifiers( td ), td->typeexpr->build() );
    814848} // buildTypeof
     849
    815850
    816851Declaration * buildDecl( const TypeData * td, const string &name, Type::StorageClasses scs, Expression * bitfieldWidth, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec linkage, Expression *asmName, Initializer * init, std::list< Attribute * > attributes ) {
     
    836871        return nullptr;
    837872} // buildDecl
     873
    838874
    839875FunctionType * buildFunction( const TypeData * td ) {
     
    857893        return ft;
    858894} // buildFunction
     895
    859896
    860897// Transform KR routine declarations into C99 routine declarations:
  • src/Parser/lex.ll

    rb96ec83 r6840e7c  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sun Sep 10 22:29:15 2017
    13  * Update Count     : 620
     12 * Last Modified On : Sat Sep 23 17:29:28 2017
     13 * Update Count     : 632
    1414 */
    1515
     
    9393                                // numeric constants, CFA: '_' in constant
    9494hex_quad {hex}("_"?{hex}){3}
    95 length ("ll"|"LL"|[lL])|("hh"|"HH"|[hH])
     95size_opt (8|16|32|64|128)?
     96length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hH])
    9697integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]))?{user_suffix_opt}
    9798
     
    109110                                // GCC: D (double) and iI (imaginary) suffixes, and DL (long double)
    110111exponent "_"?[eE]"_"?[+-]?{decimal_digits}
    111 floating_suffix ([fFdDlL]?[iI]?)|([iI][lLfFdD])
     112floating_size 32|64|80|128
     113floating_length ([fFdDlL]|[lL]{floating_size})
     114floating_suffix ({floating_length}?[iI]?)|([iI]{floating_length})
    112115floating_suffix_opt ("_"?({floating_suffix}|"DL"))?{user_suffix_opt}
    113116decimal_digits ({decimal})|({decimal}({decimal}|"_")*{decimal})
     
    234237finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    235238float                   { KEYWORD_RETURN(FLOAT); }
    236 __float128              { KEYWORD_RETURN(FLOAT); }                              // GCC
     239__float80               { KEYWORD_RETURN(FLOAT80); }                    // GCC
     240float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
     241__float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
     242float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
    237243for                             { KEYWORD_RETURN(FOR); }
    238244forall                  { KEYWORD_RETURN(FORALL); }                             // CFA
     
    249255__inline__              { KEYWORD_RETURN(INLINE); }                             // GCC
    250256int                             { KEYWORD_RETURN(INT); }
    251 __int128                { KEYWORD_RETURN(INT); }                                // GCC
    252 __int128_t              { KEYWORD_RETURN(INT); }                                // GCC
     257__int128                { KEYWORD_RETURN(INT128); }                             // GCC
     258int128                  { KEYWORD_RETURN(INT128); }                             // GCC
    253259__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    254260long                    { KEYWORD_RETURN(LONG); }
     
    285291__typeof                { KEYWORD_RETURN(TYPEOF); }                             // GCC
    286292__typeof__              { KEYWORD_RETURN(TYPEOF); }                             // GCC
    287 __uint128_t             { KEYWORD_RETURN(INT); }                                // GCC
    288293union                   { KEYWORD_RETURN(UNION); }
    289294unsigned                { KEYWORD_RETURN(UNSIGNED); }
  • src/Parser/parser.yy

    rb96ec83 r6840e7c  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Sep 14 23:07:12 2017
    13 // Update Count     : 2815
     12// Last Modified On : Mon Oct 16 11:07:29 2017
     13// Update Count     : 2892
    1414//
    1515
     
    4343#define YYDEBUG_LEXER_TEXT (yylval)                                             // lexer loads this up each time
    4444#define YYDEBUG 1                                                                               // get the pretty debugging code to compile
    45 #define YYERROR_VERBOSE
     45#define YYERROR_VERBOSE                                                                 // more information in syntax errors
    4646
    4747#undef __GNUC_MINOR__
     
    117117bool forall = false;                                                                    // aggregate have one or more forall qualifiers ?
    118118
    119 # define YYLLOC_DEFAULT(Cur, Rhs, N)                            \
    120 do                                                              \
    121         if (N) {                                                      \
    122                 (Cur).first_line   = YYRHSLOC(Rhs, 1).first_line;           \
    123                 (Cur).first_column = YYRHSLOC(Rhs, 1).first_column;         \
    124                 (Cur).last_line    = YYRHSLOC(Rhs, N).last_line;            \
    125                 (Cur).last_column  = YYRHSLOC(Rhs, N).last_column;          \
    126                 (Cur).filename     = YYRHSLOC(Rhs, 1).filename;             \
    127         } else {                                                      \
    128                 (Cur).first_line   = (Cur).last_line   =                    \
    129                         YYRHSLOC(Rhs, 0).last_line;                               \
    130                 (Cur).first_column = (Cur).last_column =                    \
    131                         YYRHSLOC(Rhs, 0).last_column;                             \
    132                 (Cur).filename     = YYRHSLOC(Rhs, 0).filename;             \
    133         }                                                             \
    134 while (0)
     119// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
     120#define YYLLOC_DEFAULT(Cur, Rhs, N)                                                                                             \
     121if ( N ) {                                                                                                                                              \
     122        (Cur).first_line   = YYRHSLOC( Rhs, 1 ).first_line;                                                     \
     123        (Cur).first_column = YYRHSLOC( Rhs, 1 ).first_column;                                           \
     124        (Cur).last_line    = YYRHSLOC( Rhs, N ).last_line;                                                      \
     125        (Cur).last_column  = YYRHSLOC( Rhs, N ).last_column;                                            \
     126        (Cur).filename     = YYRHSLOC( Rhs, 1 ).filename;                                                       \
     127} else {                                                                                                                                                \
     128        (Cur).first_line   = (Cur).last_line = YYRHSLOC( Rhs, 0 ).last_line;            \
     129        (Cur).first_column = (Cur).last_column = YYRHSLOC( Rhs, 0 ).last_column;        \
     130        (Cur).filename     = YYRHSLOC( Rhs, 0 ).filename;                                                       \
     131}
    135132%}
    136133
    137134%define parse.error verbose
    138135
    139 // Types declaration
     136// Types declaration for productions
    140137%union
    141138{
     
    173170%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    174171%token BOOL COMPLEX IMAGINARY                                                   // C99
     172%token INT128 FLOAT80 FLOAT128                                                  // GCC
    175173%token ZERO_T ONE_T                                                                             // CFA
    176174%token VALIST                                                                                   // GCC
     
    252250%type<sn> exception_statement                   handler_clause                          finally_clause
    253251%type<catch_kind> handler_key
     252%type<sn> mutex_statement
    254253%type<en> when_clause                                   when_clause_opt                         waitfor                                         timeout
    255254%type<sn> waitfor_statement
     
    458457        | '(' compound_statement ')'                                            // GCC, lambda expression
    459458                { $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); }
    460         | primary_expression '{' argument_expression_list '}' // CFA, constructor call
    461                 {
    462                         Token fn;
    463                         fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
    464                         $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    465                 }
    466459        | type_name '.' no_attr_identifier                                      // CFA, nested type
    467460                { $$ = nullptr; }                                                               // FIX ME
     
    478471                // equivalent to the old x[i,j].
    479472                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $4 ) ); }
     473        | postfix_expression '{' argument_expression_list '}' // CFA, constructor call
     474                {
     475                        Token fn;
     476                        fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
     477                        $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
     478                }
    480479        | postfix_expression '(' argument_expression_list ')'
    481480                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
     
    809808        | jump_statement
    810809        | with_statement
     810        | mutex_statement
    811811        | waitfor_statement
    812812        | exception_statement
     
    10331033        ;
    10341034
     1035// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
     1036mutex_statement:
     1037        MUTEX '(' argument_expression_list ')' statement
     1038                { $$ = nullptr; }                                                               // FIX ME
     1039        ;
     1040
    10351041when_clause:
    10361042        WHEN '(' comma_expression ')'
     
    15511557        | VOLATILE
    15521558                { $$ = DeclarationNode::newTypeQualifier( Type::Volatile ); }
    1553         | MUTEX
    1554                 { $$ = DeclarationNode::newTypeQualifier( Type::Mutex ); }
    15551559        | ATOMIC
    15561560                { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
     
    16061610
    16071611basic_type_name:
    1608         CHAR
     1612        VOID
     1613                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     1614        | BOOL                                                                                          // C99
     1615                { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
     1616        | CHAR
    16091617                { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
     1618        | INT
     1619                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
     1620        | INT128
     1621                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 ); }
     1622        | FLOAT
     1623                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
     1624        | FLOAT80
     1625                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float80 ); }
     1626        | FLOAT128
     1627                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float128 ); }
    16101628        | DOUBLE
    16111629                { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
    1612         | FLOAT
    1613                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
    1614         | INT
    1615                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
    1616         | LONG
    1617                 { $$ = DeclarationNode::newLength( DeclarationNode::Long ); }
    1618         | SHORT
    1619                 { $$ = DeclarationNode::newLength( DeclarationNode::Short ); }
     1630        | COMPLEX                                                                                       // C99
     1631                { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
     1632        | IMAGINARY                                                                                     // C99
     1633                { $$ = DeclarationNode::newComplexType( DeclarationNode::Imaginary ); }
    16201634        | SIGNED
    16211635                { $$ = DeclarationNode::newSignedNess( DeclarationNode::Signed ); }
    16221636        | UNSIGNED
    16231637                { $$ = DeclarationNode::newSignedNess( DeclarationNode::Unsigned ); }
    1624         | VOID
    1625                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
    1626         | BOOL                                                                                          // C99
    1627                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
    1628         | COMPLEX                                                                                       // C99
    1629                 { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
    1630         | IMAGINARY                                                                                     // C99
    1631                 { $$ = DeclarationNode::newComplexType( DeclarationNode::Imaginary ); }
     1638        | SHORT
     1639                { $$ = DeclarationNode::newLength( DeclarationNode::Short ); }
     1640        | LONG
     1641                { $$ = DeclarationNode::newLength( DeclarationNode::Long ); }
    16321642        | ZERO_T
    16331643                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
     
    26992709        paren_identifier attribute_list_opt
    27002710                { $$ = $1->addQualifiers( $2 ); }
     2711        | '&' MUTEX paren_identifier attribute_list_opt
     2712                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( Type::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    27012713        | identifier_parameter_ptr
    27022714        | identifier_parameter_array attribute_list_opt
     
    27392751//
    27402752//              typedef int foo;
     2753//              forall( otype T ) foo( T );
    27412754//              int f( int foo ); // redefine typedef name in new scope
    27422755//
     
    27462759        typedef attribute_list_opt
    27472760                { $$ = $1->addQualifiers( $2 ); }
     2761        | '&' MUTEX typedef attribute_list_opt
     2762                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( Type::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    27482763        | type_parameter_ptr
    27492764        | type_parameter_array attribute_list_opt
     
    28922907abstract_parameter_declarator:
    28932908        abstract_parameter_ptr
     2909        | '&' MUTEX attribute_list_opt
     2910                { $$ = DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( Type::Mutex ), OperKinds::AddressOf )->addQualifiers( $3 ); }
    28942911        | abstract_parameter_array attribute_list_opt
    28952912                { $$ = $1->addQualifiers( $2 ); }
  • src/ResolvExpr/AdjustExprType.cc

    rb96ec83 r6840e7c  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "SymTab/Indexer.h"       // for Indexer
    1718#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
     
    2122
    2223namespace ResolvExpr {
    23         class AdjustExprType : public Mutator {
    24                 typedef Mutator Parent;
    25                 using Parent::mutate;
     24        class AdjustExprType : public WithShortCircuiting {
    2625          public:
    2726                AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
     27                void premutate( VoidType * ) { visit_children = false; }
     28                void premutate( BasicType * ) { visit_children = false; }
     29                void premutate( PointerType * ) { visit_children = false; }
     30                void premutate( FunctionType * ) { visit_children = false; }
     31                void premutate( StructInstType * ) { visit_children = false; }
     32                void premutate( UnionInstType * ) { visit_children = false; }
     33                void premutate( EnumInstType * ) { visit_children = false; }
     34                void premutate( TraitInstType * ) { visit_children = false; }
     35                void premutate( TypeInstType * ) { visit_children = false; }
     36                void premutate( TupleType * ) { visit_children = false; }
     37                void premutate( VarArgsType * ) { visit_children = false; }
     38                void premutate( ZeroType * ) { visit_children = false; }
     39                void premutate( OneType * ) { visit_children = false; }
     40
     41                Type * postmutate( ArrayType *arrayType );
     42                Type * postmutate( FunctionType *functionType );
     43                Type * postmutate( TypeInstType *aggregateUseType );
     44
    2845          private:
    29                 virtual Type* mutate( VoidType *voidType );
    30                 virtual Type* mutate( BasicType *basicType );
    31                 virtual Type* mutate( PointerType *pointerType );
    32                 virtual Type* mutate( ArrayType *arrayType );
    33                 virtual Type* mutate( FunctionType *functionType );
    34                 virtual Type* mutate( StructInstType *aggregateUseType );
    35                 virtual Type* mutate( UnionInstType *aggregateUseType );
    36                 virtual Type* mutate( EnumInstType *aggregateUseType );
    37                 virtual Type* mutate( TraitInstType *aggregateUseType );
    38                 virtual Type* mutate( TypeInstType *aggregateUseType );
    39                 virtual Type* mutate( TupleType *tupleType );
    40                 virtual Type* mutate( VarArgsType *varArgsType );
    41                 virtual Type* mutate( ZeroType *zeroType );
    42                 virtual Type* mutate( OneType *oneType );
    43 
    4446                const TypeEnvironment &env;
    4547                const SymTab::Indexer &indexer;
     
    4749
    4850        void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    49                 AdjustExprType adjuster( env, indexer );
     51                PassVisitor<AdjustExprType> adjuster( env, indexer );
    5052                Type *newType = type->acceptMutator( adjuster );
    5153                type = newType;
     
    5658        }
    5759
    58         Type *AdjustExprType::mutate( VoidType *voidType ) {
    59                 return voidType;
    60         }
    61 
    62         Type *AdjustExprType::mutate( BasicType *basicType ) {
    63                 return basicType;
    64         }
    65 
    66         Type *AdjustExprType::mutate( PointerType *pointerType ) {
    67                 return pointerType;
    68         }
    69 
    70         Type *AdjustExprType::mutate( ArrayType *arrayType ) {
     60        Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
    7161                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    72                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ) );
     62                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
     63                arrayType->base = nullptr;
    7364                delete arrayType;
    7465                return pointerType;
    7566        }
    7667
    77         Type *AdjustExprType::mutate( FunctionType *functionType ) {
    78                 PointerType *pointerType = new PointerType( Type::Qualifiers(), functionType );
    79                 return pointerType;
     68        Type * AdjustExprType::postmutate( FunctionType * functionType ) {
     69                return new PointerType( Type::Qualifiers(), functionType );
    8070        }
    8171
    82         Type *AdjustExprType::mutate( StructInstType *aggregateUseType ) {
    83                 return aggregateUseType;
    84         }
    85 
    86         Type *AdjustExprType::mutate( UnionInstType *aggregateUseType ) {
    87                 return aggregateUseType;
    88         }
    89 
    90         Type *AdjustExprType::mutate( EnumInstType *aggregateUseType ) {
    91                 return aggregateUseType;
    92         }
    93 
    94         Type *AdjustExprType::mutate( TraitInstType *aggregateUseType ) {
    95                 return aggregateUseType;
    96         }
    97 
    98         Type *AdjustExprType::mutate( TypeInstType *typeInst ) {
     72        Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
    9973                EqvClass eqvClass;
    10074                if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
     
    11387                return typeInst;
    11488        }
    115 
    116         Type *AdjustExprType::mutate( TupleType *tupleType ) {
    117                 return tupleType;
    118         }
    119 
    120         Type *AdjustExprType::mutate( VarArgsType *varArgsType ) {
    121                 return varArgsType;
    122         }
    123 
    124         Type *AdjustExprType::mutate( ZeroType *zeroType ) {
    125                 return zeroType;
    126         }
    127 
    128         Type *AdjustExprType::mutate( OneType *oneType ) {
    129                 return oneType;
    130         }
    13189} // namespace ResolvExpr
    13290
  • src/ResolvExpr/Alternative.cc

    rb96ec83 r6840e7c  
    6666        }
    6767
    68         void Alternative::print( std::ostream &os, int indent ) const {
    69                 os << std::string( indent, ' ' ) << "Cost " << cost << ": ";
     68        void Alternative::print( std::ostream &os, Indenter indent ) const {
     69                os << "Cost " << cost << ": ";
    7070                if ( expr ) {
    71                         expr->print( os, indent );
    72                         os << "(types:" << std::endl;
    73                         os << std::string( indent+4, ' ' );
    74                         expr->get_result()->print( os, indent + 4 );
    75                         os << std::endl << ")" << std::endl;
     71                        expr->print( os, indent+1 );
     72                        os << std::endl << indent << "(types:" << std::endl;
     73                        os << indent+1;
     74                        expr->result->print( os, indent+1 );
     75                        os << std::endl << indent << ")" << std::endl;
    7676                } else {
    7777                        os << "Null expression!" << std::endl;
    7878                } // if
    79                 os << std::string( indent, ' ' ) << "Environment: ";
    80                 env.print( os, indent+2 );
     79                os << indent << "Environment: ";
     80                env.print( os, indent+1 );
    8181                os << std::endl;
    8282        }
  • src/ResolvExpr/Alternative.h

    rb96ec83 r6840e7c  
    3939                ~Alternative();
    4040
    41                 void print( std::ostream &os, int indent = 0 ) const;
     41                void print( std::ostream &os, Indenter indent = {} ) const;
    4242
    4343                Cost cost;
  • src/ResolvExpr/AlternativeFinder.cc

    rb96ec83 r6840e7c  
    7575
    7676        namespace {
    77                 void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
     77                void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ) {
     78                        Indenter indent = { Indenter::tabsize, indentAmt };
    7879                        for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    7980                                i->print( os, indent );
     
    195196                                AltList winners;
    196197                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    197                                 stream << "Cannot choose between " << winners.size() << " alternatives for expression ";
     198                                stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
    198199                                expr->print( stream );
    199                                 stream << "Alternatives are:";
    200                                 printAlts( winners, stream, 8 );
     200                                stream << "Alternatives are:\n";
     201                                printAlts( winners, stream, 1 );
    201202                                throw SemanticError( stream.str() );
    202203                        }
     
    604605                                Alternative newerAlt( newAlt );
    605606                                newerAlt.env = newEnv;
    606                                 assert( (*candidate)->get_uniqueId() );
     607                                assertf( (*candidate)->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( *candidate ).c_str() );
    607608                                DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) );
    608609
     
    728729                PRINT(
    729730                        std::cerr << "known function ops:" << std::endl;
    730                         printAlts( funcOpFinder.alternatives, std::cerr, 8 );
     731                        printAlts( funcOpFinder.alternatives, std::cerr, 1 );
    731732                )
    732733
     
    838839        bool isLvalue( Expression *expr ) {
    839840                // xxx - recurse into tuples?
    840                 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
     841                return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    841842        }
    842843
     
    972973                PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
    973974                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    974                         VariableExpr newExpr( *i, nameExpr->get_argName() );
     975                        VariableExpr newExpr( *i );
    975976                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    976977                        PRINT(
     
    12671268                // O(N^2) checks of d-types with e-types
    12681269                for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
    1269                         Type * toType = resolveTypeof( initAlt.type, indexer );
     1270                        Type * toType = resolveTypeof( initAlt.type->clone(), indexer );
    12701271                        SymTab::validateType( toType, &indexer );
    12711272                        adjustExprType( toType, env, indexer );
  • src/ResolvExpr/CastCost.cc

    rb96ec83 r6840e7c  
    2424#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
    2525
     26#if 0
     27#define PRINT(x) x
     28#else
     29#define PRINT(x)
     30#endif
    2631
    2732namespace ResolvExpr {
     
    5257                        } // if
    5358                } // if
     59
     60                PRINT(
     61                        std::cerr << "castCost ::: src is ";
     62                        src->print( std::cerr );
     63                        std::cerr << std::endl << "dest is ";
     64                        dest->print( std::cerr );
     65                        std::cerr << std::endl << "env is" << std::endl;
     66                        env.print( std::cerr, 8 );
     67                )
     68
    5469                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
     70                        PRINT( std::cerr << "compatible!" << std::endl; )
    5571                        return Cost::zero;
    5672                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    5773                        return Cost::safe;
    5874                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     75                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    5976                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
    6077                                return ptrsCastable( t1, t2, env, indexer );
  • src/ResolvExpr/CommonType.cc

    rb96ec83 r6840e7c  
    1010// Created On       : Sun May 17 06:59:27 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 16:24:31 2017
    13 // Update Count     : 7
     12// Last Modified On : Mon Sep 25 15:18:17 2017
     13// Update Count     : 9
    1414//
    1515
     
    150150        static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
    151151        {
    152 /*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary */
    153                 /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    154                 /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    155                 /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    156                 /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    157                 /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    158                 /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    159                 /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    160                 /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    161                 /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    162                 /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    163                 /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    164                 /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    165                 /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    166                 /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    167                 /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex },
    168                 /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    169                 /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex },
    170                 /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex },
    171                 /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary },
    172                 /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary },
    173                 /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary }
     152/*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128 */
     153                /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     154                /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     155                /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     156                /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     157                /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     158                /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     159                /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     160                /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     161                /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     162                /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     163                /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     164                /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     165                /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, },
     166                /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, },
     167                /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, },
     168                /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, },
     169                /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, },
     170                /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, },
     171                /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, },
     172                /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, },
     173                /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary },
     174                /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
     175                /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, },
    174176        };
    175177
  • src/ResolvExpr/ConversionCost.cc

    rb96ec83 r6840e7c  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:35:46 2016
    13 // Update Count     : 6
     12// Last Modified On : Mon Sep 25 15:43:34 2017
     13// Update Count     : 10
    1414//
    1515
     
    219219*/
    220220
    221         static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
    222         {
    223         /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag */
    224                 /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              10,             11,             12,             11,             12,             13,             -1,             -1,             -1 },
    225                 /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              9,              10,             11,             10,             11,             12,             -1,             -1,             -1 },
    226                 /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              9,              10,             11,             10,             11,             12,             -1,             -1,             -1 },
    227                 /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              8,              9,              10,             9,              10,             11,             -1,             -1,             -1 },
    228                 /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              7,              8,              9,              8,              9,              10,             -1,             -1,             -1 },
    229                 /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              6,              7,              8,              7,              8,              9,              -1,             -1,             -1 },
    230                 /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              5,              6,              7,              6,              7,              8,              -1,             -1,             -1 },
    231                 /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              4,              5,              6,              5,              6,              7,              -1,             -1,             -1 },
    232                 /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              5,              6,              5,              6,              7,              -1,             -1,             -1 },
    233                 /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              5,              4,              5,              6,              -1,             -1,             -1 },
    234                 /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              3,              4,              5,              -1,             -1,             -1 },
    235                 /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              2,              3,              4,              -1,             -1,             -1 },
    236                 /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1 },
    237                 /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1 },
    238                 /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1 },
    239                 /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1 },
    240                 /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1 },
    241                 /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1 },
    242                 /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2 },
    243                 /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1 },
    244                 /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0 }
     221        static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
     222        /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128 */
     223                /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,     },
     224                /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
     225                /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
     226                /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,      },
     227                /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,      },
     228                /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,      },
     229                /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,      },
     230                /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
     231                /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
     232                /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,      },
     233                /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,      },
     234                /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,      },
     235
     236                /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,     },
     237                /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,     },
     238                /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,     },
     239                /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,     },
     240                /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,     },
     241                /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,     },
     242                /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,     },
     243                /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,     },
     244                /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,     },
     245
     246                /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,      },
     247                /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,      },
    245248        };
    246249
     
    303306                // recursively compute conversion cost from T1 to T2.
    304307                // cv can be safely dropped because of 'implicit dereference' behavior.
    305                 refType->get_base()->accept( *this );
    306                 if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
     308                refType->base->accept( *this );
     309                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    307310                        cost.incReference();  // prefer exact qualifiers
    308                 } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
     311                } else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
    309312                        cost.incSafe(); // then gaining qualifiers
    310313                } else {
     
    318321        void ConversionCost::visit(StructInstType *inst) {
    319322                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    320                         if ( inst->get_name() == destAsInst->get_name() ) {
     323                        if ( inst->name == destAsInst->name ) {
    321324                                cost = Cost::zero;
    322325                        } // if
     
    325328
    326329        void ConversionCost::visit(UnionInstType *inst) {
    327                 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    328                         if ( inst->get_name() == destAsInst->get_name() ) {
     330                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
     331                        if ( inst->name == destAsInst->name ) {
    329332                                cost = Cost::zero;
    330333                        } // if
  • src/ResolvExpr/ResolveTypeof.cc

    rb96ec83 r6840e7c  
    1818#include <cassert>               // for assert
    1919
     20#include "Common/PassVisitor.h"  // for PassVisitor
    2021#include "Resolver.h"            // for resolveInVoidContext
    2122#include "SynTree/Expression.h"  // for Expression
     
    4142        }
    4243
    43         class ResolveTypeof : public Mutator {
     44        class ResolveTypeof : public WithShortCircuiting {
    4445          public:
    4546                ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    46                 Type *mutate( TypeofType *typeofType );
     47                void premutate( TypeofType *typeofType );
     48                Type * postmutate( TypeofType *typeofType );
    4749
    4850          private:
     
    5052        };
    5153
    52         Type *resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    53                 ResolveTypeof mutator( indexer );
     54        Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
     55                PassVisitor<ResolveTypeof> mutator( indexer );
    5456                return type->acceptMutator( mutator );
    5557        }
    5658
    57         Type *ResolveTypeof::mutate( TypeofType *typeofType ) {
     59        void ResolveTypeof::premutate( TypeofType * ) {
     60                visit_children = false;
     61        }
     62
     63        Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
    5864#if 0
    59                 std::cout << "resolving typeof: ";
    60                 typeofType->print( std::cout );
    61                 std::cout << std::endl;
     65                std::cerr << "resolving typeof: ";
     66                typeofType->print( std::cerr );
     67                std::cerr << std::endl;
    6268#endif
    63                 if ( typeofType->get_expr() ) {
    64                         Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
    65                         assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
    66                         Type *newType = newExpr->get_result();
    67                         newExpr->set_result( nullptr );
     69                if ( typeofType->expr ) {
     70                        Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
     71                        assert( newExpr->result && ! newExpr->result->isVoid() );
     72                        Type * newType = newExpr->result;
     73                        newExpr->result = nullptr;
    6874                        delete typeofType;
    6975                        delete newExpr;
  • src/ResolvExpr/Resolver.cc

    rb96ec83 r6840e7c  
    5353                void previsit( FunctionDecl *functionDecl );
    5454                void postvisit( FunctionDecl *functionDecl );
    55                 void previsit( ObjectDecl *functionDecl );
     55                void previsit( ObjectDecl *objectDecll );
    5656                void previsit( TypeDecl *typeDecl );
    5757                void previsit( EnumDecl * enumDecl );
     
    109109
    110110        namespace {
    111                 void finishExpr( Expression *expr, const TypeEnvironment &env ) {
    112                         expr->set_env( new TypeSubstitution );
     111                void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
     112                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    113113                        env.makeSubstitution( *expr->get_env() );
    114114                }
     115
     116                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
     117                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     118                                if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     119                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
     120                                        expr = castExpr->arg;
     121                                        castExpr->arg = nullptr;
     122                                        std::swap( expr->env, castExpr->env );
     123                                        delete castExpr;
     124                                }
     125                        }
     126                }
    115127        } // namespace
    116128
    117         Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     129        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    118130                global_renamer.reset();
    119131                TypeEnvironment env;
    120132                Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
    121                 finishExpr( newExpr, env );
    122                 return newExpr;
    123         }
    124 
    125         Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     133                finishExpr( newExpr, env, untyped->env );
     134                delete untyped;
     135                untyped = newExpr;
     136        }
     137
     138        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
     139                if ( ! untyped ) return;
    126140                TypeEnvironment env;
    127141                AlternativeFinder finder( indexer, env );
     
    129143                #if 0
    130144                if ( finder.get_alternatives().size() != 1 ) {
    131                         std::cout << "untyped expr is ";
    132                         untyped->print( std::cout );
    133                         std::cout << std::endl << "alternatives are:";
    134                         for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    135                                 i->print( std::cout );
     145                        std::cerr << "untyped expr is ";
     146                        untyped->print( std::cerr );
     147                        std::cerr << std::endl << "alternatives are:";
     148                        for ( const Alternative & alt : finder.get_alternatives() ) {
     149                                alt.print( std::cerr );
    136150                        } // for
    137151                } // if
     
    140154                Alternative &choice = finder.get_alternatives().front();
    141155                Expression *newExpr = choice.expr->clone();
    142                 finishExpr( newExpr, choice.env );
    143                 return newExpr;
     156                finishExpr( newExpr, choice.env, untyped->env );
     157                delete untyped;
     158                untyped = newExpr;
     159        }
     160
     161        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
     162                assert( untyped && type );
     163                untyped = new CastExpr( untyped, type );
     164                findSingleExpression( untyped, indexer );
     165                removeExtraneousCast( untyped, indexer );
    144166        }
    145167
     
    157179                }
    158180
    159                 Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     181                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    160182                        TypeEnvironment env;
    161183                        AlternativeFinder finder( indexer, env );
     
    186208                                throw SemanticError( "No interpretations for case control expression", untyped );
    187209                        } // if
    188                         finishExpr( newExpr, *newEnv );
    189                         return newExpr;
     210                        finishExpr( newExpr, *newEnv, untyped->env );
     211                        delete untyped;
     212                        untyped = newExpr;
    190213                }
    191214
     
    212235        void Resolver::handlePtrType( PtrType * type ) {
    213236                if ( type->get_dimension() ) {
    214                         CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
    215                         Expression *newExpr = findSingleExpression( castExpr, indexer );
    216                         delete type->get_dimension();
    217                         type->set_dimension( newExpr );
     237                        findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
    218238                }
    219239        }
     
    245265                functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
    246266        }
    247 
    248267
    249268        void Resolver::postvisit( FunctionDecl *functionDecl ) {
     
    269288        void Resolver::previsit( ExprStmt *exprStmt ) {
    270289                visit_children = false;
    271                 assertf( exprStmt->get_expr(), "ExprStmt has null Expression in resolver" );
    272                 Expression *newExpr = findVoidExpression( exprStmt->get_expr(), indexer );
    273                 delete exprStmt->get_expr();
    274                 exprStmt->set_expr( newExpr );
     290                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     291                findVoidExpression( exprStmt->expr, indexer );
    275292        }
    276293
    277294        void Resolver::previsit( AsmExpr *asmExpr ) {
    278295                visit_children = false;
    279                 Expression *newExpr = findVoidExpression( asmExpr->get_operand(), indexer );
    280                 delete asmExpr->get_operand();
    281                 asmExpr->set_operand( newExpr );
     296                findVoidExpression( asmExpr->operand, indexer );
    282297                if ( asmExpr->get_inout() ) {
    283                         newExpr = findVoidExpression( asmExpr->get_inout(), indexer );
    284                         delete asmExpr->get_inout();
    285                         asmExpr->set_inout( newExpr );
     298                        findVoidExpression( asmExpr->inout, indexer );
    286299                } // if
    287300        }
     
    294307
    295308        void Resolver::previsit( IfStmt *ifStmt ) {
    296                 Expression *newExpr = findSingleExpression( ifStmt->get_condition(), indexer );
    297                 delete ifStmt->get_condition();
    298                 ifStmt->set_condition( newExpr );
     309                findSingleExpression( ifStmt->condition, indexer );
    299310        }
    300311
    301312        void Resolver::previsit( WhileStmt *whileStmt ) {
    302                 Expression *newExpr = findSingleExpression( whileStmt->get_condition(), indexer );
    303                 delete whileStmt->get_condition();
    304                 whileStmt->set_condition( newExpr );
     313                findSingleExpression( whileStmt->condition, indexer );
    305314        }
    306315
    307316        void Resolver::previsit( ForStmt *forStmt ) {
    308                 if ( forStmt->get_condition() ) {
    309                         Expression * newExpr = findSingleExpression( forStmt->get_condition(), indexer );
    310                         delete forStmt->get_condition();
    311                         forStmt->set_condition( newExpr );
     317                if ( forStmt->condition ) {
     318                        findSingleExpression( forStmt->condition, indexer );
    312319                } // if
    313320
    314                 if ( forStmt->get_increment() ) {
    315                         Expression * newExpr = findVoidExpression( forStmt->get_increment(), indexer );
    316                         delete forStmt->get_increment();
    317                         forStmt->set_increment( newExpr );
     321                if ( forStmt->increment ) {
     322                        findVoidExpression( forStmt->increment, indexer );
    318323                } // if
    319324        }
     
    321326        void Resolver::previsit( SwitchStmt *switchStmt ) {
    322327                GuardValue( currentObject );
    323                 Expression *newExpr;
    324                 newExpr = findIntegralExpression( switchStmt->get_condition(), indexer );
    325                 delete switchStmt->get_condition();
    326                 switchStmt->set_condition( newExpr );
    327 
    328                 currentObject = CurrentObject( newExpr->get_result() );
     328                findIntegralExpression( switchStmt->condition, indexer );
     329
     330                currentObject = CurrentObject( switchStmt->condition->result );
    329331        }
    330332
     
    333335                        std::list< InitAlternative > initAlts = currentObject.getOptions();
    334336                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
    335                         CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() );
    336                         Expression * newExpr = findSingleExpression( castExpr, indexer );
    337                         castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
    338                         caseStmt->set_condition( castExpr->get_arg() );
    339                         castExpr->set_arg( nullptr );
     337                        // must remove cast from case statement because RangeExpr cannot be cast.
     338                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
     339                        findSingleExpression( newExpr, indexer );
     340                        CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
     341                        caseStmt->condition = castExpr->arg;
     342                        castExpr->arg = nullptr;
    340343                        delete castExpr;
    341344                }
     
    346349                // must resolve the argument for a computed goto
    347350                if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
    348                         if ( Expression * arg = branchStmt->get_computedTarget() ) {
    349                                 VoidType v = Type::Qualifiers();                // cast to void * for the alternative finder
    350                                 PointerType pt( Type::Qualifiers(), v.clone() );
    351                                 CastExpr * castExpr = new CastExpr( arg, pt.clone() );
    352                                 Expression * newExpr = findSingleExpression( castExpr, indexer ); // find best expression
    353                                 branchStmt->set_target( newExpr );
     351                        if ( branchStmt->computedTarget ) {
     352                                // computed goto argument is void *
     353                                findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
    354354                        } // if
    355355                } // if
     
    358358        void Resolver::previsit( ReturnStmt *returnStmt ) {
    359359                visit_children = false;
    360                 if ( returnStmt->get_expr() ) {
    361                         CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() );
    362                         Expression *newExpr = findSingleExpression( castExpr, indexer );
    363                         delete castExpr;
    364                         returnStmt->set_expr( newExpr );
     360                if ( returnStmt->expr ) {
     361                        findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
    365362                } // if
    366363        }
     
    373370                                indexer.lookupStruct( "__cfaehm__base_exception_t" );
    374371                        assert( exception_decl );
    375                         Expression * wrapped = new CastExpr(
    376                                 throwStmt->get_expr(),
    377                                 new PointerType(
    378                                         noQualifiers,
    379                                         new StructInstType(
    380                                                 noQualifiers,
    381                                                 exception_decl
    382                                                 )
    383                                         )
    384                                 );
    385                         Expression * newExpr = findSingleExpression( wrapped, indexer );
    386                         throwStmt->set_expr( newExpr );
     372                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
     373                        findSingleExpression( throwStmt->expr, exceptType, indexer );
    387374                }
    388375        }
    389376
    390377        void Resolver::previsit( CatchStmt *catchStmt ) {
    391                 if ( catchStmt->get_cond() ) {
    392                         Expression * wrapped = new CastExpr(
    393                                 catchStmt->get_cond(),
    394                                 new BasicType( noQualifiers, BasicType::Bool )
    395                                 );
    396                         catchStmt->set_cond( findSingleExpression( wrapped, indexer ) );
    397                 }
    398         }
    399 
    400         inline void resolveAsIf( Expression *& expr, SymTab::Indexer & indexer ) {
    401                 if( !expr ) return;
    402                 Expression * newExpr = findSingleExpression( expr, indexer );
    403                 delete expr;
    404                 expr = newExpr;
    405         }
    406 
    407         inline void resolveAsType( Expression *& expr, Type * type, SymTab::Indexer & indexer ) {
    408                 if( !expr ) return;
    409                 Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), indexer );
    410                 delete expr;
    411                 expr = newExpr;
     378                if ( catchStmt->cond ) {
     379                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     380                }
    412381        }
    413382
     
    579548                        // Resolve the conditions as if it were an IfStmt
    580549                        // Resolve the statments normally
    581                         resolveAsIf( clause.condition, this->indexer );
     550                        findSingleExpression( clause.condition, this->indexer );
    582551                        clause.statement->accept( *visitor );
    583552                }
     
    588557                        // Resolve the conditions as if it were an IfStmt
    589558                        // Resolve the statments normally
    590                         resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
    591                         resolveAsIf  ( stmt->timeout.condition, this->indexer );
     559                        findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
     560                        findSingleExpression( stmt->timeout.condition, this->indexer );
    592561                        stmt->timeout.statement->accept( *visitor );
    593562                }
     
    596565                        // Resolve the conditions as if it were an IfStmt
    597566                        // Resolve the statments normally
    598                         resolveAsIf( stmt->orelse.condition, this->indexer );
     567                        findSingleExpression( stmt->orelse.condition, this->indexer );
    599568                        stmt->orelse.statement->accept( *visitor );
    600569                }
     
    613582                visit_children = false;
    614583                // resolve initialization using the possibilities as determined by the currentObject cursor
    615                 UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() );
    616                 Expression * newExpr = findSingleExpression( untyped, indexer );
     584                Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
     585                findSingleExpression( newExpr, indexer );
    617586                InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
    618587
     
    621590
    622591                // discard InitExpr wrapper and retain relevant pieces
    623                 newExpr = initExpr->get_expr();
    624                 newExpr->set_env( initExpr->get_env() );
    625                 initExpr->set_expr( nullptr );
    626                 initExpr->set_env( nullptr );
     592                newExpr = initExpr->expr;
     593                initExpr->expr = nullptr;
     594                std::swap( initExpr->env, newExpr->env );
    627595                delete initExpr;
    628596
    629597                // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
    630598                Type * initContext = currentObject.getCurrentType();
     599
     600                removeExtraneousCast( newExpr, indexer );
    631601
    632602                // check if actual object's type is char[]
     
    636606                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    637607                                        if ( isCharType( pt->get_base() ) ) {
    638                                                 // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
    639                                                 CastExpr *ce = strict_dynamic_cast< CastExpr * >( newExpr );
    640                                                 newExpr = ce->get_arg();
    641                                                 ce->set_arg( nullptr );
    642                                                 delete ce;
     608                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
     609                                                        // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     610                                                        newExpr = ce->get_arg();
     611                                                        ce->set_arg( nullptr );
     612                                                        std::swap( ce->env, newExpr->env );
     613                                                        delete ce;
     614                                                }
    643615                                        }
    644616                                }
     
    647619
    648620                // set initializer expr to resolved express
    649                 singleInit->set_value( newExpr );
     621                singleInit->value = newExpr;
    650622
    651623                // move cursor to next object in preparation for next initializer
  • src/ResolvExpr/Resolver.h

    rb96ec83 r6840e7c  
    3030        void resolve( std::list< Declaration * > translationUnit );
    3131        void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
    32         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    33         Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
    34         Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer );
     32        Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer );
     33        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer );
     34        void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer );
    3535        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3636        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
  • src/ResolvExpr/TypeEnvironment.cc

    rb96ec83 r6840e7c  
    6868        }
    6969
    70         void EqvClass::print( std::ostream &os, int indent ) const {
    71                 os << std::string( indent, ' ' ) << "( ";
     70        void EqvClass::print( std::ostream &os, Indenter indent ) const {
     71                os << "( ";
    7272                std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );
    7373                os << ")";
    7474                if ( type ) {
    7575                        os << " -> ";
    76                         type->print( os, indent );
     76                        type->print( os, indent+1 );
    7777                } // if
    7878                if ( ! allowWidening ) {
     
    144144        }
    145145
    146         void TypeEnvironment::print( std::ostream &os, int indent ) const {
     146        void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
    147147                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    148148                        i->print( os, indent );
  • src/ResolvExpr/TypeEnvironment.h

    rb96ec83 r6840e7c  
    6868                EqvClass &operator=( const EqvClass &other );
    6969                ~EqvClass();
    70                 void print( std::ostream &os, int indent = 0 ) const;
     70                void print( std::ostream &os, Indenter indent = {} ) const;
    7171        };
    7272
     
    8080                void makeSubstitution( TypeSubstitution &result ) const;
    8181                bool isEmpty() const { return env.empty(); }
    82                 void print( std::ostream &os, int indent = 0 ) const;
     82                void print( std::ostream &os, Indenter indent = {} ) const;
    8383                void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
    8484                void simpleCombine( const TypeEnvironment &second );
  • src/ResolvExpr/Unify.cc

    rb96ec83 r6840e7c  
    2222#include <utility>                // for pair
    2323
     24#include "Common/PassVisitor.h"   // for PassVisitor
    2425#include "FindOpenVars.h"         // for findOpenVars
    2526#include "Parser/LinkageSpec.h"   // for C
     
    537538        /// If this isn't done then argument lists can have wildly different
    538539        /// size and structure, when they should be compatible.
    539         struct TtypeExpander : public Mutator {
    540                 TypeEnvironment & env;
    541                 TtypeExpander( TypeEnvironment & env ) : env( env ) {}
    542                 Type * mutate( TypeInstType * typeInst ) {
     540        struct TtypeExpander : public WithShortCircuiting {
     541                TypeEnvironment & tenv;
     542                TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
     543                void premutate( TypeInstType * ) { visit_children = false; }
     544                Type * postmutate( TypeInstType * typeInst ) {
    543545                        EqvClass eqvClass;
    544                         if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
     546                        if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
    545547                                if ( eqvClass.data.kind == TypeDecl::Ttype ) {
    546548                                        // expand ttype parameter into its actual type
     
    560562                dst.clear();
    561563                for ( DeclarationWithType * dcl : src ) {
    562                         TtypeExpander expander( env );
     564                        PassVisitor<TtypeExpander> expander( env );
    563565                        dcl->acceptMutator( expander );
    564566                        std::list< Type * > types;
     
    750752                        std::list<Type *> types1, types2;
    751753
    752                         TtypeExpander expander( env );
     754                        PassVisitor<TtypeExpander> expander( env );
    753755                        flat1->acceptMutator( expander );
    754756                        flat2->acceptMutator( expander );
  • src/SymTab/Autogen.cc

    rb96ec83 r6840e7c  
    4343namespace SymTab {
    4444        Type * SizeType = 0;
    45         typedef ScopedMap< std::string, bool > TypeMap;
    46 
    47         /// Data used to generate functions generically. Specifically, the name of the generated function, a function which generates the routine protoype, and a map which contains data to determine whether a function should be generated.
     45
     46        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4847        struct FuncData {
    4948                typedef FunctionType * (*TypeGen)( Type * );
    50                 FuncData( const std::string & fname, const TypeGen & genType, TypeMap & map ) : fname( fname ), genType( genType ), map( map ) {}
     49                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    5150                std::string fname;
    5251                TypeGen genType;
    53                 TypeMap & map;
    54         };
    55 
    56         struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting {
     52        };
     53
     54        struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting, public WithIndexer {
    5755                AutogenerateRoutines();
    5856
     
    7068
    7169          private:
     70
    7271                GenPoly::ScopedSet< std::string > structsDone;
    7372                unsigned int functionNesting = 0;     // current level of nested functions
    74                 /// Note: the following maps could be ScopedSets, but it should be easier to work
    75                 /// deleted functions in if they are maps, since the value false can be inserted
    76                 /// at the current scope without affecting outer scopes or requiring copies.
    77                 TypeMap copyable, assignable, constructable, destructable;
     73
     74                InitTweak::ManagedTypes managedTypes;
    7875                std::vector< FuncData > data;
    7976        };
     
    8178        /// generates routines for tuple types.
    8279        struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting {
    83                 void previsit( FunctionDecl *functionDecl );
    84 
    85                 void postvisit( TupleType *tupleType );
    86 
    87                 void previsit( CompoundStmt *compoundStmt );
     80                void previsit( FunctionDecl * functionDecl );
     81
     82                void postvisit( TupleType * tupleType );
     83
     84                void previsit( CompoundStmt * compoundStmt );
    8885
    8986          private:
     
    10198        }
    10299
     100        //=============================================================================================
     101        // FuncGenerator definitions
     102        //=============================================================================================
     103        class FuncGenerator {
     104        public:
     105                std::list< Declaration * > definitions, forwards;
     106
     107                FuncGenerator( Type * type, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : type( type ), data( data ), functionNesting( functionNesting ), indexer( indexer ) {}
     108
     109                virtual bool shouldAutogen() const = 0;
     110                void genStandardFuncs();
     111                virtual void genFieldCtors() = 0;
     112        protected:
     113                Type * type;
     114                const std::vector< FuncData > & data;
     115                unsigned int functionNesting;
     116                SymTab::Indexer & indexer;
     117
     118                virtual void genFuncBody( FunctionDecl * dcl ) = 0;
     119                virtual bool isConcurrentType() const = 0;
     120
     121                void resolve( FunctionDecl * dcl );
     122                void generatePrototypes( std::list< FunctionDecl * > & newFuncs );
     123        };
     124
     125        class StructFuncGenerator : public FuncGenerator {
     126                StructDecl * aggregateDecl;
     127        public:
     128                StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {}
     129
     130                virtual bool shouldAutogen() const override;
     131                virtual bool isConcurrentType() const override;
     132
     133                virtual void genFuncBody( FunctionDecl * dcl ) override;
     134                virtual void genFieldCtors() override;
     135
     136        private:
     137                /// generates a single struct member operation (constructor call, destructor call, assignment call)
     138                void makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true );
     139
     140                /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
     141                template<typename Iterator>
     142                void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true );
     143
     144                /// generate the body of a constructor which takes parameters that match fields, e.g.
     145                /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
     146                template<typename Iterator>
     147                void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func );
     148        };
     149
     150        class UnionFuncGenerator : public FuncGenerator {
     151                UnionDecl * aggregateDecl;
     152        public:
     153                UnionFuncGenerator( UnionDecl * aggregateDecl, UnionInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {}
     154
     155                virtual bool shouldAutogen() const override;
     156                virtual bool isConcurrentType() const override;
     157
     158                virtual void genFuncBody( FunctionDecl * dcl ) override;
     159                virtual void genFieldCtors() override;
     160
     161        private:
     162                /// generates a single struct member operation (constructor call, destructor call, assignment call)
     163                template<typename OutputIterator>
     164                void makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out );
     165
     166                /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
     167                template<typename Iterator>
     168                void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true );
     169
     170                /// generate the body of a constructor which takes parameters that match fields, e.g.
     171                /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
     172                template<typename Iterator>
     173                void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func );
     174        };
     175
     176        class EnumFuncGenerator : public FuncGenerator {
     177        public:
     178                EnumFuncGenerator( EnumInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ) {}
     179
     180                virtual bool shouldAutogen() const override;
     181                virtual bool isConcurrentType() const override;
     182
     183                virtual void genFuncBody( FunctionDecl * dcl ) override;
     184                virtual void genFieldCtors() override;
     185
     186        private:
     187        };
     188
     189        class TypeFuncGenerator : public FuncGenerator {
     190                TypeDecl * typeDecl;
     191        public:
     192                TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, const std::vector<FuncData> & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), typeDecl( typeDecl ) {}
     193
     194                virtual bool shouldAutogen() const override;
     195                virtual void genFuncBody( FunctionDecl * dcl ) override;
     196                virtual bool isConcurrentType() const override;
     197                virtual void genFieldCtors() override;
     198        };
     199
     200        //=============================================================================================
     201        // helper functions
     202        //=============================================================================================
     203        void generateFunctions( FuncGenerator & gen, std::list< Declaration * > & declsToAdd ) {
     204                if ( ! gen.shouldAutogen() ) return;
     205
     206                // generate each of the functions based on the supplied FuncData objects
     207                gen.genStandardFuncs();
     208                gen.genFieldCtors();
     209
     210                declsToAdd.splice( declsToAdd.end(), gen.forwards );
     211                declsToAdd.splice( declsToAdd.end(), gen.definitions );
     212        }
     213
    103214        bool isUnnamedBitfield( ObjectDecl * obj ) {
    104                 return obj != nullptr && obj->get_name() == "" && obj->get_bitfieldWidth() != nullptr;
     215                return obj != nullptr && obj->name == "" && obj->bitfieldWidth != nullptr;
    105216        }
    106217
     
    108219        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
    109220                FunctionDecl * decl = functionDecl->clone();
    110                 delete decl->get_statements();
    111                 decl->set_statements( nullptr );
     221                delete decl->statements;
     222                decl->statements = nullptr;
    112223                declsToAdd.push_back( decl );
    113224                decl->fixUniqueId();
    114225        }
    115226
     227        const std::list< TypeDecl * > getGenericParams( Type * t ) {
     228                std::list< TypeDecl * > * ret = nullptr;
     229                if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) {
     230                        ret = inst->get_baseParameters();
     231                } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     232                        ret = inst->get_baseParameters();
     233                }
     234                return ret ? *ret : std::list< TypeDecl * >();
     235        }
     236
    116237        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    117238        FunctionType * genDefaultType( Type * paramType ) {
     239                const auto & typeParams = getGenericParams( paramType );
    118240                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
     241                cloneAll( typeParams, ftype->forall );
    119242                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    120                 ftype->get_parameters().push_back( dstParam );
     243                ftype->parameters.push_back( dstParam );
    121244                return ftype;
    122245        }
     
    126249                FunctionType *ftype = genDefaultType( paramType );
    127250                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    128                 ftype->get_parameters().push_back( srcParam );
     251                ftype->parameters.push_back( srcParam );
    129252                return ftype;
    130253        }
     
    134257                FunctionType *ftype = genCopyType( paramType );
    135258                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    136                 ftype->get_returnVals().push_back( returnVal );
     259                ftype->returnVals.push_back( returnVal );
    137260                return ftype;
    138261        }
     
    151274        }
    152275
    153         /// inserts base type of first argument into map if pred(funcDecl) is true
    154         void insert( FunctionDecl *funcDecl, TypeMap & map, FunctionDecl * (*pred)(Declaration *) ) {
    155                 // insert type into constructable, etc. map if appropriate
    156                 if ( pred( funcDecl ) ) {
    157                         FunctionType * ftype = funcDecl->get_functionType();
    158                         assert( ! ftype->get_parameters().empty() );
    159                         Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );
    160                         assert( t );
    161                         map.insert( Mangler::mangleType( t ), true );
    162                 }
    163         }
    164 
    165         /// using map and t, determines if is constructable, etc.
    166         bool lookup( const TypeMap & map, Type * t ) {
    167                 assertf( t, "Autogenerate lookup was given non-type: %s", toString( t ).c_str() );
    168                 if ( dynamic_cast< PointerType * >( t ) ) {
    169                         // will need more complicated checking if we want this to work with pointer types, since currently
    170                         return true;
    171                 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {
    172                         // an array's constructor, etc. is generated on the fly based on the base type's constructor, etc.
    173                         return lookup( map, at->get_base() );
    174                 }
    175                 TypeMap::const_iterator it = map.find( Mangler::mangleType( t ) );
    176                 if ( it != map.end() ) return it->second;
    177                 // something that does not appear in the map is by default not constructable, etc.
    178                 return false;
    179         }
    180 
    181         /// using map and aggr, examines each member to determine if constructor, etc. should be generated
    182         template<typename Container>
    183         bool shouldGenerate( const TypeMap & map, const Container & container ) {
    184                 for ( Type * t : container ) {
    185                         if ( ! lookup( map, t ) ) return false;
    186                 }
    187                 return true;
    188         }
    189 
    190         /// data structure for abstracting the generation of special functions
    191         template< typename OutputIterator, typename Container >
    192         struct FuncGenerator {
    193                 const Container & container;
    194                 Type *refType;
    195                 unsigned int functionNesting;
    196                 const std::list< TypeDecl* > & typeParams;
    197                 OutputIterator out;
    198                 FuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) : container( container ), refType( refType ), functionNesting( functionNesting ), typeParams( typeParams ), out( out ) {}
    199 
    200                 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map.
    201                 void gen( const FuncData & data, bool concurrent_type ) {
    202                         if ( ! shouldGenerate( data.map, container ) ) return;
    203                         FunctionType * ftype = data.genType( refType );
    204 
     276        Type * declToType( Declaration * decl ) {
     277                if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
     278                        return dwt->get_type();
     279                }
     280                return nullptr;
     281        }
     282
     283        Type * declToTypeDeclBase( Declaration * decl ) {
     284                if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {
     285                        return td->base;
     286                }
     287                return nullptr;
     288        }
     289
     290        //=============================================================================================
     291        // FuncGenerator member definitions
     292        //=============================================================================================
     293        void FuncGenerator::genStandardFuncs() {
     294                std::list< FunctionDecl * > newFuncs;
     295                generatePrototypes( newFuncs );
     296
     297                for ( FunctionDecl * dcl : newFuncs ) {
     298                        genFuncBody( dcl );
     299                        if ( CodeGen::isAssignment( dcl->name ) ) {
     300                                // assignment needs to return a value
     301                                FunctionType * assignType = dcl->type;
     302                                assert( assignType->parameters.size() == 2 );
     303                                assert( assignType->returnVals.size() == 1 );
     304                                ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.front() );
     305                                dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( dstParam ) ) );
     306                        }
     307                        resolve( dcl );
     308                }
     309        }
     310
     311        void FuncGenerator::generatePrototypes( std::list< FunctionDecl * > & newFuncs ) {
     312                bool concurrent_type = isConcurrentType();
     313                for ( const FuncData & data : data ) {
     314                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
     315                        FunctionType * ftype = data.genType( type );
     316
     317                        // destructor for concurrent type must be mutex
    205318                        if ( concurrent_type && CodeGen::isDestructor( data.fname ) ) {
    206319                                ftype->parameters.front()->get_type()->set_mutex( true );
    207320                        }
    208321
    209                         cloneAll( typeParams, ftype->forall );
    210                         *out++ = genFunc( data.fname, ftype, functionNesting );
    211                         data.map.insert( Mangler::mangleType( refType ), true );
    212                 }
    213         };
    214 
    215         template< typename OutputIterator, typename Container >
    216         FuncGenerator<OutputIterator, Container> makeFuncGenerator( const Container & container, Type *refType, unsigned int functionNesting, const std::list< TypeDecl* > & typeParams, OutputIterator out ) {
    217                 return FuncGenerator<OutputIterator, Container>( container, refType, functionNesting, typeParams, out );
    218         }
    219 
    220         /// generates a single enumeration assignment expression
    221         ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) {
    222                 // enum copy construct and assignment is just C-style assignment.
    223                 // this looks like a bad recursive call, but code gen will turn it into
    224                 // a C-style assignment.
    225                 // This happens before function pointer type conversion, so need to do it manually here
    226                 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the
    227                 // type of the function that this expression is being generated for (so that the correct
    228                 // parameters) are using in the variable exprs
    229                 assert( ftype->get_parameters().size() == 2 );
    230                 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    231                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    232 
    233                 VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
    234                 Type * assignVarExprType = assignVarExpr->get_result();
    235                 assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType );
    236                 assignVarExpr->set_result( assignVarExprType );
    237                 ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr );
    238                 assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
    239                 assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
    240                 return assignExpr;
    241         }
    242 
    243         // E ?=?(E volatile*, int),
    244         //   ?=?(E _Atomic volatile*, int);
    245         void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    246 
    247                 // T ?=?(E *, E);
    248                 FunctionType *assignType = genAssignType( refType );
    249 
    250                 // void ?{}(E *); void ^?{}(E *);
    251                 FunctionType * ctorType = genDefaultType( refType->clone() );
    252                 FunctionType * dtorType = genDefaultType( refType->clone() );
    253 
    254                 // void ?{}(E *, E);
    255                 FunctionType *copyCtorType = genCopyType( refType->clone() );
    256 
    257                 // add unused attribute to parameters of default constructor and destructor
    258                 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    259                 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    260 
    261                 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    262                 // right now these cases work, but that might change.
    263 
    264                 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
    265                 // Really they're something of a cross between instrinsic and autogen, so should
    266                 // probably make a new linkage type
    267                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true );
    268                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true );
    269                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true );
    270                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true );
    271 
    272                 // body is either return stmt or expr stmt
    273                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) );
    274                 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) );
    275 
    276                 declsToAdd.push_back( ctorDecl );
    277                 declsToAdd.push_back( copyCtorDecl );
    278                 declsToAdd.push_back( dtorDecl );
    279                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    280         }
    281 
    282         /// generates a single struct member operation (constructor call, destructor call, assignment call)
    283         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) {
     322                        newFuncs.push_back( genFunc( data.fname, ftype, functionNesting ) );
     323                }
     324        }
     325
     326        void FuncGenerator::resolve( FunctionDecl * dcl ) {
     327                try {
     328                        ResolvExpr::resolveDecl( dcl, indexer );
     329                        if ( functionNesting == 0 ) {
     330                                // forward declare if top-level struct, so that
     331                                // type is complete as soon as its body ends
     332                                // Note: this is necessary if we want structs which contain
     333                                // generic (otype) structs as members.
     334                                addForwardDecl( dcl, forwards );
     335                        }
     336                        definitions.push_back( dcl );
     337                        indexer.addId( dcl );
     338                } catch ( SemanticError err ) {
     339                        // okay if decl does not resolve - that means the function should not be generated
     340                        delete dcl;
     341                }
     342        }
     343
     344        bool StructFuncGenerator::shouldAutogen() const {
     345                // Builtins do not use autogeneration.
     346                return ! aggregateDecl->linkage.is_builtin;
     347        }
     348        bool StructFuncGenerator::isConcurrentType() const { return aggregateDecl->is_thread() || aggregateDecl->is_monitor(); }
     349
     350        void StructFuncGenerator::genFuncBody( FunctionDecl * dcl ) {
     351                // generate appropriate calls to member ctor, assignment
     352                // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
     353                if ( ! CodeGen::isDestructor( dcl->name ) ) {
     354                        makeFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl );
     355                } else {
     356                        makeFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false );
     357                }
     358        }
     359
     360        void StructFuncGenerator::genFieldCtors() {
     361                // field ctors are only generated if default constructor and copy constructor are both generated
     362                unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->name ); } );
     363
     364                // Field constructors are only generated if default and copy constructor
     365                // are generated, since they need access to both
     366                if ( numCtors != 2 ) return;
     367
     368                // create constructors which take each member type as a parameter.
     369                // for example, for struct A { int x, y; }; generate
     370                //   void ?{}(A *, int) and void ?{}(A *, int, int)
     371                FunctionType * memCtorType = genDefaultType( type );
     372                for ( Declaration * member : aggregateDecl->members ) {
     373                        DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member );
     374                        if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
     375                                // don't make a function whose parameter is an unnamed bitfield
     376                                continue;
     377                        }
     378                        memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) );
     379                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
     380                        makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor );
     381                        resolve( ctor );
     382                }
     383                delete memCtorType;
     384        }
     385
     386        void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
    284387                InitTweak::InitExpander srcParam( src );
    285388
    286389                // assign to destination
    287                 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) );
    288                 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    289         }
    290 
    291         /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
     390                Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->base->clone() ) );
     391                genImplicitCall( srcParam, dstselect, func->name, back_inserter( func->statements->kids ), field, forward );
     392        }
     393
    292394        template<typename Iterator>
    293         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ) {
     395        void StructFuncGenerator::makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward ) {
    294396                for ( ; member != end; ++member ) {
    295397                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    301403                                }
    302404
    303                                 if ( type->get_const() && func->get_name() == "?=?" ) {
     405                                if ( type->get_const() && CodeGen::isAssignment( func->name ) ) {
    304406                                        // don't assign const members, but do construct/destruct
    305                                         continue;
    306                                 }
    307 
    308                                 if ( field->get_name() == "" ) {
    309                                         // don't assign to anonymous members
    310                                         // xxx - this is a temporary fix. Anonymous members tie into
    311                                         // our inheritance model. I think the correct way to handle this is to
    312                                         // cast the structure to the type of the member and let the resolver
    313                                         // figure out whether it's valid and have a pass afterwards that fixes
    314                                         // the assignment to use pointer arithmetic with the offset of the
    315                                         // member, much like how generic type members are handled.
    316407                                        continue;
    317408                                }
     
    323414                                        srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
    324415                                }
     416
    325417                                // srcParam may be NULL, in which case we have default ctor/dtor
    326418                                assert( dstParam );
    327419
    328420                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr;
    329                                 makeStructMemberOp( dstParam, srcselect, field, func, forward );
     421                                makeMemberOp( dstParam, srcselect, field, func, forward );
    330422                        } // if
    331423                } // for
    332         } // makeStructFunctionBody
    333 
    334         /// generate the body of a constructor which takes parameters that match fields, e.g.
    335         /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
     424        } // makeFunctionBody
     425
    336426        template<typename Iterator>
    337         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
    338                 FunctionType * ftype = func->get_functionType();
    339                 std::list<DeclarationWithType*> & params = ftype->get_parameters();
     427        void StructFuncGenerator::makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
     428                FunctionType * ftype = func->type;
     429                std::list<DeclarationWithType*> & params = ftype->parameters;
    340430                assert( params.size() >= 2 );  // should not call this function for default ctor, etc.
    341431
     
    349439                                        // don't make a function whose parameter is an unnamed bitfield
    350440                                        continue;
    351                                 } else if ( field->get_name() == "" ) {
    352                                         // don't assign to anonymous members
    353                                         // xxx - this is a temporary fix. Anonymous members tie into
    354                                         // our inheritance model. I think the correct way to handle this is to
    355                                         // cast the structure to the type of the member and let the resolver
    356                                         // figure out whether it's valid and have a pass afterwards that fixes
    357                                         // the assignment to use pointer arithmetic with the offset of the
    358                                         // member, much like how generic type members are handled.
    359                                         continue;
    360441                                } else if ( parameter != params.end() ) {
    361442                                        // matching parameter, initialize field with copy ctor
    362443                                        Expression *srcselect = new VariableExpr(*parameter);
    363                                         makeStructMemberOp( dstParam, srcselect, field, func );
     444                                        makeMemberOp( dstParam, srcselect, field, func );
    364445                                        ++parameter;
    365446                                } else {
    366447                                        // no matching parameter, initialize field with default ctor
    367                                         makeStructMemberOp( dstParam, nullptr, field, func );
     448                                        makeMemberOp( dstParam, nullptr, field, func );
    368449                                }
    369450                        }
     
    371452        }
    372453
    373         Type * declToType( Declaration * decl ) {
    374                 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    375                         return dwt->get_type();
    376                 }
    377                 return nullptr;
    378         }
    379 
    380         /// generates struct constructors, destructor, and assignment functions
    381         void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
     454        bool UnionFuncGenerator::shouldAutogen() const {
    382455                // Builtins do not use autogeneration.
    383                 if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) {
    384                         return;
    385                 }
    386 
    387                 // Make function polymorphic in same parameters as generic struct, if applicable
    388                 const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    389 
    390                 // generate each of the functions based on the supplied FuncData objects
    391                 std::list< FunctionDecl * > newFuncs;
    392                 // structure that iterates aggregate decl members, returning their types
    393                 auto generator = makeFuncGenerator( lazy_map( aggregateDecl->members, declToType ), refType, functionNesting, typeParams, back_inserter( newFuncs ) );
    394                 for ( const FuncData & d : data ) {
    395                         generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() );
    396                 }
    397 
     456                return ! aggregateDecl->linkage.is_builtin;
     457        }
     458
     459        // xxx - is this right?
     460        bool UnionFuncGenerator::isConcurrentType() const { return false; };
     461
     462        /// generate a single union assignment expression (using memcpy)
     463        template< typename OutputIterator >
     464        void UnionFuncGenerator::makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
     465                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
     466                copy->args.push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
     467                copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
     468                copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     469                *out++ = new ExprStmt( noLabels, copy );
     470        }
     471
     472        /// generates the body of a union assignment/copy constructor/field constructor
     473        void UnionFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) {
     474                FunctionType * ftype = funcDecl->type;
     475                if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) {
     476                        assert( ftype->parameters.size() == 2 );
     477                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     478                        ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() );
     479                        makeMemberOp( srcParam, dstParam, back_inserter( funcDecl->statements->kids ) );
     480                } else {
     481                        // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
     482                        assert( ftype->parameters.size() == 1 );
     483                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     484                        dstParam->attributes.push_back( new Attribute( "unused" ) );
     485                }
     486        }
     487
     488        /// generate the body of a constructor which takes parameters that match fields, e.g.
     489        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
     490        void UnionFuncGenerator::genFieldCtors() {
    398491                // field ctors are only generated if default constructor and copy constructor are both generated
    399                 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
    400 
    401                 if ( functionNesting == 0 ) {
    402                         // forward declare if top-level struct, so that
    403                         // type is complete as soon as its body ends
    404                         // Note: this is necessary if we want structs which contain
    405                         // generic (otype) structs as members.
    406                         for ( FunctionDecl * dcl : newFuncs ) {
    407                                 addForwardDecl( dcl, declsToAdd );
    408                         }
    409                 }
    410 
    411                 for ( FunctionDecl * dcl : newFuncs ) {
    412                         // generate appropriate calls to member ctor, assignment
    413                         // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
    414                         if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {
    415                                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl );
    416                         } else {
    417                                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false );
    418                         }
    419                         if ( CodeGen::isAssignment( dcl->get_name() ) ) {
    420                                 // assignment needs to return a value
    421                                 FunctionType * assignType = dcl->get_functionType();
    422                                 assert( assignType->get_parameters().size() == 2 );
    423                                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
    424                                 dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    425                         }
    426                         declsToAdd.push_back( dcl );
    427                 }
    428 
    429                 // create constructors which take each member type as a parameter.
    430                 // for example, for struct A { int x, y; }; generate
    431                 //   void ?{}(A *, int) and void ?{}(A *, int, int)
     492                unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
     493
    432494                // Field constructors are only generated if default and copy constructor
    433495                // are generated, since they need access to both
    434                 if ( numCtors == 2 ) {
    435                         FunctionType * memCtorType = genDefaultType( refType );
    436                         cloneAll( typeParams, memCtorType->get_forall() );
    437                         for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) {
    438                                 DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i );
    439                                 assert( member );
    440                                 if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) {
    441                                         // don't make a function whose parameter is an unnamed bitfield
    442                                         continue;
    443                                 } else if ( member->get_name() == "" ) {
    444                                         // don't assign to anonymous members
    445                                         // xxx - this is a temporary fix. Anonymous members tie into
    446                                         // our inheritance model. I think the correct way to handle this is to
    447                                         // cast the structure to the type of the member and let the resolver
    448                                         // figure out whether it's valid/choose the correct unnamed member
    449                                         continue;
    450                                 }
    451                                 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    452                                 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    453                                 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor );
    454                                 declsToAdd.push_back( ctor );
    455                         }
    456                         delete memCtorType;
    457                 }
    458         }
    459 
    460         /// generate a single union assignment expression (using memcpy)
    461         template< typename OutputIterator >
    462         void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    463                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    464                 copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
    465                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    466                 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
    467                 *out++ = new ExprStmt( noLabels, copy );
    468         }
    469 
    470         /// generates the body of a union assignment/copy constructor/field constructor
    471         void makeUnionAssignBody( FunctionDecl * funcDecl ) {
    472                 FunctionType * ftype = funcDecl->get_functionType();
    473                 assert( ftype->get_parameters().size() == 2 );
    474                 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    475                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    476 
    477                 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
    478                 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) {
    479                         // also generate return statement in assignment
    480                         funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    481                 }
    482         }
    483 
    484         /// generates union constructors, destructors, and assignment operator
    485         void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
    486                 // Make function polymorphic in same parameters as generic union, if applicable
    487                 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    488 
    489                 // default ctor/dtor need only first parameter
    490                 // void ?{}(T *); void ^?{}(T *);
    491                 FunctionType *ctorType = genDefaultType( refType );
    492                 FunctionType *dtorType = genDefaultType( refType );
    493 
    494                 // copy ctor needs both parameters
    495                 // void ?{}(T *, T);
    496                 FunctionType *copyCtorType = genCopyType( refType );
    497 
    498                 // assignment needs both and return value
    499                 // T ?=?(T *, T);
    500                 FunctionType *assignType = genAssignType( refType );
    501 
    502                 cloneAll( typeParams, ctorType->get_forall() );
    503                 cloneAll( typeParams, dtorType->get_forall() );
    504                 cloneAll( typeParams, copyCtorType->get_forall() );
    505                 cloneAll( typeParams, assignType->get_forall() );
    506 
    507                 // add unused attribute to parameters of default constructor and destructor
    508                 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    509                 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    510 
    511                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    512                 // because each unit generates copies of the default routines for each aggregate.
    513                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
    514                 FunctionDecl *ctorDecl = genFunc( "?{}",  ctorType, functionNesting );
    515                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
    516                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
    517 
    518                 makeUnionAssignBody( assignDecl );
    519 
    520                 // body of assignment and copy ctor is the same
    521                 makeUnionAssignBody( copyCtorDecl );
     496                if ( numCtors != 2 ) return;
    522497
    523498                // create a constructor which takes the first member type as a parameter.
     
    525500                // void ?{}(A *, int)
    526501                // This is to mimic C's behaviour which initializes the first member of the union.
    527                 std::list<Declaration *> memCtors;
    528                 for ( Declaration * member : aggregateDecl->get_members() ) {
    529                         if ( DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member ) ) {
    530                                 ObjectDecl * srcParam = new ObjectDecl( "src", Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 );
    531 
    532                                 FunctionType * memCtorType = ctorType->clone();
    533                                 memCtorType->get_parameters().push_back( srcParam );
    534                                 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting );
    535 
    536                                 makeUnionAssignBody( ctor );
    537                                 memCtors.push_back( ctor );
    538                                 // only generate a ctor for the first field
     502                FunctionType * memCtorType = genDefaultType( type );
     503                for ( Declaration * member : aggregateDecl->members ) {
     504                        DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member );
     505                        if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
     506                                // don't make a function whose parameter is an unnamed bitfield
    539507                                break;
    540508                        }
    541                 }
    542 
    543                 declsToAdd.push_back( ctorDecl );
    544                 declsToAdd.push_back( copyCtorDecl );
    545                 declsToAdd.push_back( dtorDecl );
    546                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    547                 declsToAdd.splice( declsToAdd.end(), memCtors );
    548         }
    549 
     509                        memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, field->get_type()->clone(), nullptr ) );
     510                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
     511                        ObjectDecl * srcParam = strict_dynamic_cast<ObjectDecl *>( ctor->type->parameters.back() );
     512                        srcParam->fixUniqueId();
     513                        ObjectDecl * dstParam = InitTweak::getParamThis( ctor->type );
     514                        makeMemberOp( srcParam, dstParam, back_inserter( ctor->statements->kids ) );
     515                        resolve( ctor );
     516                        // only generate one field ctor for unions
     517                        break;
     518                }
     519                delete memCtorType;
     520        }
     521
     522        void EnumFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) {
     523                // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
     524                // Really they're something of a cross between instrinsic and autogen, so should
     525                // probably make a new linkage type
     526                funcDecl->linkage = LinkageSpec::Intrinsic;
     527                FunctionType * ftype = funcDecl->type;
     528                if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) {
     529                        assert( ftype->parameters.size() == 2 );
     530                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     531                        ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() );
     532
     533                        // enum copy construct and assignment is just C-style assignment.
     534                        // this looks like a bad recursive call, but code gen will turn it into
     535                        // a C-style assignment.
     536                        // This happens before function pointer type conversion, so need to do it manually here
     537                        ApplicationExpr * callExpr = new ApplicationExpr( VariableExpr::functionPointer( funcDecl ) );
     538                        callExpr->get_args().push_back( new VariableExpr( dstParam ) );
     539                        callExpr->get_args().push_back( new VariableExpr( srcParam ) );
     540                        funcDecl->statements->push_back( new ExprStmt( noLabels, callExpr ) );
     541                } else {
     542                        // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
     543                        assert( ftype->parameters.size() == 1 );
     544                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     545                        dstParam->attributes.push_back( new Attribute( "unused" ) );
     546                }
     547        }
     548
     549        bool EnumFuncGenerator::shouldAutogen() const { return true; }
     550        bool EnumFuncGenerator::isConcurrentType() const { return false; }
     551        // enums do not have field constructors
     552        void EnumFuncGenerator::genFieldCtors() {}
     553
     554        bool TypeFuncGenerator::shouldAutogen() const { return true; };
     555
     556        void TypeFuncGenerator::genFuncBody( FunctionDecl * dcl ) {
     557                FunctionType * ftype = dcl->type;
     558                assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() );
     559                DeclarationWithType * dst = ftype->parameters.front();
     560                DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr;
     561                // generate appropriate calls to member ctor, assignment
     562                UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) );
     563                expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
     564                if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
     565                dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) );
     566        };
     567
     568        // xxx - should reach in and determine if base type is concurrent?
     569        bool TypeFuncGenerator::isConcurrentType() const { return false; };
     570
     571        // opaque types do not have field constructors
     572        void TypeFuncGenerator::genFieldCtors() {};
     573
     574        //=============================================================================================
     575        // Visitor definitions
     576        //=============================================================================================
    550577        AutogenerateRoutines::AutogenerateRoutines() {
    551578                // the order here determines the order that these functions are generated.
    552579                // assignment should come last since it uses copy constructor in return.
    553                 data.emplace_back( "?{}", genDefaultType, constructable );
    554                 data.emplace_back( "?{}", genCopyType, copyable );
    555                 data.emplace_back( "^?{}", genDefaultType, destructable );
    556                 data.emplace_back( "?=?", genAssignType, assignable );
     580                data.emplace_back( "?{}", genDefaultType );
     581                data.emplace_back( "?{}", genCopyType );
     582                data.emplace_back( "^?{}", genDefaultType );
     583                data.emplace_back( "?=?", genAssignType );
    557584        }
    558585
    559586        void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) {
    560                 visit_children = false;
    561                 if ( ! enumDecl->get_members().empty() ) {
    562                         EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    563                         // enumInst->set_baseEnum( enumDecl );
    564                         makeEnumFunctions( enumInst, functionNesting, declsToAddAfter );
     587                // must visit children (enum constants) to add them to the indexer
     588                if ( enumDecl->has_body() ) {
     589                        EnumInstType enumInst( Type::Qualifiers(), enumDecl->get_name() );
     590                        enumInst.set_baseEnum( enumDecl );
     591                        EnumFuncGenerator gen( &enumInst, data, functionNesting, indexer );
     592                        generateFunctions( gen, declsToAddAfter );
    565593                }
    566594        }
     
    568596        void AutogenerateRoutines::previsit( StructDecl * structDecl ) {
    569597                visit_children = false;
    570                 if ( structDecl->has_body() && structsDone.find( structDecl->name ) == structsDone.end() ) {
     598                if ( structDecl->has_body() ) {
    571599                        StructInstType structInst( Type::Qualifiers(), structDecl->name );
     600                        structInst.set_baseStruct( structDecl );
    572601                        for ( TypeDecl * typeDecl : structDecl->parameters ) {
    573                                 // need to visit assertions so that they are added to the appropriate maps
    574                                 acceptAll( typeDecl->assertions, *visitor );
    575602                                structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) );
    576603                        }
    577                         structInst.set_baseStruct( structDecl );
    578                         makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );
    579                         structsDone.insert( structDecl->name );
     604                        StructFuncGenerator gen( structDecl, &structInst, data, functionNesting, indexer );
     605                        generateFunctions( gen, declsToAddAfter );
    580606                } // if
    581607        }
     
    583609        void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) {
    584610                visit_children = false;
    585                 if ( ! unionDecl->get_members().empty() ) {
     611                if ( unionDecl->has_body() ) {
    586612                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    587613                        unionInst.set_baseUnion( unionDecl );
     
    589615                                unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    590616                        }
    591                         makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter );
     617                        UnionFuncGenerator gen( unionDecl, &unionInst, data, functionNesting, indexer );
     618                        generateFunctions( gen, declsToAddAfter );
    592619                } // if
    593         }
    594 
    595         Type * declToTypeDeclBase( Declaration * decl ) {
    596                 if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {
    597                         return td->base;
    598                 }
    599                 return nullptr;
    600620        }
    601621
     
    605625                if ( ! typeDecl->base ) return;
    606626
    607                 // generate each of the functions based on the supplied FuncData objects
    608                 std::list< FunctionDecl * > newFuncs;
    609                 std::list< Declaration * > tds { typeDecl };
    610                 std::list< TypeDecl * > typeParams;
    611627                TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl );
    612                 auto generator = makeFuncGenerator( lazy_map( tds, declToTypeDeclBase ), &refType, functionNesting, typeParams, back_inserter( newFuncs ) );
    613                 for ( const FuncData & d : data ) {
    614                         generator.gen( d, false );
    615                 }
    616 
    617                 if ( functionNesting == 0 ) {
    618                         // forward declare if top-level struct, so that
    619                         // type is complete as soon as its body ends
    620                         // Note: this is necessary if we want structs which contain
    621                         // generic (otype) structs as members.
    622                         for ( FunctionDecl * dcl : newFuncs ) {
    623                                 addForwardDecl( dcl, declsToAddAfter );
    624                         }
    625                 }
    626 
    627                 for ( FunctionDecl * dcl : newFuncs ) {
    628                         FunctionType * ftype = dcl->type;
    629                         assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() );
    630                         DeclarationWithType * dst = ftype->parameters.front();
    631                         DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr;
    632                         // generate appropriate calls to member ctor, assignment
    633                         // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
    634                         UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) );
    635                         expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
    636                         if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
    637                         dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) );
    638                         if ( CodeGen::isAssignment( dcl->get_name() ) ) {
    639                                 // assignment needs to return a value
    640                                 FunctionType * assignType = dcl->type;
    641                                 assert( assignType->parameters.size() == 2 );
    642                                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.back() );
    643                                 dcl->statements->kids.push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    644                         }
    645                         declsToAddAfter.push_back( dcl );
    646                 }
     628                TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer );
     629                generateFunctions( gen, declsToAddAfter );
    647630        }
    648631
     
    665648                visit_children = false;
    666649                // record the existence of this function as appropriate
    667                 insert( functionDecl, constructable, InitTweak::isDefaultConstructor );
    668                 insert( functionDecl, assignable, InitTweak::isAssignment );
    669                 insert( functionDecl, copyable, InitTweak::isCopyConstructor );
    670                 insert( functionDecl, destructable, InitTweak::isDestructor );
     650                managedTypes.handleDWT( functionDecl );
    671651
    672652                maybeAccept( functionDecl->type, *visitor );
     
    677657
    678658        void AutogenerateRoutines::previsit( CompoundStmt * ) {
    679                 GuardScope( constructable );
    680                 GuardScope( assignable );
    681                 GuardScope( copyable );
    682                 GuardScope( destructable );
     659                GuardScope( managedTypes );
    683660                GuardScope( structsDone );
    684661        }
  • src/SymTab/Autogen.h

    rb96ec83 r6840e7c  
    1919#include <string>                 // for string
    2020
     21#include "CodeGen/OperatorTable.h"
    2122#include "Common/UniqueName.h"    // for UniqueName
    2223#include "InitTweak/InitTweak.h"  // for InitExpander
     
    5152
    5253        // generate the type of a copy constructor for paramType
    53         FunctionType * genDefaultType( Type * paramType );
     54        FunctionType * genCopyType( Type * paramType );
    5455
    5556        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
     
    6061        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    6162        template< typename OutputIterator >
    62         Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
     63        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, bool addCast = false ) {
     64                bool isReferenceCtorDtor = false;
     65                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     66                        // reference constructors are essentially application of the rebind operator.
     67                        // apply & to both arguments, do not need a cast
     68                        fname = "?=?";
     69                        dstParam = new AddressExpr( dstParam );
     70                        addCast = false;
     71                        isReferenceCtorDtor = true;
     72                }
     73
    6374                // want to be able to generate assignment, ctor, and dtor generically,
    6475                // so fname is either ?=?, ?{}, or ^?{}
    65                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     76                UntypedExpr * fExpr = new UntypedExpr( new NameExpr( fname ) );
    6677
    6778                if ( addCast ) {
     
    7889                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
    7990                }
    80                 fExpr->get_args().push_back( dstParam );
     91                fExpr->args.push_back( dstParam );
    8192
    8293                Statement * listInit = srcParam.buildListInit( fExpr );
    8394
    84                 std::list< Expression * > args = *++srcParam;
    85                 fExpr->get_args().splice( fExpr->get_args().end(), args );
     95                // fetch next set of arguments
     96                ++srcParam;
     97
     98                // return if adding reference fails - will happen on default constructor and destructor
     99                if ( isReferenceCtorDtor && ! srcParam.addReference() ) {
     100                        delete fExpr;
     101                        return listInit;
     102                }
     103
     104                std::list< Expression * > args = *srcParam;
     105                fExpr->args.splice( fExpr->args.end(), args );
    86106
    87107                *out++ = new ExprStmt( noLabels, fExpr );
     
    105125                        // generate: for ( int i = 0; i < N; ++i )
    106126                        begin = new ConstantExpr( Constant::from_int( 0 ) );
    107                         end = array->get_dimension()->clone();
     127                        end = array->dimension->clone();
    108128                        cmp = new NameExpr( "?<?" );
    109129                        update = new NameExpr( "++?" );
     
    111131                        // generate: for ( int i = N-1; i >= 0; --i )
    112132                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
    113                         ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    114                         ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
     133                        ((UntypedExpr*)begin)->args.push_back( array->dimension->clone() );
     134                        ((UntypedExpr*)begin)->args.push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
    115135                        end = new ConstantExpr( Constant::from_int( 0 ) );
    116136                        cmp = new NameExpr( "?>=?" );
     
    121141
    122142                UntypedExpr *cond = new UntypedExpr( cmp );
    123                 cond->get_args().push_back( new VariableExpr( index ) );
    124                 cond->get_args().push_back( end );
     143                cond->args.push_back( new VariableExpr( index ) );
     144                cond->args.push_back( end );
    125145
    126146                UntypedExpr *inc = new UntypedExpr( update );
    127                 inc->get_args().push_back( new VariableExpr( index ) );
     147                inc->args.push_back( new VariableExpr( index ) );
    128148
    129149                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    130                 dstIndex->get_args().push_back( dstParam );
    131                 dstIndex->get_args().push_back( new VariableExpr( index ) );
     150                dstIndex->args.push_back( dstParam );
     151                dstIndex->args.push_back( new VariableExpr( index ) );
    132152                dstParam = dstIndex;
    133153
    134154                // srcParam must keep track of the array indices to build the
    135155                // source parameter and/or array list initializer
    136                 srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
     156                srcParam.addArrayIndex( new VariableExpr( index ), array->dimension->clone() );
    137157
    138158                // for stmt's body, eventually containing call
    139159                CompoundStmt * body = new CompoundStmt( noLabels );
    140                 Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
     160                Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward );
    141161
    142162                // block containing for stmt and index variable
    143163                std::list<Statement *> initList;
    144164                CompoundStmt * block = new CompoundStmt( noLabels );
    145                 block->get_kids().push_back( new DeclStmt( noLabels, index ) );
     165                block->push_back( new DeclStmt( noLabels, index ) );
    146166                if ( listInit ) block->get_kids().push_back( listInit );
    147                 block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
     167                block->push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
    148168
    149169                *out++ = block;
     
    151171
    152172        template< typename OutputIterator >
    153         Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
     173        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
    154174                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    155175                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    165185        /// ImplicitCtorDtorStmt node.
    166186        template< typename OutputIterator >
    167         void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     187        void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    168188                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    169189                assert( obj );
     
    173193                bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) );
    174194                std::list< Statement * > stmts;
    175                 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
     195                genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward );
    176196
    177197                // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
  • src/SymTab/FixFunction.cc

    rb96ec83 r6840e7c  
    2626        FixFunction::FixFunction() : isVoid( false ) {}
    2727
    28         DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
     28
     29        DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
    2930                // can't delete function type because it may contain assertions, so transfer ownership to new object
    30                 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
    31                 functionDecl->get_attributes().clear();
     31                ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
     32                functionDecl->attributes.clear();
    3233                functionDecl->type = nullptr;
    3334                delete functionDecl;
     
    3536        }
    3637
    37         Type * FixFunction::mutate(VoidType *voidType) {
    38                 isVoid = true;
    39                 return voidType;
    40         }
    41 
    42         Type * FixFunction::mutate(BasicType *basicType) {
    43                 return basicType;
    44         }
    45 
    46         Type * FixFunction::mutate(PointerType *pointerType) {
    47                 return pointerType;
    48         }
    49 
    50         Type * FixFunction::mutate(ArrayType *arrayType) {
     38        Type * FixFunction::postmutate(ArrayType *arrayType) {
    5139                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    52                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
     40                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
     41                arrayType->base = nullptr;
     42                arrayType->dimension = nullptr;
    5343                delete arrayType;
    5444                return pointerType;
    5545        }
    5646
    57         Type * FixFunction::mutate(StructInstType *aggregateUseType) {
    58                 return aggregateUseType;
     47        void FixFunction::premutate(VoidType *) {
     48                isVoid = true;
    5949        }
    6050
    61         Type * FixFunction::mutate(UnionInstType *aggregateUseType) {
    62                 return aggregateUseType;
    63         }
    64 
    65         Type * FixFunction::mutate(EnumInstType *aggregateUseType) {
    66                 return aggregateUseType;
    67         }
    68 
    69         Type * FixFunction::mutate(TraitInstType *aggregateUseType) {
    70                 return aggregateUseType;
    71         }
    72 
    73         Type * FixFunction::mutate(TypeInstType *aggregateUseType) {
    74                 return aggregateUseType;
    75         }
    76 
    77         Type * FixFunction::mutate(TupleType *tupleType) {
    78                 return tupleType;
    79         }
    80 
    81         Type * FixFunction::mutate(VarArgsType *varArgsType) {
    82                 return varArgsType;
    83         }
    84 
    85         Type * FixFunction::mutate(ZeroType *zeroType) {
    86                 return zeroType;
    87         }
    88 
    89         Type * FixFunction::mutate(OneType *oneType) {
    90                 return oneType;
    91         }
     51        void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
     52        void FixFunction::premutate(BasicType *) { visit_children = false; }
     53        void FixFunction::premutate(PointerType *) { visit_children = false; }
     54        void FixFunction::premutate(StructInstType *) { visit_children = false; }
     55        void FixFunction::premutate(UnionInstType *) { visit_children = false; }
     56        void FixFunction::premutate(EnumInstType *) { visit_children = false; }
     57        void FixFunction::premutate(TraitInstType *) { visit_children = false; }
     58        void FixFunction::premutate(TypeInstType *) { visit_children = false; }
     59        void FixFunction::premutate(TupleType *) { visit_children = false; }
     60        void FixFunction::premutate(VarArgsType *) { visit_children = false; }
     61        void FixFunction::premutate(ZeroType *) { visit_children = false; }
     62        void FixFunction::premutate(OneType *) { visit_children = false; }
    9263} // namespace SymTab
    9364
  • src/SymTab/FixFunction.h

    rb96ec83 r6840e7c  
    1616#pragma once
    1717
    18 #include "SynTree/Mutator.h"  // for Mutator
    19 #include "SynTree/SynTree.h"  // for Types
     18#include "Common/PassVisitor.h" // for PassVisitor
     19#include "SynTree/SynTree.h"    // for Types
    2020
    2121namespace SymTab {
    2222        /// Replaces function and array types by equivalent pointer types.
    23         class FixFunction : public Mutator {
     23        class FixFunction : public WithShortCircuiting {
    2424                typedef Mutator Parent;
    2525          public:
    2626                FixFunction();
    2727
    28                 bool get_isVoid() const { return isVoid; }
    29                 void set_isVoid( bool newValue ) { isVoid = newValue; }
    30           private:
    31                 virtual DeclarationWithType* mutate(FunctionDecl *functionDecl);
     28                void premutate(FunctionDecl *functionDecl);
     29                DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    3230
    33                 virtual Type* mutate(VoidType *voidType);
    34                 virtual Type* mutate(BasicType *basicType);
    35                 virtual Type* mutate(PointerType *pointerType);
    36                 virtual Type* mutate(ArrayType *arrayType);
    37                 virtual Type* mutate(StructInstType *aggregateUseType);
    38                 virtual Type* mutate(UnionInstType *aggregateUseType);
    39                 virtual Type* mutate(EnumInstType *aggregateUseType);
    40                 virtual Type* mutate(TraitInstType *aggregateUseType);
    41                 virtual Type* mutate(TypeInstType *aggregateUseType);
    42                 virtual Type* mutate(TupleType *tupleType);
    43                 virtual Type* mutate(VarArgsType *varArgsType);
    44                 virtual Type* mutate(ZeroType *zeroType);
    45                 virtual Type* mutate(OneType *oneType);
     31                Type * postmutate(ArrayType * arrayType);
     32
     33                void premutate(VoidType * voidType);
     34                void premutate(BasicType * basicType);
     35                void premutate(PointerType * pointerType);
     36                void premutate(StructInstType * aggregateUseType);
     37                void premutate(UnionInstType * aggregateUseType);
     38                void premutate(EnumInstType * aggregateUseType);
     39                void premutate(TraitInstType * aggregateUseType);
     40                void premutate(TypeInstType * aggregateUseType);
     41                void premutate(TupleType * tupleType);
     42                void premutate(VarArgsType * varArgsType);
     43                void premutate(ZeroType * zeroType);
     44                void premutate(OneType * oneType);
    4645
    4746                bool isVoid;
  • src/SymTab/Indexer.cc

    rb96ec83 r6840e7c  
    407407                makeWritable();
    408408
    409                 const std::string &name = decl->get_name();
     409                const std::string &name = decl->name;
    410410                std::string mangleName;
    411                 if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
     411                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
    412412                        // mangle the name without including the appropriate suffix, so overridable routines are placed into the
    413413                        // same "bucket" as their user defined versions.
     
    418418
    419419                // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage
    420                 if ( ! LinkageSpec::isMangled( decl->get_linkage() ) ) {
     420                if ( ! LinkageSpec::isMangled( decl->linkage ) ) {
    421421                        // NOTE this is broken in Richard's original code in such a way that it never triggers (it
    422422                        // doesn't check decls that have the same manglename, and all C-linkage decls are defined to
     
    571571
    572572                if ( doDebug ) {
    573                         std::cout << "--- Entering scope " << scope << std::endl;
     573                        std::cerr << "--- Entering scope " << scope << std::endl;
    574574                }
    575575        }
    576576
    577577        void Indexer::leaveScope() {
    578                 using std::cout;
     578                using std::cerr;
    579579
    580580                assert( scope > 0 && "cannot leave initial scope" );
     581                if ( doDebug ) {
     582                        cerr << "--- Leaving scope " << scope << " containing" << std::endl;
     583                }
    581584                --scope;
    582585
    583586                while ( tables && tables->scope > scope ) {
    584587                        if ( doDebug ) {
    585                                 cout << "--- Leaving scope " << tables->scope << " containing" << std::endl;
    586                                 dump( tables->idTable, cout );
    587                                 dump( tables->typeTable, cout );
    588                                 dump( tables->structTable, cout );
    589                                 dump( tables->enumTable, cout );
    590                                 dump( tables->unionTable, cout );
    591                                 dump( tables->traitTable, cout );
     588                                dump( tables->idTable, cerr );
     589                                dump( tables->typeTable, cerr );
     590                                dump( tables->structTable, cerr );
     591                                dump( tables->enumTable, cerr );
     592                                dump( tables->unionTable, cerr );
     593                                dump( tables->traitTable, cerr );
    592594                        }
    593595
  • src/SymTab/Mangler.cc

    rb96ec83 r6840e7c  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:40:29 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 28 15:31:00 2017
    13 // Update Count     : 21
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Sep 25 15:49:26 2017
     13// Update Count     : 23
    1414//
    1515#include "Mangler.h"
     
    115115                        "Id",   // DoubleImaginary
    116116                        "Ir",   // LongDoubleImaginary
     117                        "w",    // SignedInt128
     118                        "Uw",   // UnsignedInt128
    117119                };
    118120
  • src/SymTab/Validate.cc

    rb96ec83 r6840e7c  
    153153                void previsit( ObjectDecl * object );
    154154                void previsit( FunctionDecl * func );
     155                void previsit( StructDecl * aggrDecl );
     156                void previsit( UnionDecl * aggrDecl );
    155157        };
    156158
     
    270272                acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist
    271273                VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
     274                ReturnChecker::checkFunctionReturns( translationUnit );
     275                InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
    272276                Concurrency::applyKeywords( translationUnit );
     277                acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    273278                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
    274279                Concurrency::implementMutexFuncs( translationUnit );
    275280                Concurrency::implementThreadStarter( translationUnit );
    276                 ReturnChecker::checkFunctionReturns( translationUnit );
    277281                mutateAll( translationUnit, compoundliteral );
    278                 acceptAll( translationUnit, fpd );
    279282                ArrayLength::computeLength( translationUnit );
    280                 acceptAll( translationUnit, finder );
     283                acceptAll( translationUnit, finder ); // xxx - remove this pass soon
    281284                mutateAll( translationUnit, labelAddrFixer );
    282285        }
     
    369372                        DWTIterator begin( dwts.begin() ), end( dwts.end() );
    370373                        if ( begin == end ) return;
    371                         FixFunction fixer;
     374                        PassVisitor<FixFunction> fixer;
    372375                        DWTIterator i = begin;
    373376                        *i = (*i)->acceptMutator( fixer );
    374                         if ( fixer.get_isVoid() ) {
     377                        if ( fixer.pass.isVoid ) {
    375378                                DWTIterator j = i;
    376379                                ++i;
     
    383386                                ++i;
    384387                                for ( ; i != end; ++i ) {
    385                                         FixFunction fixer;
     388                                        PassVisitor<FixFunction> fixer;
    386389                                        *i = (*i)->acceptMutator( fixer );
    387                                         if ( fixer.get_isVoid() ) {
     390                                        if ( fixer.pass.isVoid ) {
    388391                                                throw SemanticError( "invalid type void in function type ", func );
    389392                                        } // if
     
    597600                        // apply FixFunction to every assertion to check for invalid void type
    598601                        for ( DeclarationWithType *& assertion : type->assertions ) {
    599                                 FixFunction fixer;
     602                                PassVisitor<FixFunction> fixer;
    600603                                assertion = assertion->acceptMutator( fixer );
    601                                 if ( fixer.get_isVoid() ) {
     604                                if ( fixer.pass.isVoid ) {
    602605                                        throw SemanticError( "invalid type void in assertion of function ", node );
    603606                                } // if
     
    618621                forallFixer( func->type->forall, func );
    619622                func->fixUniqueId();
     623        }
     624
     625        void ForallPointerDecay::previsit( StructDecl * aggrDecl ) {
     626                forallFixer( aggrDecl->parameters, aggrDecl );
     627        }
     628
     629        void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) {
     630                forallFixer( aggrDecl->parameters, aggrDecl );
    620631        }
    621632
  • src/SynTree/AddressExpr.cc

    rb96ec83 r6840e7c  
    3333        Type * addrType( Type * type ) {
    3434                if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
    35                         return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) );
     35                        return new ReferenceType( refType->get_qualifiers(), addrType( refType->base ) );
    3636                } else {
    3737                        return new PointerType( Type::Qualifiers(), type->clone() );
     
    4040}
    4141
    42 AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) {
    43         if ( arg->has_result() ) {
    44                 if ( arg->get_result()->get_lvalue() ) {
     42AddressExpr::AddressExpr( Expression *arg ) : Expression(), arg( arg ) {
     43        if ( arg->result ) {
     44                if ( arg->result->get_lvalue() ) {
    4545                        // lvalue, retains all layers of reference and gains a pointer inside the references
    46                         set_result( addrType( arg->get_result() ) );
     46                        set_result( addrType( arg->result ) );
    4747                } else {
    4848                        // taking address of non-lvalue -- must be a reference, loses one layer of reference
    49                         ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->get_result() );
    50                         set_result( addrType( refType->get_base() ) );
     49                        ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->result );
     50                        set_result( addrType( refType->base ) );
    5151                }
    5252                // result of & is never an lvalue
     
    6262}
    6363
    64 void AddressExpr::print( std::ostream &os, int indent ) const {
     64void AddressExpr::print( std::ostream &os, Indenter indent ) const {
    6565        os << "Address of:" << std::endl;
    6666        if ( arg ) {
    67                 os << std::string( indent+2, ' ' );
    68                 arg->print( os, indent+2 );
     67                os << indent+1;
     68                arg->print( os, indent+1 );
    6969        } // if
    7070}
     
    7777LabelAddressExpr::~LabelAddressExpr() {}
    7878
    79 void LabelAddressExpr::print( std::ostream & os, int indent ) const {
    80         os << "Address of label:" << std::endl << std::string( indent+2, ' ' ) << arg;
     79void LabelAddressExpr::print( std::ostream & os, Indenter ) const {
     80        os << "Address of label:" << arg;
    8181}
    8282
  • src/SynTree/AggregateDecl.cc

    rb96ec83 r6840e7c  
    4141}
    4242
    43 void AggregateDecl::print( std::ostream &os, int indent ) const {
     43void AggregateDecl::print( std::ostream &os, Indenter indent ) const {
    4444        using std::string;
    4545        using std::endl;
    4646
    47         os << typeString() << " " << get_name() << ":";
     47        os << typeString() << " " << name << ":";
    4848        if ( get_linkage() != LinkageSpec::Cforall ) {
    49                 os << " " << LinkageSpec::linkageName( get_linkage() );
     49                os << " " << LinkageSpec::linkageName( linkage );
    5050        } // if
    51         os << " with body " << has_body() << endl;
     51        os << " with body " << has_body();
    5252
    5353        if ( ! parameters.empty() ) {
    54                 os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
    55                 printAll( parameters, os, indent+4 );
     54                os << endl << indent << "... with parameters" << endl;
     55                printAll( parameters, os, indent+1 );
    5656        } // if
    5757        if ( ! members.empty() ) {
    58                 os << endl << string( indent+2, ' ' ) << "with members" << endl;
    59                 printAll( members, os, indent+4 );
     58                os << endl << indent << "... with members" << endl;
     59                printAll( members, os, indent+1 );
    6060        } // if
    6161        if ( ! attributes.empty() ) {
    62                 os << endl << string( indent+2, ' ' ) << "with attributes" << endl;
    63                 printAll( attributes, os, indent+4 );
     62                os << endl << indent << "... with attributes" << endl;
     63                printAll( attributes, os, indent+1 );
    6464        } // if
     65        os << endl;
    6566}
    6667
    67 void AggregateDecl::printShort( std::ostream &os, int indent ) const {
     68void AggregateDecl::printShort( std::ostream &os, Indenter indent ) const {
    6869        using std::string;
    6970        using std::endl;
    7071
    71         os << typeString() << " " << get_name();
    72         os << string( indent+2, ' ' ) << "with body " << has_body() << endl;
     72        os << typeString() << " " << name << " with body " << has_body() << endl;
    7373
    7474        if ( ! parameters.empty() ) {
    75                 os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
    76                 printAll( parameters, os, indent+4 );
     75                os << indent << "... with parameters" << endl;
     76                printAll( parameters, os, indent+1 );
    7777        } // if
    7878}
  • src/SynTree/ApplicationExpr.cc

    rb96ec83 r6840e7c  
    5555        set_result( ResolvExpr::extractResultType( function ) );
    5656
    57         assert( has_result() );
     57        assert( result );
    5858}
    5959
     
    6868}
    6969
    70 void printInferParams( const InferredParams & inferParams, std::ostream &os, int indent, int level ) {
     70void printInferParams( const InferredParams & inferParams, std::ostream &os, Indenter indent, int level ) {
    7171        if ( ! inferParams.empty() ) {
    72                 os << std::string(indent, ' ') << "with inferred parameters " << level << ":" << std::endl;
     72                os << indent << "with inferred parameters " << level << ":" << std::endl;
    7373                for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
    74                         os << std::string(indent+2, ' ');
    75                         Declaration::declFromId( i->second.decl )->printShort( os, indent+2 );
     74                        os << indent+1;
     75                        Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
    7676                        os << std::endl;
    77                         printInferParams( *i->second.inferParams, os, indent+2, level+1 );
     77                        printInferParams( *i->second.inferParams, os, indent+1, level+1 );
    7878                } // for
    7979        } // if
    8080}
    8181
    82 void ApplicationExpr::print( std::ostream &os, int indent ) const {
    83         os << "Application of" << std::endl << std::string(indent+2, ' ');
    84         function->print( os, indent+2 );
     82void ApplicationExpr::print( std::ostream &os, Indenter indent ) const {
     83        os << "Application of" << std::endl << indent+1;
     84        function->print( os, indent+1 );
     85        os << std::endl;
    8586        if ( ! args.empty() ) {
    86                 os << std::string( indent, ' ' ) << "to arguments" << std::endl;
    87                 printAll( args, os, indent+2 );
     87                os << indent << "... to arguments" << std::endl;
     88                printAll( args, os, indent+1 );
    8889        } // if
    89         printInferParams( inferParams, os, indent+2, 0 );
     90        printInferParams( inferParams, os, indent+1, 0 );
    9091        Expression::print( os, indent );
    9192}
  • src/SynTree/ArrayType.cc

    rb96ec83 r6840e7c  
    3939}
    4040
    41 void ArrayType::print( std::ostream &os, int indent ) const {
     41void ArrayType::print( std::ostream &os, Indenter indent ) const {
    4242        Type::print( os, indent );
    4343        if ( isStatic ) {
  • src/SynTree/AttrType.cc

    rb96ec83 r6840e7c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AttrType.cc.cc -- 
     7// AttrType.cc.cc --
    88//
    99// Author           : Richard C. Bilson
     
    4242}
    4343
    44 void AttrType::print( std::ostream &os, int indent ) const {
     44void AttrType::print( std::ostream &os, Indenter indent ) const {
    4545        Type::print( os, indent );
    4646        os << "attribute " << name << " applied to ";
  • src/SynTree/Attribute.cc

    rb96ec83 r6840e7c  
    2828}
    2929
    30 void Attribute::print( std::ostream &os, int indent ) const {
     30void Attribute::print( std::ostream &os, Indenter indent ) const {
    3131  using std::endl;
    3232  using std::string;
     
    3636    if ( ! parameters.empty() ) {
    3737      os << " with parameters: " << endl;
    38       printAll( parameters, os, indent );
     38      printAll( parameters, os, indent+1 );
    3939    }
    4040  }
  • src/SynTree/Attribute.h

    rb96ec83 r6840e7c  
    4343        bool empty() const { return name == ""; }
    4444
    45         Attribute * clone() const { return new Attribute( *this ); }
    46         virtual void accept( Visitor & v ) { v.visit( this ); }
    47         virtual Attribute * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    48         virtual void print( std::ostream & os, int indent = 0 ) const;
     45        Attribute * clone() const override { return new Attribute( *this ); }
     46        virtual void accept( Visitor & v ) override { v.visit( this ); }
     47        virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     48        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    4949};
    5050
  • src/SynTree/BaseSyntaxNode.h

    rb96ec83 r6840e7c  
    1717
    1818#include "Common/CodeLocation.h"
     19#include "Common/Indenter.h"
    1920class Visitor;
    2021class Mutator;
     
    2930        virtual void accept( Visitor & v ) = 0;
    3031        virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
    31         virtual void print( std::ostream & os, int indent = 0 ) const = 0;
     32  /// Notes:
     33  /// * each node is responsible for indenting its children.
     34  /// * Expressions should not finish with a newline, since the expression's parent has better information.
     35        virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
     36  void print( std::ostream & os, unsigned int indent ) {
     37    print( os, Indenter{ Indenter::tabsize, indent });
     38  }
    3239};
    3340
  • src/SynTree/BasicType.cc

    rb96ec83 r6840e7c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // BasicType.cc -- 
     7// BasicType.cc --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 11 12:52:05 2017
    13 // Update Count     : 9
     12// Last Modified On : Mon Sep 25 14:14:03 2017
     13// Update Count     : 11
    1414//
    1515
     
    2424BasicType::BasicType( const Type::Qualifiers &tq, Kind bt, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), kind( bt ) {}
    2525
    26 void BasicType::print( std::ostream &os, int indent ) const {
     26void BasicType::print( std::ostream &os, Indenter indent ) const {
    2727        Type::print( os, indent );
    2828        os << BasicType::typeNames[ kind ];
     
    4343          case LongLongSignedInt:
    4444          case LongLongUnsignedInt:
     45          case SignedInt128:
     46          case UnsignedInt128:
    4547                return true;
    4648          case Float:
  • src/SynTree/CommaExpr.cc

    rb96ec83 r6840e7c  
    2121#include "Type.h"            // for Type
    2222
    23 CommaExpr::CommaExpr( Expression *arg1, Expression *arg2, Expression *_aname )
    24                 : Expression( _aname ), arg1( arg1 ), arg2( arg2 ) {
     23CommaExpr::CommaExpr( Expression *arg1, Expression *arg2 )
     24                : Expression(), arg1( arg1 ), arg2( arg2 ) {
    2525        // xxx - result of a comma expression is never an lvalue, so should set lvalue
    2626        // to false on all result types. Actually doing this causes some strange things
     
    3939}
    4040
    41 void CommaExpr::print( std::ostream &os, int indent ) const {
     41void CommaExpr::print( std::ostream &os, Indenter indent ) const {
    4242        os << "Comma Expression:" << std::endl;
    43         os << std::string( indent+2, ' ' );
    44         arg1->print( os, indent+2 );
     43        os << (indent+1);
     44        arg1->print( os, indent+1 );
    4545        os << std::endl;
    46         os << std::string( indent+2, ' ' );
    47         arg2->print( os, indent+2 );
     46        os << (indent+1);
     47        arg2->print( os, indent+1 );
    4848        Expression::print( os, indent );
    4949}
  • src/SynTree/CompoundStmt.cc

    rb96ec83 r6840e7c  
    7373}
    7474
    75 void CompoundStmt::print( std::ostream &os, int indent ) const {
    76         os << "CompoundStmt" << endl ;
    77         printAll( kids, os, indent + 2 );
     75void CompoundStmt::print( std::ostream &os, Indenter indent ) const {
     76        os << "CompoundStmt" << endl;
     77        printAll( kids, os, indent+1 );
    7878}
    7979
  • src/SynTree/Constant.cc

    rb96ec83 r6840e7c  
    7171}
    7272
    73 void Constant::print( std::ostream &os ) const {
     73void Constant::print( std::ostream &os, Indenter ) const {
    7474        os << "(" << rep << " " << val.ival;
    7575        if ( type ) {
  • src/SynTree/Constant.h

    rb96ec83 r6840e7c  
    1919#include <string>     // for string
    2020
     21#include "BaseSyntaxNode.h"
    2122#include "Mutator.h"  // for Mutator
    2223#include "Visitor.h"  // for Visitor
     
    2425class Type;
    2526
    26 class Constant {
     27class Constant : public BaseSyntaxNode {
    2728  public:
    2829        Constant( Type * type, std::string rep, unsigned long long val );
     
    3031        Constant( const Constant & other );
    3132        virtual ~Constant();
     33
     34        virtual Constant * clone() const { return new Constant( *this ); }
    3235
    3336        Type * get_type() { return type; }
     
    5457        virtual void accept( Visitor & v ) { v.visit( this ); }
    5558        virtual Constant * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    56         virtual void print( std::ostream & os ) const;
     59        virtual void print( std::ostream & os, Indenter indent = 0 ) const;
    5760  private:
    5861        Type * type;
  • src/SynTree/DeclStmt.cc

    rb96ec83 r6840e7c  
    3333}
    3434
    35 void DeclStmt::print( std::ostream &os, int indent ) const {
     35void DeclStmt::print( std::ostream &os, Indenter indent ) const {
    3636        assert( decl != 0 );
    3737        os << "Declaration of ";
  • src/SynTree/Declaration.cc

    rb96ec83 r6840e7c  
    4242
    4343void Declaration::fixUniqueId() {
     44        // don't need to set unique ID twice
     45        if ( uniqueId ) return;
    4446        uniqueId = ++lastUniqueId;
    4547        idMap[ uniqueId ] = this;
     
    7072}
    7173
    72 void AsmDecl::print( std::ostream &os, int indent ) const {
     74void AsmDecl::print( std::ostream &os, Indenter indent ) const {
    7375        stmt->print( os, indent );
    7476}
    7577
    76 void AsmDecl::printShort( std::ostream &os, int indent ) const {
     78void AsmDecl::printShort( std::ostream &os, Indenter indent ) const {
    7779        stmt->print( os, indent );
    7880}
  • src/SynTree/Declaration.h

    rb96ec83 r6840e7c  
    6161
    6262        void fixUniqueId( void );
    63         virtual Declaration *clone() const = 0;
     63        virtual Declaration *clone() const override = 0;
    6464        virtual void accept( Visitor &v ) override = 0;
    65         virtual Declaration *acceptMutator( Mutator &m ) = 0;
    66         virtual void print( std::ostream &os, int indent = 0 ) const override = 0;
    67         virtual void printShort( std::ostream &os, int indent = 0 ) const = 0;
     65        virtual Declaration *acceptMutator( Mutator &m ) override = 0;
     66        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
     67        virtual void printShort( std::ostream &os, Indenter indent = {} ) const = 0;
    6868
    6969        static void dumpIds( std::ostream &os );
     
    142142        virtual void accept( Visitor &v ) override { v.visit( this ); }
    143143        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    144         virtual void print( std::ostream &os, int indent = 0 ) const override;
    145         virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     144        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     145        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    146146};
    147147
     
    170170        virtual void accept( Visitor &v ) override { v.visit( this ); }
    171171        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    172         virtual void print( std::ostream &os, int indent = 0 ) const override;
    173         virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     172        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     173        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    174174};
    175175
     
    193193
    194194        virtual NamedTypeDecl *clone() const override = 0;
    195         virtual void print( std::ostream &os, int indent = 0 ) const override;
    196         virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     195        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     196        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    197197};
    198198
     
    235235        virtual void accept( Visitor &v ) override { v.visit( this ); }
    236236        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    237         virtual void print( std::ostream &os, int indent = 0 ) const override;
     237        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    238238
    239239  private:
     
    276276        AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
    277277
    278         virtual void print( std::ostream &os, int indent = 0 ) const override;
    279         virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     278        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     279        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    280280  protected:
    281281        virtual std::string typeString() const = 0;
     
    355355        virtual void accept( Visitor &v ) override { v.visit( this ); }
    356356        virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    357         virtual void print( std::ostream &os, int indent = 0 ) const override;
    358         virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     357        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     358        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    359359};
    360360
  • src/SynTree/Expression.cc

    rb96ec83 r6840e7c  
    3333#include "GenPoly/Lvalue.h"
    3434
    35 Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
    36 
    37 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
     35Expression::Expression() : result( 0 ), env( 0 ) {}
     36
     37Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ) {
    3838}
    3939
    4040Expression::~Expression() {
    4141        delete env;
    42         delete argName; // xxx -- there's a problem in cloning ConstantExpr I still don't know how to fix
    4342        delete result;
    4443}
    4544
    46 void Expression::print( std::ostream &os, int indent ) const {
     45void Expression::print( std::ostream &os, Indenter indent ) const {
    4746        if ( env ) {
    48                 os << std::string( indent, ' ' ) << "with environment:" << std::endl;
    49                 env->print( os, indent+2 );
     47                os << std::endl << indent << "... with environment:" << std::endl;
     48                env->print( os, indent+1 );
    5049        } // if
    5150
    52         if ( argName ) {
    53                 os << std::string( indent, ' ' ) << "with designator:";
    54                 argName->print( os, indent+2 );
     51        if ( extension ) {
     52                os << std::endl << indent << "... with extension:";
    5553        } // if
    56 
    57         if ( extension ) {
    58                 os << std::string( indent, ' ' ) << "with extension:";
    59         } // if
    60 }
    61 
    62 ConstantExpr::ConstantExpr( Constant _c, Expression *_aname ) : Expression( _aname ), constant( _c ) {
     54}
     55
     56ConstantExpr::ConstantExpr( Constant _c ) : Expression(), constant( _c ) {
    6357        set_result( constant.get_type()->clone() );
    6458}
     
    6963ConstantExpr::~ConstantExpr() {}
    7064
    71 void ConstantExpr::print( std::ostream &os, int indent ) const {
     65void ConstantExpr::print( std::ostream &os, Indenter indent ) const {
    7266        os << "constant expression " ;
    7367        constant.print( os );
     
    7569}
    7670
    77 VariableExpr::VariableExpr( DeclarationWithType *_var, Expression *_aname ) : Expression( _aname ), var( _var ) {
     71VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
    7872        assert( var );
    7973        assert( var->get_type() );
     
    9690}
    9791
    98 void VariableExpr::print( std::ostream &os, int indent ) const {
     92void VariableExpr::print( std::ostream &os, Indenter indent ) const {
    9993        os << "Variable Expression: ";
    100 
    101         Declaration *decl = get_var();
    102         if ( decl != 0) decl->printShort(os, indent + 2);
    103         os << std::endl;
    104         Expression::print( os, indent );
    105 }
    106 
    107 SizeofExpr::SizeofExpr( Expression *expr_, Expression *_aname ) :
    108                 Expression( _aname ), expr(expr_), type(0), isType(false) {
     94        var->printShort(os, indent);
     95        Expression::print( os, indent );
     96}
     97
     98SizeofExpr::SizeofExpr( Expression *expr_ ) :
     99                Expression(), expr(expr_), type(0), isType(false) {
    109100        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    110101}
    111102
    112 SizeofExpr::SizeofExpr( Type *type_, Expression *_aname ) :
    113                 Expression( _aname ), expr(0), type(type_), isType(true) {
     103SizeofExpr::SizeofExpr( Type *type_ ) :
     104                Expression(), expr(0), type(type_), isType(true) {
    114105        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    115106}
     
    124115}
    125116
    126 void SizeofExpr::print( std::ostream &os, int indent) const {
     117void SizeofExpr::print( std::ostream &os, Indenter indent) const {
    127118        os << "Sizeof Expression on: ";
    128 
    129         if (isType)
    130                 type->print(os, indent + 2);
    131         else
    132                 expr->print(os, indent + 2);
    133 
    134         os << std::endl;
    135         Expression::print( os, indent );
    136 }
    137 
    138 AlignofExpr::AlignofExpr( Expression *expr_, Expression *_aname ) :
    139                 Expression( _aname ), expr(expr_), type(0), isType(false) {
     119        if (isType) type->print(os, indent+1);
     120        else expr->print(os, indent+1);
     121        Expression::print( os, indent );
     122}
     123
     124AlignofExpr::AlignofExpr( Expression *expr_ ) :
     125                Expression(), expr(expr_), type(0), isType(false) {
    140126        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    141127}
    142128
    143 AlignofExpr::AlignofExpr( Type *type_, Expression *_aname ) :
    144                 Expression( _aname ), expr(0), type(type_), isType(true) {
     129AlignofExpr::AlignofExpr( Type *type_ ) :
     130                Expression(), expr(0), type(type_), isType(true) {
    145131        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    146132}
     
    155141}
    156142
    157 void AlignofExpr::print( std::ostream &os, int indent) const {
     143void AlignofExpr::print( std::ostream &os, Indenter indent) const {
    158144        os << "Alignof Expression on: ";
    159 
    160         if (isType)
    161                 type->print(os, indent + 2);
    162         else
    163                 expr->print(os, indent + 2);
    164 
    165         os << std::endl;
    166         Expression::print( os, indent );
    167 }
    168 
    169 UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type_, const std::string &member_, Expression *_aname ) :
    170                 Expression( _aname ), type(type_), member(member_) {
     145        if (isType) type->print(os, indent+1);
     146        else expr->print(os, indent+1);
     147        Expression::print( os, indent );
     148}
     149
     150UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type, const std::string &member ) :
     151                Expression(), type(type), member(member) {
     152        assert( type );
    171153        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    172154}
     
    179161}
    180162
    181 void UntypedOffsetofExpr::print( std::ostream &os, int indent) const {
    182         os << std::string( indent, ' ' ) << "Untyped Offsetof Expression on member " << member << " of ";
    183 
    184         if ( type ) {
    185                 type->print(os, indent + 2);
    186         } else {
    187                 os << "<NULL>";
    188         }
    189 
    190         os << std::endl;
    191         Expression::print( os, indent );
    192 }
    193 
    194 OffsetofExpr::OffsetofExpr( Type *type_, DeclarationWithType *member_, Expression *_aname ) :
    195                 Expression( _aname ), type(type_), member(member_) {
     163void UntypedOffsetofExpr::print( std::ostream &os, Indenter indent) const {
     164        os << "Untyped Offsetof Expression on member " << member << " of ";
     165        type->print(os, indent+1);
     166        Expression::print( os, indent );
     167}
     168
     169OffsetofExpr::OffsetofExpr( Type *type, DeclarationWithType *member ) :
     170                Expression(), type(type), member(member) {
     171        assert( member );
     172        assert( type );
    196173        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    197174}
     
    204181}
    205182
    206 void OffsetofExpr::print( std::ostream &os, int indent) const {
    207         os << std::string( indent, ' ' ) << "Offsetof Expression on member ";
    208 
    209         if ( member ) {
    210                 os << member->get_name();
    211         } else {
    212                 os << "<NULL>";
    213         }
    214 
    215         os << " of ";
    216 
    217         if ( type ) {
    218                 type->print(os, indent + 2);
    219         } else {
    220                 os << "<NULL>";
    221         }
    222 
    223         os << std::endl;
    224         Expression::print( os, indent );
    225 }
    226 
    227 OffsetPackExpr::OffsetPackExpr( StructInstType *type_, Expression *aname_ ) : Expression( aname_ ), type( type_ ) {
     183void OffsetofExpr::print( std::ostream &os, Indenter indent) const {
     184        os << "Offsetof Expression on member " << member->name << " of ";
     185        type->print(os, indent+1);
     186        Expression::print( os, indent );
     187}
     188
     189OffsetPackExpr::OffsetPackExpr( StructInstType *type ) : Expression(), type( type ) {
     190        assert( type );
    228191        set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
    229192}
     
    233196OffsetPackExpr::~OffsetPackExpr() { delete type; }
    234197
    235 void OffsetPackExpr::print( std::ostream &os, int indent ) const {
    236         os << std::string( indent, ' ' ) << "Offset pack expression on ";
    237 
    238         if ( type ) {
    239                 type->print(os, indent + 2);
    240         } else {
    241                 os << "<NULL>";
    242         }
    243 
    244         os << std::endl;
    245         Expression::print( os, indent );
    246 }
    247 
    248 AttrExpr::AttrExpr( Expression *attr, Expression *expr_, Expression *_aname ) :
    249                 Expression( _aname ), attr( attr ), expr(expr_), type(0), isType(false) {
    250 }
    251 
    252 AttrExpr::AttrExpr( Expression *attr, Type *type_, Expression *_aname ) :
    253                 Expression( _aname ), attr( attr ), expr(0), type(type_), isType(true) {
     198void OffsetPackExpr::print( std::ostream &os, Indenter indent ) const {
     199        os << "Offset pack expression on ";
     200        type->print(os, indent+1);
     201        Expression::print( os, indent );
     202}
     203
     204AttrExpr::AttrExpr( Expression *attr, Expression *expr_ ) :
     205                Expression(), attr( attr ), expr(expr_), type(0), isType(false) {
     206}
     207
     208AttrExpr::AttrExpr( Expression *attr, Type *type_ ) :
     209                Expression(), attr( attr ), expr(0), type(type_), isType(true) {
    254210}
    255211
     
    264220}
    265221
    266 void AttrExpr::print( std::ostream &os, int indent) const {
     222void AttrExpr::print( std::ostream &os, Indenter indent) const {
    267223        os << "Attr ";
    268         attr->print( os, indent + 2 );
     224        attr->print( os, indent+1);
    269225        if ( isType || expr ) {
    270226                os << "applied to: ";
    271 
    272                 if (isType)
    273                         type->print(os, indent + 2);
    274                 else
    275                         expr->print(os, indent + 2);
     227                if (isType) type->print(os, indent+1);
     228                else expr->print(os, indent+1);
    276229        } // if
    277 
    278         os << std::endl;
    279         Expression::print( os, indent );
    280 }
    281 
    282 CastExpr::CastExpr( Expression *arg_, Type *toType, Expression *_aname ) : Expression( _aname ), arg(arg_) {
     230        Expression::print( os, indent );
     231}
     232
     233CastExpr::CastExpr( Expression *arg_, Type *toType ) : Expression(), arg(arg_) {
    283234        set_result(toType);
    284235}
    285236
    286 CastExpr::CastExpr( Expression *arg_, Expression *_aname ) : Expression( _aname ), arg(arg_) {
     237CastExpr::CastExpr( Expression *arg_ ) : Expression(), arg(arg_) {
    287238        set_result( new VoidType( Type::Qualifiers() ) );
    288239}
     
    295246}
    296247
    297 void CastExpr::print( std::ostream &os, int indent ) const {
    298         os << "Cast of:" << std::endl << std::string( indent+2, ' ' );
    299         arg->print(os, indent+2);
    300         os << std::endl << std::string( indent, ' ' ) << "to:" << std::endl;
    301         os << std::string( indent+2, ' ' );
     248void CastExpr::print( std::ostream &os, Indenter indent ) const {
     249        os << "Cast of:" << std::endl << indent+1;
     250        arg->print(os, indent+1);
     251        os << std::endl << indent << "... to:";
    302252        if ( result->isVoid() ) {
    303                 os << "nothing";
     253                os << " nothing";
    304254        } else {
    305                 result->print( os, indent+2 );
     255                os << std::endl << indent+1;
     256                result->print( os, indent+1 );
    306257        } // if
    307         os << std::endl;
    308258        Expression::print( os, indent );
    309259}
     
    320270}
    321271
    322 void VirtualCastExpr::print( std::ostream &os, int indent ) const {
    323         os << "Virtual Cast of:" << std::endl << std::string( indent+2, ' ' );
    324         arg->print(os, indent+2);
    325         os << std::endl << std::string( indent, ' ' ) << "to:" << std::endl;
    326         os << std::string( indent+2, ' ' );
     272void VirtualCastExpr::print( std::ostream &os, Indenter indent ) const {
     273        os << "Virtual Cast of:" << std::endl << indent+1;
     274        arg->print(os, indent+1);
     275        os << std::endl << indent << "... to:";
    327276        if ( ! result ) {
    328                 os << "unknown";
     277                os << " unknown";
    329278        } else {
    330                 result->print( os, indent+2 );
     279                os << std::endl << indent+1;
     280                result->print( os, indent+1 );
    331281        } // if
    332         os << std::endl;
    333         Expression::print( os, indent );
    334 }
    335 
    336 UntypedMemberExpr::UntypedMemberExpr( Expression * _member, Expression *_aggregate, Expression *_aname ) :
    337                 Expression( _aname ), member(_member), aggregate(_aggregate) {}
     282        Expression::print( os, indent );
     283}
     284
     285UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression *aggregate ) :
     286                Expression(), member(member), aggregate(aggregate) {
     287        assert( aggregate );
     288}
    338289
    339290UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr &other ) :
     
    346297}
    347298
    348 void UntypedMemberExpr::print( std::ostream &os, int indent ) const {
    349         os << "Untyped Member Expression, with field: " << std::endl;
    350         os << std::string( indent+2, ' ' );
    351         get_member()->print(os, indent+4);
    352         os << std::string( indent+2, ' ' );
    353 
    354         Expression *agg = get_aggregate();
    355         os << "from aggregate: " << std::endl;
    356         if (agg != 0) {
    357                 os << std::string( indent + 4, ' ' );
    358                 agg->print(os, indent + 4);
    359         }
    360         os << std::string( indent+2, ' ' );
     299void UntypedMemberExpr::print( std::ostream &os, Indenter indent ) const {
     300        os << "Untyped Member Expression, with field: " << std::endl << indent+1;
     301        member->print(os, indent+1 );
     302        os << indent << "... from aggregate: " << std::endl << indent+1;
     303        aggregate->print(os, indent+1);
    361304        Expression::print( os, indent );
    362305}
     
    377320
    378321
    379 MemberExpr::MemberExpr( DeclarationWithType *_member, Expression *_aggregate, Expression *_aname ) :
    380                 Expression( _aname ), member(_member), aggregate(_aggregate) {
     322MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
     323                Expression(), member(member), aggregate(aggregate) {
     324        assert( member );
     325        assert( aggregate );
    381326
    382327        TypeSubstitution sub( makeSub( aggregate->get_result() ) );
     
    396341}
    397342
    398 void MemberExpr::print( std::ostream &os, int indent ) const {
     343void MemberExpr::print( std::ostream &os, Indenter indent ) const {
    399344        os << "Member Expression, with field: " << std::endl;
    400 
    401         assert( member );
    402         os << std::string( indent + 2, ' ' );
    403         member->print( os, indent + 2 );
    404         os << std::endl;
    405 
    406         Expression *agg = get_aggregate();
    407         os << std::string( indent, ' ' ) << "from aggregate: " << std::endl;
    408         if (agg != 0) {
    409                 os << std::string( indent + 2, ' ' );
    410                 agg->print(os, indent + 2);
    411         }
    412         os << std::string( indent+2, ' ' );
    413         Expression::print( os, indent );
    414 }
    415 
    416 UntypedExpr::UntypedExpr( Expression *_function, const std::list<Expression *> &_args, Expression *_aname ) :
    417                 Expression( _aname ), function(_function), args(_args) {}
     345        os << indent+1;
     346        member->print( os, indent+1 );
     347        os << std::endl << indent << "... from aggregate: " << std::endl << indent+1;
     348        aggregate->print(os, indent + 1);
     349        Expression::print( os, indent );
     350}
     351
     352UntypedExpr::UntypedExpr( Expression *function, const std::list<Expression *> &args ) :
     353                Expression(), function(function), args(args) {}
    418354
    419355UntypedExpr::UntypedExpr( const UntypedExpr &other ) :
     
    456392
    457393
    458 void UntypedExpr::print( std::ostream &os, int indent ) const {
     394void UntypedExpr::print( std::ostream &os, Indenter indent ) const {
    459395        os << "Applying untyped: " << std::endl;
    460         os << std::string( indent+2, ' ' );
    461         function->print(os, indent + 2);
    462         os << std::string( indent, ' ' ) << "...to: " << std::endl;
    463         printAll(args, os, indent + 2);
    464         Expression::print( os, indent );
    465 }
    466 
    467 void UntypedExpr::printArgs( std::ostream &os, int indent ) const {
    468         std::list<Expression *>::const_iterator i;
    469         for (i = args.begin(); i != args.end(); i++) {
    470                 os << std::string(indent, ' ' );
    471                 (*i)->print(os, indent);
    472         }
    473 }
    474 
    475 NameExpr::NameExpr( std::string _name, Expression *_aname ) : Expression( _aname ), name(_name) {
    476         assertf(_name != "0", "Zero is not a valid name\n");
    477         assertf(_name != "1", "One is not a valid name\n");
     396        os << indent+1;
     397        function->print(os, indent+1);
     398        os << std::endl << indent << "...to: " << std::endl;
     399        printAll(args, os, indent+1);
     400        Expression::print( os, indent );
     401}
     402
     403NameExpr::NameExpr( std::string name ) : Expression(), name(name) {
     404        assertf(name != "0", "Zero is not a valid name");
     405        assertf(name != "1", "One is not a valid name");
    478406}
    479407
     
    483411NameExpr::~NameExpr() {}
    484412
    485 void NameExpr::print( std::ostream &os, int indent ) const {
    486         os << "Name: " << get_name() << std::endl;
    487         Expression::print( os, indent );
    488 }
    489 
    490 LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp, Expression *_aname ) :
    491                 Expression( _aname ), arg1(arg1_), arg2(arg2_), isAnd(andp) {
     413void NameExpr::print( std::ostream &os, Indenter indent ) const {
     414        os << "Name: " << get_name();
     415        Expression::print( os, indent );
     416}
     417
     418LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp ) :
     419                Expression(), arg1(arg1_), arg2(arg2_), isAnd(andp) {
    492420        set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    493421}
     
    502430}
    503431
    504 void LogicalExpr::print( std::ostream &os, int indent )const {
    505         os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
     432void LogicalExpr::print( std::ostream &os, Indenter indent )const {
     433        os << "Short-circuited operation (" << (isAnd ? "and" : "or") << ") on: ";
    506434        arg1->print(os);
    507435        os << " and ";
    508436        arg2->print(os);
    509         os << std::endl;
    510         Expression::print( os, indent );
    511 }
    512 
    513 ConditionalExpr::ConditionalExpr( Expression *arg1_, Expression *arg2_, Expression *arg3_, Expression *_aname ) :
    514                 Expression( _aname ), arg1(arg1_), arg2(arg2_), arg3(arg3_) {}
     437        Expression::print( os, indent );
     438}
     439
     440ConditionalExpr::ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 ) :
     441                Expression(), arg1(arg1), arg2(arg2), arg3(arg3) {}
    515442
    516443ConditionalExpr::ConditionalExpr( const ConditionalExpr &other ) :
     
    524451}
    525452
    526 void ConditionalExpr::print( std::ostream &os, int indent ) const {
    527         os << "Conditional expression on: " << std::endl;
    528         os << std::string( indent+2, ' ' );
    529         arg1->print( os, indent+2 );
    530         os << std::string( indent, ' ' ) << "First alternative:" << std::endl;
    531         os << std::string( indent+2, ' ' );
    532         arg2->print( os, indent+2 );
    533         os << std::string( indent, ' ' ) << "Second alternative:" << std::endl;
    534         os << std::string( indent+2, ' ' );
    535         arg3->print( os, indent+2 );
    536         os << std::endl;
     453void ConditionalExpr::print( std::ostream &os, Indenter indent ) const {
     454        os << "Conditional expression on: " << std::endl << indent+1;
     455        arg1->print( os, indent+1 );
     456        os << indent << "First alternative:" << std::endl << indent+1;
     457        arg2->print( os, indent+1 );
     458        os << indent << "Second alternative:" << std::endl << indent+1;
     459        arg3->print( os, indent+1 );
    537460        Expression::print( os, indent );
    538461}
     
    541464
    542465
    543 void AsmExpr::print( std::ostream &os, int indent ) const {
     466void AsmExpr::print( std::ostream &os, Indenter indent ) const {
    544467        os << "Asm Expression: " << std::endl;
    545         if ( inout ) inout->print( os, indent + 2 );
    546         if ( constraint ) constraint->print( os, indent + 2 );
    547         if ( operand ) operand->print( os, indent + 2 );
     468        if ( inout ) inout->print( os, indent+1 );
     469        if ( constraint ) constraint->print( os, indent+1 );
     470        if ( operand ) operand->print( os, indent+1 );
    548471}
    549472
     
    551474ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {
    552475        assert( callExpr );
    553         assert( callExpr->has_result() );
     476        assert( callExpr->result );
    554477        set_result( callExpr->get_result()->clone() );
    555478}
     
    569492}
    570493
    571 void ImplicitCopyCtorExpr::print( std::ostream &os, int indent ) const {
    572         os <<  "Implicit Copy Constructor Expression: " << std::endl;
    573         assert( callExpr );
    574         os << std::string( indent+2, ' ' );
    575         callExpr->print( os, indent + 2 );
    576         os << std::endl << std::string( indent, ' ' ) << "with temporaries:" << std::endl;
    577         printAll(tempDecls, os, indent+2);
    578         os << std::endl << std::string( indent, ' ' ) << "with return temporaries:" << std::endl;
    579         printAll(returnDecls, os, indent+2);
     494void ImplicitCopyCtorExpr::print( std::ostream &os, Indenter indent ) const {
     495        os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
     496        callExpr->print( os, indent+1 );
     497        os << std::endl << indent << "... with temporaries:" << std::endl;
     498        printAll( tempDecls, os, indent+1 );
     499        os << std::endl << indent << "... with return temporaries:" << std::endl;
     500        printAll( returnDecls, os, indent+1 );
    580501        Expression::print( os, indent );
    581502}
     
    587508        Expression * arg = InitTweak::getCallArg( callExpr, 0 );
    588509        assert( arg );
    589         set_result( maybeClone( arg->get_result() ) );
     510        set_result( maybeClone( arg->result ) );
    590511}
    591512
     
    597518}
    598519
    599 void ConstructorExpr::print( std::ostream &os, int indent ) const {
    600         os <<  "Constructor Expression: " << std::endl;
    601         assert( callExpr );
    602         os << std::string( indent+2, ' ' );
     520void ConstructorExpr::print( std::ostream &os, Indenter indent ) const {
     521        os <<  "Constructor Expression: " << std::endl << indent+1;
    603522        callExpr->print( os, indent + 2 );
    604523        Expression::print( os, indent );
     
    618537}
    619538
    620 void CompoundLiteralExpr::print( std::ostream &os, int indent ) const {
    621         os << "Compound Literal Expression: " << std::endl;
    622         os << std::string( indent+2, ' ' );
    623         get_result()->print( os, indent + 2 );
    624         os << std::string( indent+2, ' ' );
    625         initializer->print( os, indent + 2 );
     539void CompoundLiteralExpr::print( std::ostream &os, Indenter indent ) const {
     540        os << "Compound Literal Expression: " << std::endl << indent+1;
     541        result->print( os, indent+1 );
     542        os << indent+1;
     543        initializer->print( os, indent+1 );
    626544        Expression::print( os, indent );
    627545}
     
    629547RangeExpr::RangeExpr( Expression *low, Expression *high ) : low( low ), high( high ) {}
    630548RangeExpr::RangeExpr( const RangeExpr &other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
    631 void RangeExpr::print( std::ostream &os, int indent ) const {
     549void RangeExpr::print( std::ostream &os, Indenter indent ) const {
    632550        os << "Range Expression: ";
    633551        low->print( os, indent );
     
    659577        deleteAll( returnDecls );
    660578}
    661 void StmtExpr::print( std::ostream &os, int indent ) const {
    662         os << "Statement Expression: " << std::endl << std::string( indent, ' ' );
    663         statements->print( os, indent+2 );
     579void StmtExpr::print( std::ostream &os, Indenter indent ) const {
     580        os << "Statement Expression: " << std::endl << indent+1;
     581        statements->print( os, indent+1 );
    664582        if ( ! returnDecls.empty() ) {
    665                 os << std::string( indent+2, ' ' ) << "with returnDecls: ";
    666                 printAll( returnDecls, os, indent+2 );
     583                os << indent+1 << "... with returnDecls: ";
     584                printAll( returnDecls, os, indent+1 );
    667585        }
    668586        if ( ! dtors.empty() ) {
    669                 os << std::string( indent+2, ' ' ) << "with dtors: ";
    670                 printAll( dtors, os, indent+2 );
     587                os << indent+1 << "... with dtors: ";
     588                printAll( dtors, os, indent+1 );
    671589        }
    672590        Expression::print( os, indent );
     
    690608        delete var;
    691609}
    692 void UniqueExpr::print( std::ostream &os, int indent ) const {
    693         os << "Unique Expression with id:" << id << std::endl << std::string( indent+2, ' ' );
    694         get_expr()->print( os, indent+2 );
    695         if ( get_object() ) {
    696                 os << std::string( indent+2, ' ' ) << "with decl: ";
    697                 get_object()->printShort( os, indent+2 );
     610void UniqueExpr::print( std::ostream &os, Indenter indent ) const {
     611        os << "Unique Expression with id:" << id << std::endl << indent+1;
     612        expr->print( os, indent+1 );
     613        if ( object ) {
     614                os << indent << "... with decl: ";
     615                get_object()->printShort( os, indent+1 );
    698616        }
    699617        Expression::print( os, indent );
     
    713631}
    714632
    715 void UntypedInitExpr::print( std::ostream & os, int indent ) const {
    716         os << "Untyped Init Expression" << std::endl << std::string( indent+2, ' ' );
    717         expr->print( os, indent+2 );
     633void UntypedInitExpr::print( std::ostream & os, Indenter indent ) const {
     634        os << "Untyped Init Expression" << std::endl << indent+1;
     635        expr->print( os, indent+1 );
    718636        if ( ! initAlts.empty() ) {
    719637                for ( const InitAlternative & alt : initAlts ) {
    720                         os << std::string( indent+2, ' ' ) <<  "InitAlternative: ";
    721                         alt.type->print( os, indent+2 );
    722                         alt.designation->print( os, indent+2 );
     638                        os << indent+1 <<  "InitAlternative: ";
     639                        alt.type->print( os, indent+1 );
     640                        alt.designation->print( os, indent+1 );
    723641                }
    724642        }
     
    734652}
    735653
    736 void InitExpr::print( std::ostream & os, int indent ) const {
    737         os << "Init Expression" << std::endl << std::string( indent+2, ' ' );
    738         expr->print( os, indent+2 );
    739         os << std::string( indent+2, ' ' ) << "with designation: ";
    740         designation->print( os, indent+2 );
     654void InitExpr::print( std::ostream & os, Indenter indent ) const {
     655        os << "Init Expression" << std::endl << indent+1;
     656        expr->print( os, indent+1 );
     657        os << indent+1 << "... with designation: ";
     658        designation->print( os, indent+1 );
    741659}
    742660
  • src/SynTree/Expression.h

    rb96ec83 r6840e7c  
    3636        Type * result;
    3737        TypeSubstitution * env;
    38         Expression * argName; // if expression is used as an argument, it can be "designated" by this name
    3938        bool extension = false;
    4039
    41         Expression( Expression * _aname = nullptr );
     40        Expression();
    4241        Expression( const Expression & other );
    4342        virtual ~Expression();
     
    4645        const Type * get_result() const { return result; }
    4746        void set_result( Type * newValue ) { result = newValue; }
    48         bool has_result() const { return result != nullptr; }
    4947
    5048        TypeSubstitution * get_env() const { return env; }
    5149        void set_env( TypeSubstitution * newValue ) { env = newValue; }
    52         Expression * get_argName() const { return argName; }
    53         void set_argName( Expression * name ) { argName = name; }
    5450        bool get_extension() const { return extension; }
    5551        Expression * set_extension( bool exten ) { extension = exten; return this; }
    5652
    57         virtual Expression * clone() const = 0;
    58         virtual void accept( Visitor & v ) = 0;
    59         virtual Expression * acceptMutator( Mutator & m ) = 0;
    60         virtual void print( std::ostream & os, int indent = 0 ) const;
     53        virtual Expression * clone() const override = 0;
     54        virtual void accept( Visitor & v ) override = 0;
     55        virtual Expression * acceptMutator( Mutator & m ) override = 0;
     56        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    6157};
    6258
     
    10197        virtual void accept( Visitor & v ) { v.visit( this ); }
    10298        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    103         virtual void print( std::ostream & os, int indent = 0 ) const;
     99        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    104100};
    105101
     
    112108        std::list<Expression*> args;
    113109
    114         UntypedExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >(), Expression *_aname = nullptr );
     110        UntypedExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >() );
    115111        UntypedExpr( const UntypedExpr & other );
    116112        virtual ~UntypedExpr();
     
    119115        void set_function( Expression * newValue ) { function = newValue; }
    120116
    121         void set_args( std::list<Expression *> & listArgs ) { args = listArgs; }
    122117        std::list<Expression*>::iterator begin_args() { return args.begin(); }
    123118        std::list<Expression*>::iterator end_args() { return args.end(); }
     
    130125        virtual void accept( Visitor & v ) { v.visit( this ); }
    131126        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    132         virtual void print( std::ostream & os, int indent = 0 ) const;
    133         virtual void printArgs(std::ostream & os, int indent = 0) const;
     127        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    134128};
    135129
     
    139133        std::string name;
    140134
    141         NameExpr( std::string name, Expression *_aname = nullptr );
     135        NameExpr( std::string name );
    142136        NameExpr( const NameExpr & other );
    143137        virtual ~NameExpr();
     
    149143        virtual void accept( Visitor & v ) { v.visit( this ); }
    150144        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    151         virtual void print( std::ostream & os, int indent = 0 ) const;
     145        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    152146};
    153147
     
    160154        Expression * arg;
    161155
    162         AddressExpr( Expression * arg, Expression *_aname = nullptr );
     156        AddressExpr( Expression * arg );
    163157        AddressExpr( const AddressExpr & other );
    164158        virtual ~AddressExpr();
     
    170164        virtual void accept( Visitor & v ) { v.visit( this ); }
    171165        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    172         virtual void print( std::ostream & os, int indent = 0 ) const;
     166        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    173167};
    174168
     
    186180        virtual void accept( Visitor & v ) { v.visit( this ); }
    187181        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    188         virtual void print( std::ostream & os, int indent = 0 ) const;
     182        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    189183};
    190184
     
    194188        Expression * arg;
    195189
    196         CastExpr( Expression * arg, Expression *_aname = nullptr );
    197         CastExpr( Expression * arg, Type * toType, Expression *_aname = nullptr );
     190        CastExpr( Expression * arg );
     191        CastExpr( Expression * arg, Type * toType );
    198192        CastExpr( const CastExpr & other );
    199193        virtual ~CastExpr();
     
    205199        virtual void accept( Visitor & v ) { v.visit( this ); }
    206200        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    207         virtual void print( std::ostream & os, int indent = 0 ) const;
     201        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    208202};
    209203
     
    223217        virtual void accept( Visitor & v ) { v.visit( this ); }
    224218        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    225         virtual void print( std::ostream & os, int indent = 0 ) const;
     219        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    226220};
    227221
     
    232226        Expression * aggregate;
    233227
    234         UntypedMemberExpr( Expression * member, Expression * aggregate, Expression *_aname = nullptr );
     228        UntypedMemberExpr( Expression * member, Expression * aggregate );
    235229        UntypedMemberExpr( const UntypedMemberExpr & other );
    236230        virtual ~UntypedMemberExpr();
     
    244238        virtual void accept( Visitor & v ) { v.visit( this ); }
    245239        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    246         virtual void print( std::ostream & os, int indent = 0 ) const;
     240        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    247241};
    248242
     
    254248        Expression * aggregate;
    255249
    256         MemberExpr( DeclarationWithType * member, Expression * aggregate, Expression *_aname = nullptr );
     250        MemberExpr( DeclarationWithType * member, Expression * aggregate );
    257251        MemberExpr( const MemberExpr & other );
    258252        virtual ~MemberExpr();
     
    266260        virtual void accept( Visitor & v ) { v.visit( this ); }
    267261        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    268         virtual void print( std::ostream & os, int indent = 0 ) const;
     262        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    269263};
    270264
     
    275269        DeclarationWithType * var;
    276270
    277         VariableExpr( DeclarationWithType * var, Expression *_aname = nullptr );
     271        VariableExpr( DeclarationWithType * var );
    278272        VariableExpr( const VariableExpr & other );
    279273        virtual ~VariableExpr();
     
    287281        virtual void accept( Visitor & v ) { v.visit( this ); }
    288282        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    289         virtual void print( std::ostream & os, int indent = 0 ) const;
     283        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    290284};
    291285
     
    295289        Constant constant;
    296290
    297         ConstantExpr( Constant constant, Expression *_aname = nullptr );
     291        ConstantExpr( Constant constant );
    298292        ConstantExpr( const ConstantExpr & other );
    299293        virtual ~ConstantExpr();
     
    305299        virtual void accept( Visitor & v ) { v.visit( this ); }
    306300        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    307         virtual void print( std::ostream & os, int indent = 0 ) const;
     301        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    308302};
    309303
     
    315309        bool isType;
    316310
    317         SizeofExpr( Expression * expr, Expression *_aname = nullptr );
     311        SizeofExpr( Expression * expr );
    318312        SizeofExpr( const SizeofExpr & other );
    319         SizeofExpr( Type * type, Expression *_aname = nullptr );
     313        SizeofExpr( Type * type );
    320314        virtual ~SizeofExpr();
    321315
     
    330324        virtual void accept( Visitor & v ) { v.visit( this ); }
    331325        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    332         virtual void print( std::ostream & os, int indent = 0 ) const;
     326        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    333327};
    334328
     
    340334        bool isType;
    341335
    342         AlignofExpr( Expression * expr, Expression *_aname = nullptr );
     336        AlignofExpr( Expression * expr );
    343337        AlignofExpr( const AlignofExpr & other );
    344         AlignofExpr( Type * type, Expression *_aname = nullptr );
     338        AlignofExpr( Type * type );
    345339        virtual ~AlignofExpr();
    346340
     
    355349        virtual void accept( Visitor & v ) { v.visit( this ); }
    356350        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    357         virtual void print( std::ostream & os, int indent = 0 ) const;
     351        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    358352};
    359353
     
    364358        std::string member;
    365359
    366         UntypedOffsetofExpr( Type * type, const std::string & member, Expression *_aname = nullptr );
     360        UntypedOffsetofExpr( Type * type, const std::string & member );
    367361        UntypedOffsetofExpr( const UntypedOffsetofExpr & other );
    368362        virtual ~UntypedOffsetofExpr();
     
    376370        virtual void accept( Visitor & v ) { v.visit( this ); }
    377371        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    378         virtual void print( std::ostream & os, int indent = 0 ) const;
     372        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    379373};
    380374
     
    385379        DeclarationWithType * member;
    386380
    387         OffsetofExpr( Type * type, DeclarationWithType * member, Expression *_aname = nullptr );
     381        OffsetofExpr( Type * type, DeclarationWithType * member );
    388382        OffsetofExpr( const OffsetofExpr & other );
    389383        virtual ~OffsetofExpr();
     
    397391        virtual void accept( Visitor & v ) { v.visit( this ); }
    398392        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    399         virtual void print( std::ostream & os, int indent = 0 ) const;
     393        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    400394};
    401395
     
    405399        StructInstType * type;
    406400
    407         OffsetPackExpr( StructInstType * type_, Expression * aname_ = 0 );
     401        OffsetPackExpr( StructInstType * type );
    408402        OffsetPackExpr( const OffsetPackExpr & other );
    409403        virtual ~OffsetPackExpr();
     
    415409        virtual void accept( Visitor & v ) { v.visit( this ); }
    416410        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    417         virtual void print( std::ostream & os, int indent = 0 ) const;
     411        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    418412};
    419413
     
    426420        bool isType;
    427421
    428         AttrExpr(Expression * attr, Expression * expr, Expression *_aname = nullptr );
     422        AttrExpr(Expression * attr, Expression * expr );
    429423        AttrExpr( const AttrExpr & other );
    430         AttrExpr( Expression * attr, Type * type, Expression *_aname = nullptr );
     424        AttrExpr( Expression * attr, Type * type );
    431425        virtual ~AttrExpr();
    432426
     
    443437        virtual void accept( Visitor & v ) { v.visit( this ); }
    444438        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    445         virtual void print( std::ostream & os, int indent = 0 ) const;
     439        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    446440};
    447441
     
    452446        Expression * arg2;
    453447
    454         LogicalExpr( Expression * arg1, Expression * arg2, bool andp = true, Expression *_aname = nullptr );
     448        LogicalExpr( Expression * arg1, Expression * arg2, bool andp = true );
    455449        LogicalExpr( const LogicalExpr & other );
    456450        virtual ~LogicalExpr();
     
    465459        virtual void accept( Visitor & v ) { v.visit( this ); }
    466460        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    467         virtual void print( std::ostream & os, int indent = 0 ) const;
     461        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    468462
    469463  private:
     
    478472        Expression * arg3;
    479473
    480         ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3, Expression *_aname = nullptr );
     474        ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 );
    481475        ConditionalExpr( const ConditionalExpr & other );
    482476        virtual ~ConditionalExpr();
     
    492486        virtual void accept( Visitor & v ) { v.visit( this ); }
    493487        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    494         virtual void print( std::ostream & os, int indent = 0 ) const;
     488        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    495489};
    496490
     
    501495        Expression * arg2;
    502496
    503         CommaExpr( Expression * arg1, Expression * arg2, Expression *_aname = nullptr );
     497        CommaExpr( Expression * arg1, Expression * arg2 );
    504498        CommaExpr( const CommaExpr & other );
    505499        virtual ~CommaExpr();
     
    513507        virtual void accept( Visitor & v ) { v.visit( this ); }
    514508        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    515         virtual void print( std::ostream & os, int indent = 0 ) const;
     509        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    516510};
    517511
     
    531525        virtual void accept( Visitor & v ) { v.visit( this ); }
    532526        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    533         virtual void print( std::ostream & os, int indent = 0 ) const;
     527        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    534528};
    535529
     
    557551        virtual void accept( Visitor & v ) { v.visit( this ); }
    558552        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    559         virtual void print( std::ostream & os, int indent = 0 ) const;
     553        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    560554
    561555        // https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
     
    585579        virtual void accept( Visitor & v ) { v.visit( this ); }
    586580        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    587         virtual void print( std::ostream & os, int indent = 0 ) const;
     581        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    588582};
    589583
     
    603597        virtual void accept( Visitor & v ) { v.visit( this ); }
    604598        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    605         virtual void print( std::ostream & os, int indent = 0 ) const;
     599        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    606600};
    607601
     
    621615        virtual void accept( Visitor & v ) { v.visit( this ); }
    622616        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    623         virtual void print( std::ostream & os, int indent = 0 ) const;
     617        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    624618};
    625619
     
    640634        virtual void accept( Visitor & v ) { v.visit( this ); }
    641635        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    642         virtual void print( std::ostream & os, int indent = 0 ) const;
     636        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    643637};
    644638
     
    648642        std::list<Expression*> exprs;
    649643
    650         UntypedTupleExpr( const std::list< Expression * > & exprs, Expression *_aname = nullptr );
     644        UntypedTupleExpr( const std::list< Expression * > & exprs );
    651645        UntypedTupleExpr( const UntypedTupleExpr & other );
    652646        virtual ~UntypedTupleExpr();
     
    657651        virtual void accept( Visitor & v ) { v.visit( this ); }
    658652        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    659         virtual void print( std::ostream & os, int indent = 0 ) const;
     653        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    660654};
    661655
     
    665659        std::list<Expression*> exprs;
    666660
    667         TupleExpr( const std::list< Expression * > & exprs, Expression *_aname = nullptr );
     661        TupleExpr( const std::list< Expression * > & exprs );
    668662        TupleExpr( const TupleExpr & other );
    669663        virtual ~TupleExpr();
     
    674668        virtual void accept( Visitor & v ) { v.visit( this ); }
    675669        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    676         virtual void print( std::ostream & os, int indent = 0 ) const;
     670        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    677671};
    678672
     
    695689        virtual void accept( Visitor & v ) { v.visit( this ); }
    696690        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    697         virtual void print( std::ostream & os, int indent = 0 ) const;
     691        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    698692};
    699693
     
    703697        StmtExpr * stmtExpr = nullptr;
    704698
    705         TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname = nullptr );
     699        TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls );
    706700        TupleAssignExpr( const TupleAssignExpr & other );
    707701        virtual ~TupleAssignExpr();
     
    713707        virtual void accept( Visitor & v ) { v.visit( this ); }
    714708        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    715         virtual void print( std::ostream & os, int indent = 0 ) const;
     709        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    716710};
    717711
     
    736730        virtual void accept( Visitor & v ) { v.visit( this ); }
    737731        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    738         virtual void print( std::ostream & os, int indent = 0 ) const;
     732        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    739733};
    740734
     
    763757        virtual void accept( Visitor & v ) { v.visit( this ); }
    764758        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    765         virtual void print( std::ostream & os, int indent = 0 ) const;
     759        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    766760
    767761private:
     
    797791        virtual void accept( Visitor & v ) { v.visit( this ); }
    798792        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    799         virtual void print( std::ostream & os, int indent = 0 ) const;
     793        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    800794};
    801795
     
    818812        virtual void accept( Visitor & v ) { v.visit( this ); }
    819813        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    820         virtual void print( std::ostream & os, int indent = 0 ) const;
     814        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    821815};
    822816
  • src/SynTree/FunctionDecl.cc

    rb96ec83 r6840e7c  
    6363}
    6464
    65 void FunctionDecl::print( std::ostream &os, int indent ) const {
     65void FunctionDecl::print( std::ostream &os, Indenter indent ) const {
    6666        using std::endl;
    6767        using std::string;
    6868
    69         if ( get_name() != "" ) {
    70                 os << get_name() << ": ";
     69        if ( name != "" ) {
     70                os << name << ": ";
    7171        } // if
    72         if ( get_linkage() != LinkageSpec::Cforall ) {
    73                 os << LinkageSpec::linkageName( get_linkage() ) << " ";
     72        if ( linkage != LinkageSpec::Cforall ) {
     73                os << LinkageSpec::linkageName( linkage ) << " ";
    7474        } // if
    7575
    76         printAll( get_attributes(), os, indent );
     76        printAll( attributes, os, indent );
    7777
    7878        get_storageClasses().print( os );
    7979        get_funcSpec().print( os );
    8080
    81         if ( get_type() ) {
    82                 get_type()->print( os, indent );
     81        if ( type ) {
     82                type->print( os, indent );
    8383        } else {
    8484                os << "untyped entity ";
     
    8686
    8787        if ( statements ) {
    88                 os << string( indent + 2, ' ' ) << "with body " << endl;
    89                 os << string( indent + 4, ' ' );
    90                 statements->print( os, indent + 4 );
     88                os << indent << "... with body " << endl << indent+1;
     89                statements->print( os, indent+1 );
    9190        } // if
    9291}
    9392
    94 void FunctionDecl::printShort( std::ostream &os, int indent ) const {
     93void FunctionDecl::printShort( std::ostream &os, Indenter indent ) const {
    9594        using std::endl;
    9695        using std::string;
    9796
    98         if ( get_name() != "" ) {
    99                 os << get_name() << ": ";
     97        if ( name != "" ) {
     98                os << name << ": ";
    10099        } // if
    101 
    102         // xxx - should printShort print attributes?
    103100
    104101        get_storageClasses().print( os );
    105102        get_funcSpec().print( os );
    106103
    107         if ( get_type() ) {
    108                 get_type()->print( os, indent );
     104        if ( type ) {
     105                type->print( os, indent );
    109106        } else {
    110107                os << "untyped entity ";
  • src/SynTree/FunctionType.cc

    rb96ec83 r6840e7c  
    5151}
    5252
    53 void FunctionType::print( std::ostream &os, int indent ) const {
     53void FunctionType::print( std::ostream &os, Indenter indent ) const {
    5454        using std::string;
    5555        using std::endl;
     
    5858        os << "function" << endl;
    5959        if ( ! parameters.empty() ) {
    60                 os << string( indent + 2, ' ' ) << "with parameters" << endl;
    61                 printAll( parameters, os, indent + 4 );
     60                os << indent << "... with parameters" << endl;
     61                printAll( parameters, os, indent+1 );
    6262                if ( isVarArgs ) {
    63                         os << string( indent + 4, ' ' ) << "and a variable number of other arguments" << endl;
     63                        os << indent+1 << "and a variable number of other arguments" << endl;
    6464                } // if
    6565        } else if ( isVarArgs ) {
    66                 os << string( indent + 4, ' ' ) << "accepting unspecified arguments" << endl;
     66                os << indent+1 << "accepting unspecified arguments" << endl;
    6767        } // if
    68         os << string( indent + 2, ' ' ) << "returning ";
     68        os << indent << "... returning ";
    6969        if ( returnVals.empty() ) {
    70                 os << endl << string( indent + 4, ' ' ) << "nothing " << endl;
     70                os << "nothing " << endl;
    7171        } else {
    7272                os << endl;
    73                 printAll( returnVals, os, indent + 4 );
     73                printAll( returnVals, os, indent+1 );
    7474        } // if
    7575}
  • src/SynTree/Initializer.cc

    rb96ec83 r6840e7c  
    3838}
    3939
    40 void Designation::print( std::ostream &os, int indent ) const {
     40void Designation::print( std::ostream &os, Indenter indent ) const {
    4141        if ( ! designators.empty() ) {
    42                 os << std::string(indent + 2, ' ' ) << "designated by: " << std::endl;
    43                 for ( std::list < Expression * >::const_iterator i = designators.begin(); i != designators.end(); i++ ) {
    44                         os << std::string(indent + 4, ' ' );
    45                         ( *i )->print(os, indent + 4 );
     42                os << "... designated by: " << std::endl;
     43                for ( const Expression * d : designators ) {
     44                        os << indent+1;
     45                        d->print(os, indent+1 );
     46                        os << std::endl;
    4647                }
    47                 os << std::endl;
    4848        } // if
    4949}
     
    6464}
    6565
    66 void SingleInit::print( std::ostream &os, int indent ) const {
    67         os << std::string(indent, ' ' ) << "Simple Initializer: " << std::endl;
    68         os << std::string(indent+4, ' ' );
    69         value->print( os, indent+4 );
     66void SingleInit::print( std::ostream &os, Indenter indent ) const {
     67        os << "Simple Initializer: ";
     68        value->print( os, indent );
    7069}
    7170
     
    9392}
    9493
    95 void ListInit::print( std::ostream &os, int indent ) const {
    96         os << std::string(indent, ' ') << "Compound initializer:  " << std::endl;
    97         for ( Designation * d : designations ) {
    98                 d->print( os, indent + 2 );
    99         }
    100 
    101         for ( const Initializer * init : initializers ) {
    102                 init->print( os, indent + 2 );
     94void ListInit::print( std::ostream &os, Indenter indent ) const {
     95        os << "Compound initializer: " << std::endl;
     96        for ( auto p : group_iterate( designations, initializers ) ) {
     97                const Designation * d = std::get<0>(p);
     98                const Initializer * init = std::get<1>(p);
     99                os << indent+1;
     100                init->print( os, indent+1 );
    103101                os << std::endl;
     102                if ( ! d->designators.empty() ) {
     103                        os << indent+1;
     104                        d->print( os, indent+1 );
     105                }
    104106        }
    105107}
     
    116118}
    117119
    118 void ConstructorInit::print( std::ostream &os, int indent ) const {
    119         os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;
     120void ConstructorInit::print( std::ostream &os, Indenter indent ) const {
     121        os << "Constructor initializer: " << std::endl;
    120122        if ( ctor ) {
    121                 os << std::string(indent+2, ' ');
    122                 os << "initially constructed with ";
    123                 ctor->print( os, indent+4 );
     123                os << indent << "... initially constructed with ";
     124                ctor->print( os, indent+1 );
    124125        } // if
    125126
    126127        if ( dtor ) {
    127                 os << std::string(indent+2, ' ');
    128                 os << "destructed with ";
    129                 dtor->print( os, indent+4 );
     128                os << indent << "... destructed with ";
     129                dtor->print( os, indent+1 );
    130130        }
    131131
    132132        if ( init ) {
    133                 os << std::string(indent+2, ' ');
    134                 os << "with fallback C-style initializer: ";
    135                 init->print( os, indent+4 );
     133                os << indent << "... with fallback C-style initializer: ";
     134                init->print( os, indent+1 );
    136135        }
    137136}
  • src/SynTree/Initializer.h

    rb96ec83 r6840e7c  
    3737        std::list< Expression * > & get_designators() { return designators; }
    3838
    39         virtual Designation * clone() const { return new Designation( *this ); };
     39        virtual Designation * clone() const override { return new Designation( *this ); };
    4040        virtual void accept( Visitor &v ) override { v.visit( this ); }
    41         virtual Designation * acceptMutator( Mutator &m ) { return m.mutate( this ); }
    42         virtual void print( std::ostream &os, int indent = 0 ) const override;
     41        virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
     42        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    4343};
    4444
     
    5454        bool get_maybeConstructed() { return maybeConstructed; }
    5555
    56         virtual Initializer *clone() const = 0;
     56        virtual Initializer *clone() const override = 0;
    5757        virtual void accept( Visitor &v ) override = 0;
    58         virtual Initializer *acceptMutator( Mutator &m ) = 0;
    59         virtual void print( std::ostream &os, int indent = 0 ) const override = 0;
     58        virtual Initializer *acceptMutator( Mutator &m ) override = 0;
     59        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
    6060  private:
    6161        bool maybeConstructed;
     
    7878        virtual void accept( Visitor &v ) override { v.visit( this ); }
    7979        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    80         virtual void print( std::ostream &os, int indent = 0 ) const override;
     80        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    8181};
    8282
     
    106106        virtual void accept( Visitor &v ) override { v.visit( this ); }
    107107        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    108         virtual void print( std::ostream &os, int indent = 0 ) const override;
     108        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    109109};
    110110
     
    135135        virtual void accept( Visitor &v ) override { v.visit( this ); }
    136136        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    137         virtual void print( std::ostream &os, int indent = 0 ) const override;
     137        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    138138
    139139  private:
  • src/SynTree/Mutator.cc

    rb96ec83 r6840e7c  
    626626}
    627627
     628TypeSubstitution * Mutator::mutate( TypeSubstitution * sub ) {
     629        for ( auto & p : sub->typeEnv ) {
     630                p.second = maybeMutate( p.second, *this );
     631        }
     632        for ( auto & p : sub->varEnv ) {
     633                p.second = maybeMutate( p.second, *this );
     634        }
     635        return sub;
     636}
     637
    628638// Local Variables: //
    629639// tab-width: 4 //
  • src/SynTree/Mutator.h

    rb96ec83 r6840e7c  
    117117
    118118        virtual Attribute * mutate( Attribute * attribute );
     119
     120        virtual TypeSubstitution * mutate( TypeSubstitution * sub );
     121
    119122  private:
    120123        virtual Declaration * handleAggregateDecl(AggregateDecl * aggregateDecl );
  • src/SynTree/NamedTypeDecl.cc

    rb96ec83 r6840e7c  
    3838}
    3939
    40 void NamedTypeDecl::print( std::ostream &os, int indent ) const {
     40void NamedTypeDecl::print( std::ostream &os, Indenter indent ) const {
    4141        using namespace std;
    4242
    43         if ( get_name() != "" ) {
    44                 os << get_name() << ": ";
    45         } // if
    46         if ( get_linkage() != LinkageSpec::Cforall ) {
    47                 os << LinkageSpec::linkageName( get_linkage() ) << " ";
     43        if ( name != "" ) os << name << ": ";
     44
     45        if ( linkage != LinkageSpec::Cforall ) {
     46                os << LinkageSpec::linkageName( linkage ) << " ";
    4847        } // if
    4948        get_storageClasses().print( os );
     
    5150        if ( base ) {
    5251                os << " for ";
    53                 base->print( os, indent );
     52                base->print( os, indent+1 );
    5453        } // if
    5554        if ( ! parameters.empty() ) {
    56                 os << endl << string( indent, ' ' ) << "with parameters" << endl;
    57                 printAll( parameters, os, indent+2 );
     55                os << endl << indent << "... with parameters" << endl;
     56                printAll( parameters, os, indent+1 );
    5857        } // if
    5958        if ( ! assertions.empty() ) {
    60                 os << endl << string( indent, ' ' ) << "with assertions" << endl;
    61                 printAll( assertions, os, indent+2 );
     59                os << endl << indent << "... with assertions" << endl;
     60                printAll( assertions, os, indent+1 );
    6261        } // if
    6362}
    6463
    65 void NamedTypeDecl::printShort( std::ostream &os, int indent ) const {
     64void NamedTypeDecl::printShort( std::ostream &os, Indenter indent ) const {
    6665        using namespace std;
    6766
    68         if ( get_name() != "" ) {
    69                 os << get_name() << ": ";
    70         } // if
     67        if ( name != "" ) os << name << ": ";
    7168        get_storageClasses().print( os );
    7269        os << typeString();
    7370        if ( base ) {
    7471                os << " for ";
    75                 base->print( os, indent );
     72                base->print( os, indent+1 );
    7673        } // if
    7774        if ( ! parameters.empty() ) {
    78                 os << endl << string( indent, ' ' ) << "with parameters" << endl;
    79                 printAll( parameters, os, indent+2 );
     75                os << endl << indent << "... with parameters" << endl;
     76                printAll( parameters, os, indent+1 );
    8077        } // if
    8178}
  • src/SynTree/ObjectDecl.cc

    rb96ec83 r6840e7c  
    4444}
    4545
    46 void ObjectDecl::print( std::ostream &os, int indent ) const {
    47         if ( get_name() != "" ) {
    48                 os << get_name() << ": ";
     46void ObjectDecl::print( std::ostream &os, Indenter indent ) const {
     47        if ( name != "" ) os << name << ": ";
     48
     49        if ( linkage != LinkageSpec::Cforall ) {
     50                os << LinkageSpec::linkageName( linkage ) << " ";
    4951        } // if
    50 
    51         if ( get_linkage() != LinkageSpec::Cforall ) {
    52                 os << LinkageSpec::linkageName( get_linkage() ) << " ";
    53         } // if
    54 
    55         printAll( get_attributes(), os, indent );
    5652
    5753        get_storageClasses().print( os );
    5854
    59         if ( get_type() ) {
    60                 get_type()->print( os, indent );
     55        if ( type ) {
     56                type->print( os, indent );
    6157        } else {
    6258                os << " untyped entity ";
     
    6460
    6561        if ( init ) {
    66                 os << " with initializer " << std::endl;
    67                 init->print( os, indent+2 );
    68                 os << std::endl << std::string(indent+2, ' ');
    69                 os << "maybeConstructed? " << init->get_maybeConstructed();
     62                os << " with initializer (" << (init->get_maybeConstructed() ? "maybe constructed" : "not constructed") << ")" << std::endl << indent+1;
     63                init->print( os, indent+1 );
     64                os << std::endl;
    7065        } // if
    7166
     67        if ( ! attributes.empty() ) {
     68                os << std::endl << indent << "... with attributes: " << std::endl;
     69                printAll( attributes, os, indent+1 );
     70        }
     71
    7272        if ( bitfieldWidth ) {
    73                 os << std::string(indent, ' ');
    74                 os << " with bitfield width ";
     73                os << indent << " with bitfield width ";
    7574                bitfieldWidth->print( os );
    7675        } // if
    7776}
    7877
    79 void ObjectDecl::printShort( std::ostream &os, int indent ) const {
     78void ObjectDecl::printShort( std::ostream &os, Indenter indent ) const {
    8079#if 0
    8180        if ( get_mangleName() != "") {
     
    8382        } else
    8483#endif
    85         if ( get_name() != "" ) {
    86                 os << get_name() << ": ";
    87         } // if
    88 
    89         // xxx - should printShort print attributes?
     84        if ( name != "" ) os << name << ": ";
    9085
    9186        get_storageClasses().print( os );
    9287
    93         if ( get_type() ) {
    94                 get_type()->print( os, indent );
     88        if ( type ) {
     89                type->print( os, indent );
    9590        } else {
    9691                os << "untyped entity ";
  • src/SynTree/PointerType.cc

    rb96ec83 r6840e7c  
    4141}
    4242
    43 void PointerType::print( std::ostream &os, int indent ) const {
     43void PointerType::print( std::ostream &os, Indenter indent ) const {
    4444        Type::print( os, indent );
    4545        if ( ! is_array() ) {
  • src/SynTree/ReferenceToType.cc

    rb96ec83 r6840e7c  
    1414//
    1515
    16 #include <stddef.h>          // for NULL
    1716#include <cassert>           // for assert
    1817#include <list>              // for list, _List_const_iterator, list<>::cons...
     
    3837}
    3938
    40 void ReferenceToType::print( std::ostream &os, int indent ) const {
     39void ReferenceToType::print( std::ostream &os, Indenter indent ) const {
    4140        using std::endl;
    4241
     
    4443        os << "instance of " << typeString() << " " << name << " ";
    4544        if ( ! parameters.empty() ) {
    46                 os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
    47                 printAll( parameters, os, indent+2 );
     45                os << endl << indent << "... with parameters" << endl;
     46                printAll( parameters, os, indent+1 );
    4847        } // if
    4948}
     
    6564
    6665std::list<TypeDecl*>* StructInstType::get_baseParameters() {
    67         if ( ! baseStruct ) return NULL;
     66        if ( ! baseStruct ) return nullptr;
    6867        return &baseStruct->get_parameters();
    6968}
     
    7675}
    7776
    78 void StructInstType::print( std::ostream &os, int indent ) const {
     77void StructInstType::print( std::ostream &os, Indenter indent ) const {
    7978        using std::endl;
    8079
    81         if ( baseStruct == NULL ) ReferenceToType::print( os, indent );
     80        if ( baseStruct == nullptr ) ReferenceToType::print( os, indent );
    8281        else {
    8382                Type::print( os, indent );
    8483                os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body() << " ";
    8584                if ( ! parameters.empty() ) {
    86                         os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
    87                         printAll( parameters, os, indent+2 );
     85                        os << endl << indent << "... with parameters" << endl;
     86                        printAll( parameters, os, indent+1 );
    8887                } // if
    8988        } // if
     
    9796
    9897std::list< TypeDecl * > * UnionInstType::get_baseParameters() {
    99         if ( ! baseUnion ) return NULL;
     98        if ( ! baseUnion ) return nullptr;
    10099        return &baseUnion->get_parameters();
    101100}
     
    108107}
    109108
    110 void UnionInstType::print( std::ostream &os, int indent ) const {
     109void UnionInstType::print( std::ostream &os, Indenter indent ) const {
    111110        using std::endl;
    112111
    113         if ( baseUnion == NULL ) ReferenceToType::print( os, indent );
     112        if ( baseUnion == nullptr ) ReferenceToType::print( os, indent );
    114113        else {
    115114                Type::print( os, indent );
    116115                os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body() << " ";
    117116                if ( ! parameters.empty() ) {
    118                         os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
    119                         printAll( parameters, os, indent+2 );
     117                        os << endl << indent << "... with parameters" << endl;
     118                        printAll( parameters, os, indent+1 );
    120119                } // if
    121120        } // if
     
    129128
    130129bool EnumInstType::isComplete() const { return baseEnum ? baseEnum->has_body() : false; }
     130
     131void EnumInstType::print( std::ostream &os, Indenter indent ) const {
     132        using std::endl;
     133
     134        if ( baseEnum == nullptr ) ReferenceToType::print( os, indent );
     135        else {
     136                Type::print( os, indent );
     137                os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body() << " ";
     138        } // if
     139}
     140
    131141
    132142std::string TraitInstType::typeString() const { return "trait"; }
     
    166176bool TypeInstType::isComplete() const { return baseType->isComplete(); }
    167177
    168 void TypeInstType::print( std::ostream &os, int indent ) const {
     178void TypeInstType::print( std::ostream &os, Indenter indent ) const {
    169179        using std::endl;
    170180
     
    172182        os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type) ";
    173183        if ( ! parameters.empty() ) {
    174                 os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
    175                 printAll( parameters, os, indent+2 );
     184                os << endl << indent << "... with parameters" << endl;
     185                printAll( parameters, os, indent+1 );
    176186        } // if
    177187}
  • src/SynTree/ReferenceType.cc

    rb96ec83 r6840e7c  
    3535}
    3636
    37 void ReferenceType::print( std::ostream &os, int indent ) const {
     37void ReferenceType::print( std::ostream &os, Indenter indent ) const {
    3838        Type::print( os, indent );
    3939        os << "reference to ";
  • src/SynTree/Statement.cc

    rb96ec83 r6840e7c  
    3434Statement::Statement( std::list<Label> labels ) : labels( labels ) {}
    3535
    36 void Statement::print( __attribute__((unused)) std::ostream &, __attribute__((unused)) int indent ) const {}
     36void Statement::print( std::ostream & os, Indenter ) const {
     37        if ( ! labels.empty() ) {
     38                os << "Labels: {";
     39                for ( const Label & l : labels ) {
     40                        os << l << ",";
     41                }
     42                os << "}" << endl;
     43        }
     44}
    3745
    3846Statement::~Statement() {}
     
    4654}
    4755
    48 void ExprStmt::print( std::ostream &os, int indent ) const {
    49         os << "Expression Statement:" << endl << std::string( indent + 2, ' ' );
    50         expr->print( os, indent + 2 );
     56void ExprStmt::print( std::ostream &os, Indenter indent ) const {
     57        os << "Expression Statement:" << endl << indent+1;
     58        expr->print( os, indent+1 );
    5159}
    5260
     
    6775}
    6876
    69 void AsmStmt::print( std::ostream &os, int indent ) const {
     77void AsmStmt::print( std::ostream &os, Indenter indent ) const {
    7078        os << "Assembler Statement:" << endl;
    71         os << std::string( indent, ' ' ) << "instruction: " << endl << std::string( indent, ' ' );
    72         instruction->print( os, indent + 2 );
     79        os << indent+1 << "instruction: " << endl << indent;
     80        instruction->print( os, indent+1 );
    7381        if ( ! output.empty() ) {
    74                 os << endl << std::string( indent, ' ' ) << "output: " << endl;
    75                 printAll( output, os, indent + 2 );
     82                os << endl << indent+1 << "output: " << endl;
     83                printAll( output, os, indent+1 );
    7684        } // if
    7785        if ( ! input.empty() ) {
    78                 os << std::string( indent, ' ' ) << "input: " << endl << std::string( indent, ' ' );
    79                 printAll( input, os, indent + 2 );
     86                os << indent+1 << "input: " << endl;
     87                printAll( input, os, indent+1 );
    8088        } // if
    8189        if ( ! clobber.empty() ) {
    82                 os << std::string( indent, ' ' ) << "clobber: " << endl;
    83                 printAll( clobber, os, indent + 2 );
     90                os << indent+1 << "clobber: " << endl;
     91                printAll( clobber, os, indent+1 );
    8492        } // if
    8593}
     
    103111}
    104112
    105 void BranchStmt::print( std::ostream &os, int indent ) const {
    106         os << string( indent, ' ' ) << "Branch (" << brType[type] << ")" << endl ;
    107         if ( target != "" ) os << string( indent+2, ' ' ) << "with target: " << target << endl;
    108         if ( originalTarget != "" ) os << string( indent+2, ' ' ) << "with original target: " << originalTarget << endl;
    109         if ( computedTarget != nullptr ) os << string( indent+2, ' ' ) << "with computed target: " << computedTarget << endl;
     113void BranchStmt::print( std::ostream &os, Indenter indent ) const {
     114        os << "Branch (" << brType[type] << ")" << endl ;
     115        if ( target != "" ) os << indent+1 << "with target: " << target << endl;
     116        if ( originalTarget != "" ) os << indent+1 << "with original target: " << originalTarget << endl;
     117        if ( computedTarget != nullptr ) os << indent+1 << "with computed target: " << computedTarget << endl;
    110118}
    111119
     
    118126}
    119127
    120 void ReturnStmt::print( std::ostream &os, int indent ) const {
    121         os <<  "Return Statement, returning: ";
    122         if ( expr != 0 ) {
    123                 os << endl << string( indent+2, ' ' );
    124                 expr->print( os, indent + 2 );
     128void ReturnStmt::print( std::ostream &os, Indenter indent ) const {
     129        os << "Return Statement, returning: ";
     130        if ( expr != nullptr ) {
     131                os << endl << indent+1;
     132                expr->print( os, indent+1 );
    125133        }
    126134        os << endl;
     
    142150}
    143151
    144 void IfStmt::print( std::ostream &os, int indent ) const {
    145         os << "If on condition: " << endl ;
    146         os << string( indent+4, ' ' );
    147         condition->print( os, indent + 4 );
     152void IfStmt::print( std::ostream &os, Indenter indent ) const {
     153        os << "If on condition: " << endl;
     154        os << indent+1;
     155        condition->print( os, indent+1 );
    148156
    149157        if ( !initialization.empty() ) {
    150                 os << string( indent + 2, ' ' ) << "initialization: \n";
    151                 for ( std::list<Statement *>::const_iterator it = initialization.begin(); it != initialization.end(); ++it ) {
    152                         os << string( indent + 4, ' ' );
    153                         (*it)->print( os, indent + 4 );
     158                os << indent << "... with initialization: \n";
     159                for ( const Statement * stmt : initialization ) {
     160                        os << indent+1;
     161                        stmt->print( os, indent+1 );
    154162                }
    155163                os << endl;
    156164        }
    157165
    158         os << string( indent+2, ' ' ) << "... then: " << endl;
    159 
    160         os << string( indent+4, ' ' );
    161         thenPart->print( os, indent + 4 );
     166        os << indent << "... then: " << endl;
     167
     168        os << indent+1;
     169        thenPart->print( os, indent+1 );
    162170
    163171        if ( elsePart != 0 ) {
    164                 os << string( indent+2, ' ' ) << "... else: " << endl;
    165                 os << string( indent+4, ' ' );
    166                 elsePart->print( os, indent + 4 );
     172                os << indent << "... else: " << endl;
     173                os << indent+1;
     174                elsePart->print( os, indent+1 );
    167175        } // if
    168176}
     
    183191}
    184192
    185 void SwitchStmt::print( std::ostream &os, int indent ) const {
     193void SwitchStmt::print( std::ostream &os, Indenter indent ) const {
    186194        os << "Switch on condition: ";
    187195        condition->print( os );
    188196        os << endl;
    189197
    190         // statements
    191         std::list<Statement *>::const_iterator i;
    192         for ( i = statements.begin(); i != statements.end(); i++)
    193                 (*i)->print( os, indent + 4 );
    194 
    195         //for_each( statements.begin(), statements.end(), mem_fun( bind1st(&Statement::print ), os ));
     198        for ( const Statement * stmt : statements ) {
     199                stmt->print( os, indent+1 );
     200        }
    196201}
    197202
    198203CaseStmt::CaseStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
    199204        Statement( labels ), condition( condition ), stmts( statements ), _isDefault( deflt ) {
    200         if ( isDefault() && condition != 0 )
    201                 throw SemanticError("default with conditions");
     205        if ( isDefault() && condition != 0 ) throw SemanticError("default case with condition: ", condition);
    202206}
    203207
     
    216220}
    217221
    218 void CaseStmt::print( std::ostream &os, int indent ) const {
    219         os << string( indent, ' ' );
    220 
    221         if ( isDefault() )
    222                 os << "Default ";
     222void CaseStmt::print( std::ostream &os, Indenter indent ) const {
     223        if ( isDefault() ) os << "Default ";
    223224        else {
    224225                os << "Case ";
    225                 condition->print( os );
    226         } // if
    227 
    228         os << endl;
    229 
    230         std::list<Statement *>::const_iterator i;
    231         for ( i = stmts.begin(); i != stmts.end(); i++)
    232                 (*i )->print( os, indent + 4 );
     226                condition->print( os, indent );
     227        } // if
     228        os << endl;
     229
     230        for ( Statement * stmt : stmts ) {
     231                stmt->print( os, indent+1 );
     232        }
    233233}
    234234
     
    246246}
    247247
    248 void WhileStmt::print( std::ostream &os, int indent ) const {
     248void WhileStmt::print( std::ostream &os, Indenter indent ) const {
    249249        os << "While on condition: " << endl ;
    250         condition->print( os, indent + 4 );
    251 
    252         os << string( indent, ' ' ) << ".... with body: " << endl;
    253 
    254         if ( body != 0 ) body->print( os, indent + 4 );
     250        condition->print( os, indent+1 );
     251
     252        os << indent << "... with body: " << endl;
     253
     254        if ( body != 0 ) body->print( os, indent+1 );
    255255}
    256256
     
    272272}
    273273
    274 void ForStmt::print( std::ostream &os, int indent ) const {
    275         os << "Labels: {";
    276         for ( std::list<Label>::const_iterator it = get_labels().begin(); it != get_labels().end(); ++it) {
    277                 os << *it << ",";
    278         }
    279         os << "}" << endl;
    280 
    281         os << string( indent, ' ' ) << "For Statement" << endl ;
    282 
    283         os << string( indent + 2, ' ' ) << "initialization: \n";
    284         for ( std::list<Statement *>::const_iterator it = initialization.begin(); it != initialization.end(); ++it ) {
    285                 os << string( indent + 4, ' ' );
    286                 (*it)->print( os, indent + 4 );
    287         }
    288 
    289         os << "\n" << string( indent + 2, ' ' ) << "condition: \n";
    290         if ( condition != 0 ) {
    291                 os << string( indent + 4, ' ' );
    292                 condition->print( os, indent + 4 );
    293         }
    294 
    295         os << "\n" << string( indent + 2, ' ' ) << "increment: \n";
    296         if ( increment != 0 ) {
    297                 os << string( indent + 4, ' ' );
    298                 increment->print( os, indent + 4 );
    299         }
    300 
    301         os << "\n" << string( indent + 2, ' ' ) << "statement block: \n";
     274void ForStmt::print( std::ostream &os, Indenter indent ) const {
     275        Statement::print( os, indent ); // print labels
     276
     277        os << "For Statement" << endl;
     278
     279        if ( ! initialization.empty() ) {
     280                os << indent << "... initialization: \n";
     281                for ( Statement * stmt : initialization ) {
     282                        os << indent+1;
     283                        stmt->print( os, indent+1 );
     284                }
     285        }
     286
     287        if ( condition != nullptr ) {
     288                os << indent << "... condition: \n" << indent+1;
     289                condition->print( os, indent+1 );
     290        }
     291
     292        if ( increment != nullptr ) {
     293                os << "\n" << indent << "... increment: \n" << indent+1;
     294                increment->print( os, indent+1 );
     295        }
     296
    302297        if ( body != 0 ) {
    303                 os << string( indent + 4, ' ' );
    304                 body->print( os, indent + 4 );
    305         }
    306 
     298                os << "\n" << indent << "... with body: \n" << indent+1;
     299                body->print( os, indent+1 );
     300        }
    307301        os << endl;
    308302}
     
    322316}
    323317
    324 void ThrowStmt::print( std::ostream &os, int indent) const {
     318void ThrowStmt::print( std::ostream &os, Indenter indent) const {
     319        if ( target ) os << "Non-Local ";
     320        os << "Throw Statement, raising: ";
     321        expr->print(os, indent+1);
    325322        if ( target ) {
    326                 os << "Non-Local ";
    327         }
    328         os << "Throw Statement, raising: ";
    329         expr->print(os, indent + 4);
    330         if ( target ) {
    331                 os << "At: ";
    332                 target->print(os, indent + 4);
     323                os << "... at: ";
     324                target->print(os, indent+1);
    333325        }
    334326}
     
    348340}
    349341
    350 void TryStmt::print( std::ostream &os, int indent ) const {
     342void TryStmt::print( std::ostream &os, Indenter indent ) const {
    351343        os << "Try Statement" << endl;
    352         os << string( indent + 2, ' ' ) << "with block:" << endl;
    353         os << string( indent + 4, ' ' );
    354         block->print( os, indent + 4 );
     344        os << indent << "... with block:" << endl << indent+1;
     345        block->print( os, indent+1 );
    355346
    356347        // handlers
    357         os << string( indent + 2, ' ' ) << "and handlers:" << endl;
    358         for ( std::list<CatchStmt *>::const_iterator i = handlers.begin(); i != handlers.end(); i++) {
    359                 os << string( indent + 4, ' ' );
    360                 (*i )->print( os, indent + 4 );
     348        os << indent << "... and handlers:" << endl;
     349        for ( const CatchStmt * stmt : handlers ) {
     350                os << indent+1;
     351                stmt->print( os, indent+1 );
    361352        }
    362353
    363354        // finally block
    364355        if ( finallyBlock != 0 ) {
    365                 os << string( indent + 2, ' ' ) << "and finally:" << endl;
    366                 finallyBlock->print( os, indent + 4 );
     356                os << indent << "... and finally:" << endl << indent+1;
     357                finallyBlock->print( os, indent+1 );
    367358        } // if
    368359}
     
    370361CatchStmt::CatchStmt( std::list<Label> labels, Kind kind, Declaration *decl, Expression *cond, Statement *body ) :
    371362        Statement( labels ), kind ( kind ), decl ( decl ), cond ( cond ), body( body ) {
     363                assertf( decl, "Catch clause must have a declaration." );
    372364}
    373365
     
    381373}
    382374
    383 void CatchStmt::print( std::ostream &os, int indent ) const {
     375void CatchStmt::print( std::ostream &os, Indenter indent ) const {
    384376        os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
    385377
    386         os << string( indent + 2, ' ' ) << "... catching: ";
    387         if ( decl ) {
    388                 decl->printShort( os, indent + 4 );
    389                 os << endl;
    390         }
    391         else
    392                 os << string( indent + 4 , ' ' ) << ">>> Error:  this catch clause must have a declaration <<<" << endl;
     378        os << indent << "... catching: ";
     379        decl->printShort( os, indent+1 );
     380        os << endl;
    393381
    394382        if ( cond ) {
    395                 os << string( indent + 2, ' ' ) << "with conditional:" << endl;
    396                 os << string( indent + 4, ' ' );
    397                 cond->print( os, indent + 4 );
    398         }
    399         else
    400                 os << string( indent + 2, ' ' ) << "with no conditional" << endl;
    401 
    402         os << string( indent + 2, ' ' ) << "with block:" << endl;
    403         os << string( indent + 4, ' ' );
    404         body->print( os, indent + 4 );
     383                os << indent << "... with conditional:" << endl << indent+1;
     384                cond->print( os, indent+1 );
     385        }
     386
     387        os << indent << "... with block:" << endl;
     388        os << indent+1;
     389        body->print( os, indent+1 );
    405390}
    406391
     
    417402}
    418403
    419 void FinallyStmt::print( std::ostream &os, int indent ) const {
     404void FinallyStmt::print( std::ostream &os, Indenter indent ) const {
    420405        os << "Finally Statement" << endl;
    421         os << string( indent + 2, ' ' ) << "with block:" << endl;
    422         os << string( indent + 4, ' ' );
    423         block->print( os, indent + 4 );
     406        os << indent << "... with block:" << endl << indent+1;
     407        block->print( os, indent+1 );
    424408}
    425409
     
    465449}
    466450
    467 void WaitForStmt::print( std::ostream &os, int indent ) const {
     451void WaitForStmt::print( std::ostream &os, Indenter indent ) const {
    468452        os << "Waitfor Statement" << endl;
    469         os << string( indent + 2, ' ' ) << "with block:" << endl;
    470         os << string( indent + 4, ' ' );
     453        os << indent << "... with block:" << endl << indent+1;
    471454        // block->print( os, indent + 4 );
    472455}
     
    475458NullStmt::NullStmt() : Statement( std::list<Label>() ) {}
    476459
    477 void NullStmt::print( std::ostream &os, __attribute__((unused)) int indent ) const {
    478         os << "Null Statement" << endl ;
     460void NullStmt::print( std::ostream &os, Indenter ) const {
     461        os << "Null Statement" << endl;
    479462}
    480463
     
    490473}
    491474
    492 void ImplicitCtorDtorStmt::print( std::ostream &os, int indent ) const {
     475void ImplicitCtorDtorStmt::print( std::ostream &os, Indenter indent ) const {
    493476        os << "Implicit Ctor Dtor Statement" << endl;
    494         os << string( indent + 2, ' ' ) << "with Ctor/Dtor: ";
    495         callStmt->print( os, indent + 2);
     477        os << indent << "... with Ctor/Dtor: ";
     478        callStmt->print( os, indent+1);
    496479        os << endl;
    497480}
  • src/SynTree/Statement.h

    rb96ec83 r6840e7c  
    4343        const std::list<Label> & get_labels() const { return labels; }
    4444
    45         virtual Statement *clone() const = 0;
     45        virtual Statement *clone() const override = 0;
    4646        virtual void accept( Visitor &v ) override = 0;
    47         virtual Statement *acceptMutator( Mutator &m ) = 0;
    48         virtual void print( std::ostream &os, int indent = 0 ) const override;
     47        virtual Statement *acceptMutator( Mutator &m ) override = 0;
     48        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    4949};
    5050
     
    6565        virtual void accept( Visitor &v ) override { v.visit( this ); }
    6666        virtual CompoundStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    67         virtual void print( std::ostream &os, int indent = 0 ) const override;
     67        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    6868};
    6969
     
    7676        virtual void accept( Visitor &v ) override { v.visit( this ); }
    7777        virtual NullStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    78         virtual void print( std::ostream &os, int indent = 0 ) const override;
     78        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    7979};
    8080
     
    9393        virtual void accept( Visitor &v ) override { v.visit( this ); }
    9494        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    95         virtual void print( std::ostream &os, int indent = 0 ) const override;
     95        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    9696};
    9797
     
    124124        virtual void accept( Visitor & v ) { v.visit( this ); }
    125125        virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    126         virtual void print( std::ostream & os, int indent = 0 ) const;
     126        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    127127};
    128128
     
    150150        virtual void accept( Visitor &v ) override { v.visit( this ); }
    151151        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    152         virtual void print( std::ostream &os, int indent = 0 ) const override;
     152        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    153153};
    154154
     
    171171
    172172        virtual SwitchStmt *clone() const override { return new SwitchStmt( *this ); }
    173         virtual void print( std::ostream &os, int indent = 0 ) const override;
     173        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    174174
    175175};
     
    199199
    200200        virtual CaseStmt *clone() const override { return new CaseStmt( *this ); }
    201         virtual void print( std::ostream &os, int indent = 0 ) const override;
     201        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    202202  private:
    203203        bool _isDefault;
     
    225225        virtual void accept( Visitor &v ) override { v.visit( this ); }
    226226        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    227         virtual void print( std::ostream &os, int indent = 0 ) const override;
     227        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    228228};
    229229
     
    251251        virtual void accept( Visitor &v ) override { v.visit( this ); }
    252252        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    253         virtual void print( std::ostream &os, int indent = 0 ) const override;
     253        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    254254};
    255255
     
    280280        virtual void accept( Visitor &v ) override { v.visit( this ); }
    281281        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    282         virtual void print( std::ostream &os, int indent = 0 ) const override;
     282        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    283283  private:
    284284        static const char *brType[];
     
    299299        virtual void accept( Visitor &v ) override { v.visit( this ); }
    300300        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    301         virtual void print( std::ostream &os, int indent = 0 ) const override;
     301        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    302302};
    303303
     
    323323        virtual void accept( Visitor &v ) override { v.visit( this ); }
    324324        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    325         virtual void print( std::ostream &os, int indent = 0 ) const override;
     325        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    326326};
    327327
     
    346346        virtual void accept( Visitor &v ) override { v.visit( this ); }
    347347        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    348         virtual void print( std::ostream &os, int indent = 0 ) const override;
     348        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    349349};
    350350
     
    374374        virtual void accept( Visitor &v ) override { v.visit( this ); }
    375375        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    376         virtual void print( std::ostream &os, int indent = 0 ) const override;
     376        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    377377};
    378378
     
    391391        virtual void accept( Visitor &v ) override { v.visit( this ); }
    392392        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    393         virtual void print( std::ostream &os, int indent = 0 ) const override;
     393        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    394394};
    395395
     
    428428        virtual void accept( Visitor &v ) override { v.visit( this ); }
    429429        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    430         virtual void print( std::ostream &os, int indent = 0 ) const override;
     430        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    431431
    432432};
     
    448448        virtual void accept( Visitor &v ) override { v.visit( this ); }
    449449        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    450         virtual void print( std::ostream &os, int indent = 0 ) const override;
     450        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    451451};
    452452
     
    470470        virtual void accept( Visitor &v ) override { v.visit( this ); }
    471471        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    472         virtual void print( std::ostream &os, int indent = 0 ) const override;
     472        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    473473};
    474474
  • src/SynTree/TupleExpr.cc

    rb96ec83 r6840e7c  
    2828#include "Type.h"               // for TupleType, Type
    2929
    30 UntypedTupleExpr::UntypedTupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
     30UntypedTupleExpr::UntypedTupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
    3131}
    3232
     
    3939}
    4040
    41 void UntypedTupleExpr::print( std::ostream &os, int indent ) const {
     41void UntypedTupleExpr::print( std::ostream &os, Indenter indent ) const {
    4242        os << "Untyped Tuple:" << std::endl;
    43         printAll( exprs, os, indent+2 );
     43        printAll( exprs, os, indent+1 );
    4444        Expression::print( os, indent );
    4545}
    4646
    47 TupleExpr::TupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
     47TupleExpr::TupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
    4848        set_result( Tuples::makeTupleType( exprs ) );
    4949}
     
    5757}
    5858
    59 void TupleExpr::print( std::ostream &os, int indent ) const {
     59void TupleExpr::print( std::ostream &os, Indenter indent ) const {
    6060        os << "Tuple:" << std::endl;
    61         printAll( exprs, os, indent+2 );
     61        printAll( exprs, os, indent+1 );
    6262        Expression::print( os, indent );
    6363}
     
    7878}
    7979
    80 void TupleIndexExpr::print( std::ostream &os, int indent ) const {
     80void TupleIndexExpr::print( std::ostream &os, Indenter indent ) const {
    8181        os << "Tuple Index Expression, with tuple:" << std::endl;
    82         os << std::string( indent+2, ' ' );
    83         tuple->print( os, indent+2 );
    84         os << std::string( indent+2, ' ' ) << "with index: " << index << std::endl;
     82        os << indent+1;
     83        tuple->print( os, indent+1 );
     84        os << indent+1 << "with index: " << index << std::endl;
    8585        Expression::print( os, indent );
    8686}
    8787
    88 TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ) {
     88TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls ) : Expression() {
    8989        // convert internally into a StmtExpr which contains the declarations and produces the tuple of the assignments
    9090        set_result( Tuples::makeTupleType( assigns ) );
     
    109109}
    110110
    111 void TupleAssignExpr::print( std::ostream &os, int indent ) const {
     111void TupleAssignExpr::print( std::ostream &os, Indenter indent ) const {
    112112        os << "Tuple Assignment Expression, with stmt expr:" << std::endl;
    113         os << std::string( indent+2, ' ' );
    114         stmtExpr->print( os, indent+4 );
     113        os << indent+1;
     114        stmtExpr->print( os, indent+1 );
    115115        Expression::print( os, indent );
    116116}
  • src/SynTree/TupleType.cc

    rb96ec83 r6840e7c  
    4848}
    4949
    50 void TupleType::print( std::ostream &os, int indent ) const {
     50void TupleType::print( std::ostream &os, Indenter indent ) const {
    5151        Type::print( os, indent );
    5252        os << "tuple of types" << std::endl;
    53         printAll( types, os, indent+2 );
     53        printAll( types, os, indent+1 );
    5454}
    5555
  • src/SynTree/Type.cc

    rb96ec83 r6840e7c  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 11 13:21:25 2017
    13 // Update Count     : 37
     12// Last Modified On : Mon Sep 25 15:16:32 2017
     13// Update Count     : 38
    1414//
    1515#include "Type.h"
     
    4545        "double _Imaginary",
    4646        "long double _Imaginary",
     47        "__int128",
     48        "unsigned __int128",
    4749};
    4850
     
    7375        Type * type;
    7476        ReferenceType * ref;
    75         for ( type = this; (ref = dynamic_cast<ReferenceType *>( type )); type = ref->get_base() );
     77        for ( type = this; (ref = dynamic_cast<ReferenceType *>( type )); type = ref->base );
    7678        return type;
    7779}
     
    7981int Type::referenceDepth() const { return 0; }
    8082
    81 void Type::print( std::ostream &os, int indent ) const {
     83void Type::print( std::ostream &os, Indenter indent ) const {
    8284        if ( ! forall.empty() ) {
    8385                os << "forall" << std::endl;
    84                 printAll( forall, os, indent + 4 );
    85                 os << std::string( indent+2, ' ' );
     86                printAll( forall, os, indent+1 );
     87                os << ++indent;
    8688        } // if
    8789
    8890        if ( ! attributes.empty() ) {
    89                 os << endl << string( indent+2, ' ' ) << "with attributes" << endl;
    90                 printAll( attributes, os, indent+4 );
     91                os << "with attributes" << endl;
     92                printAll( attributes, os, indent+1 );
    9193        } // if
    9294
  • src/SynTree/Type.h

    rb96ec83 r6840e7c  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Aug  9 14:25:00 2017
    13 // Update Count     : 152
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Sep 25 14:14:01 2017
     13// Update Count     : 154
    1414//
    1515
     
    181181        virtual void accept( Visitor & v ) = 0;
    182182        virtual Type *acceptMutator( Mutator & m ) = 0;
    183         virtual void print( std::ostream & os, int indent = 0 ) const;
     183        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    184184};
    185185
     
    198198        virtual void accept( Visitor & v ) override { v.visit( this ); }
    199199        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    200         virtual void print( std::ostream & os, int indent = 0 ) const override;
     200        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    201201};
    202202
     
    225225                DoubleImaginary,
    226226                LongDoubleImaginary,
     227                SignedInt128,
     228                UnsignedInt128,
    227229                NUMBER_OF_BASIC_TYPES
    228230        } kind;
     
    238240        virtual void accept( Visitor & v ) override { v.visit( this ); }
    239241        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    240         virtual void print( std::ostream & os, int indent = 0 ) const override;
     242        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    241243
    242244        bool isInteger() const;
     
    273275        virtual void accept( Visitor & v ) override { v.visit( this ); }
    274276        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    275         virtual void print( std::ostream & os, int indent = 0 ) const override;
     277        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    276278};
    277279
     
    301303        virtual void accept( Visitor & v ) override { v.visit( this ); }
    302304        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    303         virtual void print( std::ostream & os, int indent = 0 ) const override;
     305        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    304306};
    305307
     
    325327        virtual void accept( Visitor & v ) override { v.visit( this ); }
    326328        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    327         virtual void print( std::ostream & os, int indent = 0 ) const override;
     329        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    328330};
    329331
     
    352354        virtual void accept( Visitor & v ) override { v.visit( this ); }
    353355        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    354         virtual void print( std::ostream & os, int indent = 0 ) const override;
     356        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    355357};
    356358
     
    374376        virtual void accept( Visitor & v ) override = 0;
    375377        virtual Type *acceptMutator( Mutator & m ) override = 0;
    376         virtual void print( std::ostream & os, int indent = 0 ) const override;
     378        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    377379
    378380        virtual void lookup( __attribute__((unused)) const std::string & name, __attribute__((unused)) std::list< Declaration* > & foundDecls ) const {}
     
    408410        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    409411
    410         virtual void print( std::ostream & os, int indent = 0 ) const override;
     412        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    411413  private:
    412414        virtual std::string typeString() const override;
     
    440442        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    441443
    442         virtual void print( std::ostream & os, int indent = 0 ) const override;
     444        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    443445  private:
    444446        virtual std::string typeString() const override;
     
    464466        virtual void accept( Visitor & v ) override { v.visit( this ); }
    465467        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     468
     469        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    466470  private:
    467471        virtual std::string typeString() const override;
     
    512516        virtual void accept( Visitor & v ) override { v.visit( this ); }
    513517        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    514         virtual void print( std::ostream & os, int indent = 0 ) const override;
     518        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    515519  private:
    516520        virtual std::string typeString() const override;
     
    549553        virtual void accept( Visitor & v ) override { v.visit( this ); }
    550554        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    551         virtual void print( std::ostream & os, int indent = 0 ) const override;
     555        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    552556};
    553557
     
    568572        virtual void accept( Visitor & v ) override { v.visit( this ); }
    569573        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    570         virtual void print( std::ostream & os, int indent = 0 ) const override;
     574        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    571575};
    572576
     
    597601        virtual void accept( Visitor & v ) override { v.visit( this ); }
    598602        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    599         virtual void print( std::ostream & os, int indent = 0 ) const override;
     603        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    600604};
    601605
     
    611615        virtual void accept( Visitor & v ) override { v.visit( this ); }
    612616        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    613         virtual void print( std::ostream & os, int indent = 0 ) const override;
     617        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    614618};
    615619
     
    623627        virtual void accept( Visitor & v ) override { v.visit( this ); }
    624628        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    625         virtual void print( std::ostream & os, int indent = 0 ) const override;
     629        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    626630};
    627631
     
    635639        virtual void accept( Visitor & v ) override { v.visit( this ); }
    636640        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    637         virtual void print( std::ostream & os, int indent = 0 ) const override;
     641        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    638642};
    639643
  • src/SynTree/TypeDecl.cc

    rb96ec83 r6840e7c  
    4141}
    4242
    43 void TypeDecl::print( std::ostream &os, int indent ) const {
     43void TypeDecl::print( std::ostream &os, Indenter indent ) const {
    4444  NamedTypeDecl::print( os, indent );
    4545  if ( init ) {
    46     os << std::endl << std::string( indent, ' ' ) << "with type initializer: ";
    47     init->print( os, indent + 2 );
     46    os << std::endl << indent << "with type initializer: ";
     47    init->print( os, indent + 1 );
    4848  }
    4949}
  • src/SynTree/TypeExpr.cc

    rb96ec83 r6840e7c  
    3030}
    3131
    32 void TypeExpr::print( std::ostream &os, int indent ) const {
     32void TypeExpr::print( std::ostream &os, Indenter indent ) const {
    3333        if ( type ) type->print( os, indent );
    3434        Expression::print( os, indent );
  • src/SynTree/TypeSubstitution.cc

    rb96ec83 r6840e7c  
    148148template< typename TypeClass >
    149149Type *TypeSubstitution::handleType( TypeClass *type ) {
    150         BoundVarsType oldBoundVars( boundVars );
     150        ValueGuard<BoundVarsType> oldBoundVars( boundVars );
    151151        // bind type variables from forall-qualifiers
    152152        if ( freeOnly ) {
     
    156156        } // if
    157157        Type *ret = Mutator::mutate( type );
    158         boundVars = oldBoundVars;
    159158        return ret;
    160159}
     
    162161template< typename TypeClass >
    163162Type *TypeSubstitution::handleAggregateType( TypeClass *type ) {
    164         BoundVarsType oldBoundVars( boundVars );
     163        ValueGuard<BoundVarsType> oldBoundVars( boundVars );
    165164        // bind type variables from forall-qualifiers
    166165        if ( freeOnly ) {
     
    177176        } // if
    178177        Type *ret = Mutator::mutate( type );
    179         boundVars = oldBoundVars;
    180178        return ret;
    181179}
     
    233231}
    234232
    235 TypeSubstitution * TypeSubstitution::acceptMutator( Mutator & mutator ) {
    236         for ( auto & p : typeEnv ) {
    237                 p.second = maybeMutate( p.second, mutator );
    238         }
    239         for ( auto & p : varEnv ) {
    240                 p.second = maybeMutate( p.second, mutator );
    241         }
    242         return this;
    243 }
    244 
    245 void TypeSubstitution::print( std::ostream &os, int indent ) const {
    246         os << std::string( indent, ' ' ) << "Types:" << std::endl;
     233void TypeSubstitution::print( std::ostream &os, Indenter indent ) const {
     234        os << indent << "Types:" << std::endl;
    247235        for ( TypeEnvType::const_iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    248                 os << std::string( indent+2, ' ' ) << i->first << " -> ";
    249                 i->second->print( os, indent+4 );
     236                os << indent+1 << i->first << " -> ";
     237                i->second->print( os, indent+2 );
    250238                os << std::endl;
    251239        } // for
    252         os << std::string( indent, ' ' ) << "Non-types:" << std::endl;
     240        os << indent << "Non-types:" << std::endl;
    253241        for ( VarEnvType::const_iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
    254                 os << std::string( indent+2, ' ' ) << i->first << " -> ";
    255                 i->second->print( os, indent+4 );
     242                os << indent+1 << i->first << " -> ";
     243                i->second->print( os, indent+2 );
    256244                os << std::endl;
    257245        } // for
  • src/SynTree/TypeSubstitution.h

    rb96ec83 r6840e7c  
    5959        void normalize();
    6060
    61         TypeSubstitution * acceptMutator( Mutator & mutator );
     61        TypeSubstitution * acceptMutator( Mutator & m ) { return m.mutate( this ); }
    6262
    63         void print( std::ostream &os, int indent = 0 ) const;
     63        void print( std::ostream &os, Indenter indent = {} ) const;
    6464        TypeSubstitution *clone() const { return new TypeSubstitution( *this ); }
    6565  private:
     
    8989
    9090        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
     91
     92        friend class Mutator;
     93
     94        template<typename pass_type>
     95        friend class PassVisitor;
    9196
    9297        typedef std::map< std::string, Type* > TypeEnvType;
  • src/SynTree/TypeofType.cc

    rb96ec83 r6840e7c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // TypeofType.cc -- 
     7// TypeofType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    3333}
    3434
    35 void TypeofType::print( std::ostream &os, int indent ) const {
     35void TypeofType::print( std::ostream &os, Indenter indent ) const {
    3636        Type::print( os, indent );
    3737        os << "type-of expression ";
  • src/SynTree/VarArgsType.cc

    rb96ec83 r6840e7c  
    2525VarArgsType::VarArgsType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
    2626
    27 void VarArgsType::print( std::ostream &os, int indent ) const {
     27void VarArgsType::print( std::ostream &os, Indenter indent ) const {
    2828        Type::print( os, indent );
    2929        os << "builtin var args pack";
  • src/SynTree/VoidType.cc

    rb96ec83 r6840e7c  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // VoidType.cc -- 
     7// VoidType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2424}
    2525
    26 void VoidType::print( std::ostream &os, int indent ) const {
     26void VoidType::print( std::ostream &os, Indenter indent ) const {
    2727        Type::print( os, indent );
    2828        os << "void ";
  • src/SynTree/ZeroOneType.cc

    rb96ec83 r6840e7c  
    2525ZeroType::ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
    2626
    27 void ZeroType::print( std::ostream &os, __attribute__((unused)) int indent ) const {
     27void ZeroType::print( std::ostream &os, Indenter ) const {
    2828        os << "zero_t";
    2929}
     
    3333OneType::OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
    3434
    35 void OneType::print( std::ostream &os, __attribute__((unused)) int indent ) const {
     35void OneType::print( std::ostream &os, Indenter ) const {
    3636        os << "one_t";
    3737}
  • src/Tuples/Explode.h

    rb96ec83 r6840e7c  
    3030        Expression * distributeReference( Expression * );
    3131
     32        static inline CastExpr * isReferenceCast( Expression * expr ) {
     33                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     34                        if ( dynamic_cast< ReferenceType * >( castExpr->result ) ) {
     35                                return castExpr;
     36                        }
     37                }
     38                return nullptr;
     39        }
     40
    3241        /// helper function used by explode
    3342        template< typename OutputIterator >
     
    3544                if ( isTupleAssign ) {
    3645                        // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components
    37                         if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     46                        if ( CastExpr * castExpr = isReferenceCast( expr ) ) {
    3847                                ResolvExpr::AltList alts;
    3948                                explodeUnique( castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
  • src/Tuples/TupleAssignment.cc

    rb96ec83 r6840e7c  
    4141#include "SynTree/Visitor.h"               // for Visitor
    4242
     43#if 0
     44#define PRINT(x) x
     45#else
     46#define PRINT(x)
     47#endif
     48
    4349namespace Tuples {
    4450        class TupleAssignSpotter {
     
    8490        bool isTuple( Expression *expr ) {
    8591                if ( ! expr ) return false;
    86                 assert( expr->has_result() );
     92                assert( expr->result );
    8793                return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    8894        }
     
    119125                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    120126                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    121                                 fname = op->get_name();
     127                               fname = op->get_name();
     128                                PRINT( std::cerr << "TupleAssignment: " << fname << std::endl; )
    122129                                for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    123130                                        if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
     
    131138                                        const ResolvExpr::Alternative & alt1 = ali->front();
    132139                                        auto begin = std::next(ali->begin(), 1), end = ali->end();
     140                                        PRINT( std::cerr << "alt1 is " << alt1.expr << std::endl; )
    133141                                        if ( refToTuple(alt1.expr) ) {
     142                                                PRINT( std::cerr << "and is reference to tuple" << std::endl; )
    134143                                                if ( isMultAssign( begin, end ) ) {
     144                                                        PRINT( std::cerr << "possible multiple assignment" << std::endl; )
    135145                                                        matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
    136146                                                } else {
    137147                                                        // mass assignment
     148                                                        PRINT( std::cerr << "possible mass assignment" << std::endl; )
    138149                                                        matcher.reset( new MassAssignMatcher( *this,  *ali ) );
    139150                                                }
     
    159170                // now resolve new assignments
    160171                for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
     172                        PRINT(
     173                                std::cerr << "== resolving tuple assign ==" << std::endl;
     174                                std::cerr << *i << std::endl;
     175                        )
     176
    161177                        ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
    162178                        try {
     
    238254
    239255        ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    240                 assert( expr->has_result() && ! expr->get_result()->isVoid() );
     256                assert( expr->result && ! expr->get_result()->isVoid() );
    241257                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
    242258                // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
     
    248264                        ctorInit->accept( rm );
    249265                }
     266                PRINT( std::cerr << "new object: " << ret << std::endl; )
    250267                return ret;
    251268        }
  • src/benchmark/Makefile.am

    rb96ec83 r6840e7c  
    4848        @rm -f a.out .result.log
    4949
     50ctxswitch-pthread$(EXEEXT):
     51        @BACKEND_CC@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -lrt -pthread -DN=50000000 PthrdCtxSwitch.c
     52        @rm -f .result.log
     53        @for number in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do \
     54                ./a.out | tee -a .result.log ; \
     55        done
     56        @./stat.py .result.log
     57        @rm -f a.out .result.log
     58
    5059sched-int$(EXEEXT):
    5160        ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=50000000 SchedInt.c
  • src/benchmark/Makefile.in

    rb96ec83 r6840e7c  
    598598        @rm -f a.out .result.log
    599599
     600ctxswitch-pthread$(EXEEXT):
     601        @BACKEND_CC@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -lrt -pthread -DN=50000000 PthrdCtxSwitch.c
     602        @rm -f .result.log
     603        @for number in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do \
     604                ./a.out | tee -a .result.log ; \
     605        done
     606        @./stat.py .result.log
     607        @rm -f a.out .result.log
     608
    600609sched-int$(EXEEXT):
    601610        ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=50000000 SchedInt.c
  • src/benchmark/bench.h

    rb96ec83 r6840e7c  
    1010}
    1111#endif
    12 
    1312
    1413static inline unsigned long long int Time() {
  • src/benchmark/create_cfaThrd.c

    rb96ec83 r6840e7c  
    44
    55thread MyThread {};
    6 void main(MyThread * this) {}
     6void main(MyThread & this) {}
    77
    88int main(int argc, char* argv[]) {
  • src/driver/cfa.cc

    rb96ec83 r6840e7c  
    99// Author           : Peter A. Buhr
    1010// Created On       : Tue Aug 20 13:44:49 2002
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Aug 17 15:24:00 2017
    13 // Update Count     : 156
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Sep 26 23:12:38 2017
     13// Update Count     : 159
    1414//
    1515
     
    346346                args[nargs] = "-fgnu89-inline";
    347347                nargs += 1;
     348                args[nargs] = "-D__int8_t_defined";                             // prevent gcc type-size attributes
     349                nargs += 1;
    348350                args[nargs] = ( *new string( string("-B") + Bprefix + "/" ) ).c_str();
    349351                nargs += 1;
  • src/include/cassert

    rb96ec83 r6840e7c  
    4141static inline T strict_dynamic_cast( const U & src ) {
    4242        T ret = dynamic_cast<T>(src);
    43         assert(ret);
     43        assertf(ret, "%s", toString(src).c_str());
    4444        return ret;
    4545}
  • src/libcfa/Makefile.am

    rb96ec83 r6840e7c  
    3131
    3232libcfa_a-libcfa-prelude.o : libcfa-prelude.c
    33          ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -O2 -c -o $@ $<
     33         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -Wall -O2 -c -o $@ $<
    3434
    3535libcfa_d_a-libcfa-prelude.o : libcfa-prelude.c
    36          ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -D__CFA_DEBUG__ -O0 -c -o $@ $<
     36         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -D__CFA_DEBUG__ -Wall -O0 -c -o $@ $<
    3737
    3838EXTRA_FLAGS = -g -Wall -Wno-unused-function -imacros libcfa-prelude.c @CFA_FLAGS@
  • src/libcfa/Makefile.in

    rb96ec83 r6840e7c  
    14981498
    14991499libcfa_a-libcfa-prelude.o : libcfa-prelude.c
    1500          ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -O2 -c -o $@ $<
     1500         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -Wall -O2 -c -o $@ $<
    15011501
    15021502libcfa_d_a-libcfa-prelude.o : libcfa-prelude.c
    1503          ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -D__CFA_DEBUG__ -O0 -c -o $@ $<
     1503         ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -D__CFA_DEBUG__ -Wall -O0 -c -o $@ $<
    15041504
    15051505# extensionless header files are overridden by -o flag in default makerule => explicitly override default rule to silently do nothing
  • src/libcfa/concurrency/invoke.h

    rb96ec83 r6840e7c  
    9696            struct __condition_stack_t signal_stack;  // stack of conditions to run next once we exit the monitor
    9797            unsigned int recursion;                   // monitor routines can be called recursively, we need to keep track of that
    98             struct __waitfor_mask_t mask;               // mask used to know if some thread is waiting for something while holding the monitor
     98            struct __waitfor_mask_t mask;             // mask used to know if some thread is waiting for something while holding the monitor
     99            struct __condition_node_t * dtor_node;    // node used to signal the dtor in a waitfor dtor
    99100      };
    100101
     
    110111            struct monitor_desc    self_mon;          // monitor body used for mutual exclusion
    111112            struct monitor_desc *  self_mon_p;        // pointer to monitor with sufficient lifetime for current monitors
    112             struct __monitor_group_t monitors;          // monitors currently held by this thread
     113            struct __monitor_group_t monitors;        // monitors currently held by this thread
    113114
    114115            // Link lists fields
  • src/libcfa/concurrency/monitor

    rb96ec83 r6840e7c  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:59:01 2017
    13 // Update Count     : 3
     12// Last Modified On : Sat Oct  7 18:06:45 2017
     13// Update Count     : 10
    1414//
    1515
     
    2929static inline void ?{}(monitor_desc & this) {
    3030        (this.lock){};
    31         this.owner = NULL;
    3231        (this.entry_queue){};
    3332        (this.signal_stack){};
    34         this.recursion = 0;
     33        this.owner         = NULL;
     34        this.recursion     = 0;
    3535        this.mask.accepted = NULL;
    3636        this.mask.clauses  = NULL;
    3737        this.mask.size     = 0;
     38        this.dtor_node     = NULL;
    3839}
     40
     41// static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) {
     42//      return ((intptr_t)lhs) < ((intptr_t)rhs);
     43// }
    3944
    4045struct monitor_guard_t {
     
    4651};
    4752
    48 static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) {
    49         return ((intptr_t)lhs) < ((intptr_t)rhs);
    50 }
    51 
    5253void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, void (*func)() );
    5354void ^?{}( monitor_guard_t & this );
     55
     56struct monitor_dtor_guard_t {
     57        monitor_desc * m;
     58        monitor_desc ** prev_mntrs;
     59        unsigned short  prev_count;
     60        fptr_t          prev_func;
     61};
     62
     63void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, void (*func)() );
     64void ^?{}( monitor_dtor_guard_t & this );
     65
     66static inline forall( dtype T | sized(T) | { void ^?{}( T & mutex ); } )
     67void delete( T * th ) {
     68        ^(*th){};
     69        free( th );
     70}
    5471
    5572//-----------------------------------------------------------------------------
     
    7592        __condition_node_t ** tail;
    7693};
     94
     95void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info );
     96void ?{}(__condition_criterion_t & this );
     97void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner );
    7798
    7899void ?{}( __condition_blocked_queue_t & );
  • src/libcfa/concurrency/monitor.c

    rb96ec83 r6840e7c  
    2323//-----------------------------------------------------------------------------
    2424// Forward declarations
    25 static inline void set_owner( monitor_desc * this, thread_desc * owner );
    26 static inline void set_owner( monitor_desc ** storage, short count, thread_desc * owner );
    27 static inline void set_mask ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask );
     25static inline void set_owner ( monitor_desc * this, thread_desc * owner );
     26static inline void set_owner ( monitor_desc ** storage, short count, thread_desc * owner );
     27static inline void set_mask  ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask );
     28static inline void reset_mask( monitor_desc * this );
    2829
    2930static inline thread_desc * next_thread( monitor_desc * this );
     
    7273#define monitor_restore restore( monitors, count, locks, recursions, masks )
    7374
    74 #define blockAndWake( thrd, cnt )                               /* Create the necessary information to use the signaller stack                         */ \
    75         monitor_save;                                             /* Save monitor states                                                                 */ \
    76         BlockInternal( locks, count, thrd, cnt );                 /* Everything is ready to go to sleep                                                  */ \
    77         monitor_restore;                                          /* We are back, restore the owners and recursions                                      */ \
    78 
    7975
    8076//-----------------------------------------------------------------------------
     
    9894                }
    9995                else if( this->owner == thrd) {
    100                         // We already have the monitor, just not how many times we took it
     96                        // We already have the monitor, just note how many times we took it
    10197                        verify( this->recursion > 0 );
    10298                        this->recursion += 1;
     
    108104                        set_owner( this, thrd );
    109105
     106                        // Reset mask
     107                        reset_mask( this );
     108
    110109                        LIB_DEBUG_PRINT_SAFE("Kernel :  mon accepts \n");
    111110                }
     
    128127                unlock( &this->lock );
    129128                return;
     129        }
     130
     131        static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) {
     132                // Lock the monitor spinlock, lock_yield to reduce contention
     133                lock_yield( &this->lock DEBUG_CTX2 );
     134                thread_desc * thrd = this_thread;
     135
     136                LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     137
     138
     139                if( !this->owner ) {
     140                        LIB_DEBUG_PRINT_SAFE("Kernel : Destroying free mon %p\n", this);
     141
     142                        // No one has the monitor, just take it
     143                        set_owner( this, thrd );
     144
     145                        unlock( &this->lock );
     146                        return;
     147                }
     148                else if( this->owner == thrd) {
     149                        // We already have the monitor... but where about to destroy it so the nesting will fail
     150                        // Abort!
     151                        abortf("Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.");
     152                }
     153
     154                int count = 1;
     155                monitor_desc ** monitors = &this;
     156                __monitor_group_t group = { &this, 1, func };
     157                if( is_accepted( this, group) ) {
     158                        LIB_DEBUG_PRINT_SAFE("Kernel :  mon accepts dtor, block and signal it \n");
     159
     160                        // Wake the thread that is waiting for this
     161                        __condition_criterion_t * urgent = pop( &this->signal_stack );
     162                        verify( urgent );
     163
     164                        // Reset mask
     165                        reset_mask( this );
     166
     167                        // Create the node specific to this wait operation
     168                        wait_ctx_primed( this_thread, 0 )
     169
     170                        // Some one else has the monitor, wait for him to finish and then run
     171                        BlockInternal( &this->lock, urgent->owner->waiting_thread );
     172
     173                        // Some one was waiting for us, enter
     174                        set_owner( this, thrd );
     175                }
     176                else {
     177                        LIB_DEBUG_PRINT_SAFE("Kernel :  blocking \n");
     178
     179                        wait_ctx( this_thread, 0 )
     180                        this->dtor_node = &waiter;
     181
     182                        // Some one else has the monitor, wait in line for it
     183                        append( &this->entry_queue, thrd );
     184                        BlockInternal( &this->lock );
     185
     186                        // BlockInternal will unlock spinlock, no need to unlock ourselves
     187                        return;
     188                }
     189
     190                LIB_DEBUG_PRINT_SAFE("Kernel : Destroying %p\n", this);
     191
    130192        }
    131193
     
    159221        }
    160222
     223        // Leave single monitor for the last time
     224        void __leave_dtor_monitor_desc( monitor_desc * this ) {
     225                LIB_DEBUG_DO(
     226                        if( this_thread != this->owner ) {
     227                                abortf("Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);
     228                        }
     229                        if( this->recursion != 1 ) {
     230                                abortf("Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
     231                        }
     232                )
     233        }
     234
    161235        // Leave the thread monitor
    162236        // last routine called by a thread.
     
    211285// Ctor for monitor guard
    212286// Sorts monitors before entering
    213 void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, void (*func)() ) {
     287void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, fptr_t func ) {
    214288        // Store current array
    215289        this.m = m;
     
    229303        this_thread->monitors.func = func;
    230304
    231         LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count);
     305        // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count);
    232306
    233307        // Enter the monitors in order
     
    235309        enter( group );
    236310
    237         LIB_DEBUG_PRINT_SAFE("MGUARD : entered\n");
     311        // LIB_DEBUG_PRINT_SAFE("MGUARD : entered\n");
    238312}
    239313
     
    241315// Dtor for monitor guard
    242316void ^?{}( monitor_guard_t & this ) {
    243         LIB_DEBUG_PRINT_SAFE("MGUARD : leaving %d\n", this.count);
     317        // LIB_DEBUG_PRINT_SAFE("MGUARD : leaving %d\n", this.count);
    244318
    245319        // Leave the monitors in order
    246320        leave( this.m, this.count );
    247321
    248         LIB_DEBUG_PRINT_SAFE("MGUARD : left\n");
     322        // LIB_DEBUG_PRINT_SAFE("MGUARD : left\n");
     323
     324        // Restore thread context
     325        this_thread->monitors.list = this.prev_mntrs;
     326        this_thread->monitors.size = this.prev_count;
     327        this_thread->monitors.func = this.prev_func;
     328}
     329
     330
     331// Ctor for monitor guard
     332// Sorts monitors before entering
     333void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, fptr_t func ) {
     334        // Store current array
     335        this.m = *m;
     336
     337        // Save previous thread context
     338        this.prev_mntrs = this_thread->monitors.list;
     339        this.prev_count = this_thread->monitors.size;
     340        this.prev_func  = this_thread->monitors.func;
     341
     342        // Update thread context (needed for conditions)
     343        this_thread->monitors.list = m;
     344        this_thread->monitors.size = 1;
     345        this_thread->monitors.func = func;
     346
     347        __enter_monitor_dtor( this.m, func );
     348}
     349
     350
     351// Dtor for monitor guard
     352void ^?{}( monitor_dtor_guard_t & this ) {
     353        // Leave the monitors in order
     354        __leave_dtor_monitor_desc( this.m );
    249355
    250356        // Restore thread context
     
    303409        short thread_count = 0;
    304410        thread_desc * threads[ count ];
    305         for(int i = 0; i < count; i++) {
    306                 threads[i] = 0;
    307         }
     411        __builtin_memset( threads, 0, sizeof( threads ) );
    308412
    309413        // Save monitor states
     
    429533        short max = count_max( mask );
    430534        monitor_desc * mon_storage[max];
     535        __builtin_memset( mon_storage, 0, sizeof( mon_storage ) );
    431536        short actual_count = aggregate( mon_storage, mask );
    432537
     538        LIB_DEBUG_PRINT_SAFE("Kernel : waitfor %d (s: %d, m: %d)\n", actual_count, mask.size, (short)max);
     539
    433540        if(actual_count == 0) return;
     541
     542        LIB_DEBUG_PRINT_SAFE("Kernel : waitfor internal proceeding\n");
    434543
    435544        // Create storage for monitor context
     
    445554
    446555                if( next ) {
     556                        *mask.accepted = index;
    447557                        if( mask.clauses[index].is_dtor ) {
    448                                 #warning case not implemented
     558                                LIB_DEBUG_PRINT_SAFE("Kernel : dtor already there\n");
     559                                verifyf( mask.clauses[index].size == 1        , "ERROR: Accepted dtor has more than 1 mutex parameter." );
     560
     561                                monitor_desc * mon2dtor = mask.clauses[index].list[0];
     562                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
     563
     564                                __condition_criterion_t * dtor_crit = mon2dtor->dtor_node->criteria;
     565                                push( &mon2dtor->signal_stack, dtor_crit );
     566
     567                                unlock_all( locks, count );
    449568                        }
    450569                        else {
    451                                 blockAndWake( &next, 1 );
     570                                LIB_DEBUG_PRINT_SAFE("Kernel : thread present, baton-passing\n");
     571
     572                                // Create the node specific to this wait operation
     573                                wait_ctx_primed( this_thread, 0 );
     574
     575                                // Save monitor states
     576                                monitor_save;
     577
     578                                // Set the owners to be the next thread
     579                                set_owner( monitors, count, next );
     580
     581                                // Everything is ready to go to sleep
     582                                BlockInternal( locks, count, &next, 1 );
     583
     584                                // We are back, restore the owners and recursions
     585                                monitor_restore;
     586
     587                                LIB_DEBUG_PRINT_SAFE("Kernel : thread present, returned\n");
    452588                        }
    453589
    454                         return index;
     590                        LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted);
     591
     592                        return;
    455593                }
    456594        }
     
    458596
    459597        if( duration == 0 ) {
     598                LIB_DEBUG_PRINT_SAFE("Kernel : non-blocking, exiting\n");
     599
    460600                unlock_all( locks, count );
     601
     602                LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted);
    461603                return;
    462604        }
     
    465607        verifyf( duration < 0, "Timeout on waitfor statments not supported yet.");
    466608
     609        LIB_DEBUG_PRINT_SAFE("Kernel : blocking waitfor\n");
     610
     611        // Create the node specific to this wait operation
     612        wait_ctx_primed( this_thread, 0 );
    467613
    468614        monitor_save;
    469615        set_mask( monitors, count, mask );
    470616
    471         BlockInternal( locks, count );       // Everything is ready to go to sleep
    472         //WE WOKE UP
    473         monitor_restore;                     //We are back, restore the masks and recursions
     617        for(int i = 0; i < count; i++) {
     618                verify( monitors[i]->owner == this_thread );
     619        }
     620
     621        //Everything is ready to go to sleep
     622        BlockInternal( locks, count );
     623
     624
     625        // WE WOKE UP
     626
     627
     628        //We are back, restore the masks and recursions
     629        monitor_restore;
     630
     631        LIB_DEBUG_PRINT_SAFE("Kernel : exiting\n");
     632
     633        LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted);
    474634}
    475635
     
    478638
    479639static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
    480         LIB_DEBUG_PRINT_SAFE("Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
     640        // LIB_DEBUG_PRINT_SAFE("Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
    481641
    482642        //Pass the monitor appropriately
     
    497657                storage[i]->mask = mask;
    498658        }
     659}
     660
     661static inline void reset_mask( monitor_desc * this ) {
     662        this->mask.accepted = NULL;
     663        this->mask.clauses = NULL;
     664        this->mask.size = 0;
    499665}
    500666
     
    584750}
    585751
    586 static inline void save   ( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) {
     752static inline void save( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) {
    587753        for( int i = 0; i < count; i++ ) {
    588754                recursions[i] = ctx[i]->recursion;
  • src/libcfa/iostream

    rb96ec83 r6840e7c  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Sep 13 12:53:46 2017
    13 // Update Count     : 138
     12// Last Modified On : Tue Oct 10 14:51:10 2017
     13// Update Count     : 140
    1414//
    1515
     
    7979forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, const char * );
    8080forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, const char16_t * );
     81#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    8182forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, const char32_t * );
     83#endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    8284forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, const wchar_t * );
    8385forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, const void * );
  • src/libcfa/iostream.c

    rb96ec83 r6840e7c  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 17 23:24:25 2017
    13 // Update Count     : 422
     12// Last Modified On : Tue Oct 10 14:51:09 2017
     13// Update Count     : 424
    1414//
    1515
     
    191191} // ?|?
    192192
     193#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    193194forall( dtype ostype | ostream( ostype ) )
    194195ostype * ?|?( ostype * os, const char32_t * str ) {
     
    197198        return os;
    198199} // ?|?
     200#endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
    199201
    200202forall( dtype ostype | ostream( ostype ) )
  • src/main.cc

    rb96ec83 r6840e7c  
    4444#include "ControlStruct/Mutate.h"           // for mutate
    4545#include "GenPoly/Box.h"                    // for box
    46 #include "GenPoly/CopyParams.h"             // for copyParams
    4746#include "GenPoly/InstantiateGeneric.h"     // for instantiateGeneric
    4847#include "GenPoly/Lvalue.h"                 // for convertLvalue
     
    321320                OPTPRINT("instantiateGenerics")
    322321                GenPoly::instantiateGeneric( translationUnit );
    323                 OPTPRINT( "copyParams" );
    324                 GenPoly::copyParams( translationUnit );
    325322                OPTPRINT( "convertLvalue" )
    326323                GenPoly::convertLvalue( translationUnit );
  • src/prelude/extras.c

    rb96ec83 r6840e7c  
    11#include <stddef.h>                                     // size_t, ptrdiff_t
     2#include <stdint.h>                                     // intX_t, uintX_t, where X is 8, 16, 32, 64
    23#include <uchar.h>                                      // char16_t, char32_t
    34#include <wchar.h>                                      // wchar_t
  • src/prelude/extras.regx

    rb96ec83 r6840e7c  
    11typedef.* size_t;
    22typedef.* ptrdiff_t;
     3typedef.* int8_t;
     4typedef.* int16_t;
     5typedef.* int32_t;
     6typedef.* int64_t;
     7typedef.* uint8_t;
     8typedef.* uint16_t;
     9typedef.* uint32_t;
     10typedef.* uint64_t;
    311typedef.* char16_t;
    412typedef.* char32_t;
  • src/prelude/prelude.cf

    rb96ec83 r6840e7c  
    77// Created On       : Sat Nov 29 07:23:41 2014
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Wed Aug 30 07:56:07 2017
    10 // Update Count     : 93
     9// Last Modified On : Sun Oct  8 12:21:33 2017
     10// Update Count     : 97
    1111//
    1212
     
    558558signed long long int    ?+=?( signed long long int &, signed long long int ),   ?+=?( volatile signed long long int &, signed long long int );
    559559unsigned long long int  ?+=?( unsigned long long int &, unsigned long long int ), ?+=?( volatile unsigned long long int &, unsigned long long int );
     560//signed int128         ?+=?( signed int128 &, signed int128 ),                 ?+=?( volatile signed int128 &, signed int128 );
     561//unsigned int128               ?+=?( unsigned int128 &, unsigned int128 ),             ?+=?( volatile unsigned int128 &, unsigned int128 );
    560562
    561563_Bool                   ?-=?( _Bool &, _Bool ),                                 ?-=?( volatile _Bool &, _Bool );
  • src/tests/.expect/32/KRfunctions.txt

    rb96ec83 r6840e7c  
    2121static inline void ___destructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1);
    2222static inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___1(struct S *___dst__R2sS_1, struct S ___src__2sS_1);
     23static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __i__i_1);
    2324static inline void ___constructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1){
    2425    ((void)((*___dst__R2sS_1).__i__i_1) /* ?{} */);
     
    3334    struct S ___ret__2sS_1;
    3435    ((void)((*___dst__R2sS_1).__i__i_1=___src__2sS_1.__i__i_1));
    35     ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), ___src__2sS_1));
    36     return ((struct S )___ret__2sS_1);
     36    ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), (*___dst__R2sS_1)));
     37    return ___ret__2sS_1;
    3738}
    3839static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __i__i_1){
     
    6566    signed int *__x__FPi_ii__2(signed int __anonymous_object2, signed int __anonymous_object3);
    6667    ((void)(___retval_f10__PFPi_ii__1=__x__FPi_ii__2) /* ?{} */);
    67     return ((signed int *(*)(signed int __x__i_1, signed int __y__i_1))___retval_f10__PFPi_ii__1);
     68    return ___retval_f10__PFPi_ii__1;
    6869}
    6970signed int (*__f11__FPA0i_iPiPi__1(signed int __a__i_1, signed int *__b__Pi_1, signed int *__c__Pi_1))[]{
  • src/tests/.expect/32/attributes.txt

    rb96ec83 r6840e7c  
    2323static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_R13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
    2424    struct __anonymous0 ___ret__13s__anonymous0_1;
    25     ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), ___src__13s__anonymous0_1));
    26     return ((struct __anonymous0 )___ret__13s__anonymous0_1);
     25    ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), (*___dst__R13s__anonymous0_1)));
     26    return ___ret__13s__anonymous0_1;
    2727}
    2828__attribute__ ((unused)) struct Agn1;
     
    4141static inline struct Agn2 ___operator_assign__F5sAgn2_R5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__R5sAgn2_1, struct Agn2 ___src__5sAgn2_1){
    4242    struct Agn2 ___ret__5sAgn2_1;
    43     ((void)___constructor__F_R5sAgn25sAgn2_autogen___1((&___ret__5sAgn2_1), ___src__5sAgn2_1));
    44     return ((struct Agn2 )___ret__5sAgn2_1);
     43    ((void)___constructor__F_R5sAgn25sAgn2_autogen___1((&___ret__5sAgn2_1), (*___dst__R5sAgn2_1)));
     44    return ___ret__5sAgn2_1;
    4545}
    4646enum __attribute__ ((unused)) __anonymous1 {
     
    6969static inline void ___destructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1);
    7070static inline struct Fdl ___operator_assign__F4sFdl_R4sFdl4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1, struct Fdl ___src__4sFdl_1);
     71static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1);
     72static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1);
     73static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1);
     74static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1);
     75static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1);
     76static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1);
     77static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1);
     78static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1);
     79static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object1);
     80static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object2, signed int *__f9__Pi_1);
    7181static inline void ___constructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1){
    7282    ((void)((*___dst__R4sFdl_1).__f1__i_1) /* ?{} */);
     
    7888    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    7989    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     90    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    8091    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    8192}
     
    89100    ((void)((*___dst__R4sFdl_1).__f7__i_1=___src__4sFdl_1.__f7__i_1) /* ?{} */);
    90101    ((void)((*___dst__R4sFdl_1).__f8__i_1=___src__4sFdl_1.__f8__i_1) /* ?{} */);
     102    ((void)((*___dst__R4sFdl_1).__anonymous_object0=___src__4sFdl_1.__anonymous_object0) /* ?{} */);
    91103    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=___src__4sFdl_1.__f9__Pi_1) /* ?{} */);
    92104}
    93105static inline void ___destructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1){
    94106    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ^?{} */);
     107    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ^?{} */);
    95108    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ^?{} */);
    96109    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ^?{} */);
     
    112125    ((void)((*___dst__R4sFdl_1).__f7__i_1=___src__4sFdl_1.__f7__i_1));
    113126    ((void)((*___dst__R4sFdl_1).__f8__i_1=___src__4sFdl_1.__f8__i_1));
     127    ((void)((*___dst__R4sFdl_1).__anonymous_object0=___src__4sFdl_1.__anonymous_object0));
    114128    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=___src__4sFdl_1.__f9__Pi_1));
    115     ((void)___constructor__F_R4sFdl4sFdl_autogen___1((&___ret__4sFdl_1), ___src__4sFdl_1));
    116     return ((struct Fdl )___ret__4sFdl_1);
     129    ((void)___constructor__F_R4sFdl4sFdl_autogen___1((&___ret__4sFdl_1), (*___dst__R4sFdl_1)));
     130    return ___ret__4sFdl_1;
    117131}
    118132static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1){
     
    125139    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    126140    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     141    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    127142    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    128143}
     
    136151    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    137152    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     153    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    138154    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    139155}
     
    147163    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    148164    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     165    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    149166    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    150167}
     
    158175    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    159176    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     177    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    160178    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    161179}
     
    169187    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    170188    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     189    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    171190    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    172191}
     
    180199    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    181200    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     201    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    182202    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    183203}
     
    191211    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    192212    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     213    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    193214    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    194215}
     
    202223    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    203224    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
    204     ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    205 }
    206 static inline void ___constructor__F_R4sFdliiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int *__f9__Pi_1){
     225    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
     226    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
     227}
     228static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object3){
    207229    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    208230    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    213235    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    214236    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
     237    ((void)((*___dst__R4sFdl_1).__anonymous_object0=__anonymous_object3) /* ?{} */);
     238    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
     239}
     240static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object4, signed int *__f9__Pi_1){
     241    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
     242    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     243    ((void)((*___dst__R4sFdl_1).__f3__i_1=__f3__i_1) /* ?{} */);
     244    ((void)((*___dst__R4sFdl_1).__f4__i_1=__f4__i_1) /* ?{} */);
     245    ((void)((*___dst__R4sFdl_1).__f5__i_1=__f5__i_1) /* ?{} */);
     246    ((void)((*___dst__R4sFdl_1).__f6__i_1=__f6__i_1) /* ?{} */);
     247    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
     248    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
     249    ((void)((*___dst__R4sFdl_1).__anonymous_object0=__anonymous_object4) /* ?{} */);
    215250    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=__f9__Pi_1) /* ?{} */);
    216251}
     
    232267    __attribute__ ((unused)) signed int **const ___retval_f2__CPPi_1;
    233268}
    234 __attribute__ ((unused,used,unused)) signed int (*__f3__FPA0i_i__1(signed int __anonymous_object1))[];
     269__attribute__ ((unused,used,unused)) signed int (*__f3__FPA0i_i__1(signed int __anonymous_object5))[];
    235270__attribute__ ((unused,unused)) signed int (*__f3__FPA0i_i__1(signed int __p__i_1))[]{
    236271    __attribute__ ((unused)) signed int (*___retval_f3__PA0i_1)[];
    237272}
    238 __attribute__ ((unused,used,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object2);
    239 __attribute__ ((unused,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object3){
    240     __attribute__ ((unused)) signed int (*___retval_f4__PFi_i__1)(signed int __anonymous_object4);
     273__attribute__ ((unused,used,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object6);
     274__attribute__ ((unused,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object7){
     275    __attribute__ ((unused)) signed int (*___retval_f4__PFi_i__1)(signed int __anonymous_object8);
    241276}
    242277signed int __vtr__Fi___1(){
     
    268303signed int __tpr2__Fi_PPi__1(__attribute__ ((unused,unused,unused,unused,unused,unused)) signed int **__Foo__PPi_1);
    269304signed int __tpr3__Fi_Pi__1(__attribute__ ((unused,unused,unused)) signed int *__Foo__Pi_1);
    270 signed int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) signed int (*__anonymous_object5)(__attribute__ ((unused,unused)) signed int __anonymous_object6[((unsigned int )5)]));
     305signed int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) signed int (*__anonymous_object9)(__attribute__ ((unused,unused)) signed int __anonymous_object10[((unsigned int )5)]));
    271306signed int __tpr5__Fi_PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__Foo__PFi___1)());
    272307signed int __tpr6__Fi_PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__Foo__PFi___1)());
    273 signed int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) signed int (*__anonymous_object7)(__attribute__ ((unused)) signed int (*__anonymous_object8)(__attribute__ ((unused,unused)) signed int __anonymous_object9)));
     308signed int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) signed int (*__anonymous_object11)(__attribute__ ((unused)) signed int (*__anonymous_object12)(__attribute__ ((unused,unused)) signed int __anonymous_object13)));
    274309signed int __ad__Fi___1(){
    275310    __attribute__ ((unused)) signed int ___retval_ad__i_1;
     
    300335        struct __anonymous4 ___ret__13s__anonymous4_2;
    301336        ((void)((*___dst__R13s__anonymous4_2).__i__i_2=___src__13s__anonymous4_2.__i__i_2));
    302         ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___2((&___ret__13s__anonymous4_2), ___src__13s__anonymous4_2));
    303         return ((struct __anonymous4 )___ret__13s__anonymous4_2);
     337        ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___2((&___ret__13s__anonymous4_2), (*___dst__R13s__anonymous4_2)));
     338        return ___ret__13s__anonymous4_2;
    304339    }
    305340    inline void ___constructor__F_R13s__anonymous4i_autogen___2(struct __anonymous4 *___dst__R13s__anonymous4_2, signed int __i__i_2){
     
    313348    }
    314349    inline void ___constructor__F_R13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__R13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
    315         ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2));
     350        ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2) /* ?{} */);
    316351    }
    317352    inline void ___destructor__F_R13e__anonymous5_intrinsic___2(__attribute__ ((unused)) enum __anonymous5 *___dst__R13e__anonymous5_2){
     
    319354    inline enum __anonymous5 ___operator_assign__F13e__anonymous5_R13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__R13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
    320355        enum __anonymous5 ___ret__13e__anonymous5_2;
    321         ((void)(___ret__13e__anonymous5_2=((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2)) /* ?{} */);
    322         return ((enum __anonymous5 )___ret__13e__anonymous5_2);
     356        ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2));
     357        ((void)(___ret__13e__anonymous5_2=(*___dst__R13e__anonymous5_2)) /* ?{} */);
     358        return ___ret__13e__anonymous5_2;
    323359    }
    324360    ((void)sizeof(enum __anonymous5 ));
    325361}
    326 signed int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object10, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object11);
    327 signed int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object12, __attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object13);
    328 signed int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object14, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object15);
    329 signed int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)());
    330 signed int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object18)(__attribute__ ((unused)) signed int __anonymous_object19), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object20)(__attribute__ ((unused)) signed int __anonymous_object21));
    331 signed int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object22)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object23)());
    332 signed int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object24)(__attribute__ ((unused)) signed int __anonymous_object25), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object26)(__attribute__ ((unused)) signed int __anonymous_object27));
     362signed int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object14, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object15);
     363signed int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object16, __attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object17);
     364signed int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object18, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object19);
     365signed int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object20)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object21)());
     366signed int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object22)(__attribute__ ((unused)) signed int __anonymous_object23), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object24)(__attribute__ ((unused)) signed int __anonymous_object25));
     367signed int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object26)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object27)());
     368signed int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object28)(__attribute__ ((unused)) signed int __anonymous_object29), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object30)(__attribute__ ((unused)) signed int __anonymous_object31));
    333369struct Vad {
    334     __attribute__ ((unused)) signed int __anonymous_object28;
    335     __attribute__ ((unused,unused)) signed int *__anonymous_object29;
    336     __attribute__ ((unused,unused)) signed int __anonymous_object30[((unsigned int )10)];
    337     __attribute__ ((unused,unused)) signed int (*__anonymous_object31)();
     370    __attribute__ ((unused)) signed int __anonymous_object32;
     371    __attribute__ ((unused,unused)) signed int *__anonymous_object33;
     372    __attribute__ ((unused,unused)) signed int __anonymous_object34[((unsigned int )10)];
     373    __attribute__ ((unused,unused)) signed int (*__anonymous_object35)();
    338374};
    339375static inline void ___constructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1);
     
    341377static inline void ___destructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1);
    342378static inline struct Vad ___operator_assign__F4sVad_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1);
     379static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object36);
     380static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object37, signed int *__anonymous_object38);
     381static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object39, signed int *__anonymous_object40, signed int __anonymous_object41[((unsigned int )10)]);
     382static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object42, signed int *__anonymous_object43, signed int __anonymous_object44[((unsigned int )10)], signed int (*__anonymous_object45)());
    343383static inline void ___constructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1){
     384    ((void)((*___dst__R4sVad_1).__anonymous_object32) /* ?{} */);
     385    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ?{} */);
     386    {
     387        signed int _index0 = 0;
     388        for (;(_index0<10);((void)(++_index0))) {
     389            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index0])))) /* ?{} */);
     390        }
     391
     392    }
     393
     394    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
    344395}
    345396static inline void ___constructor__F_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1){
     397    ((void)((*___dst__R4sVad_1).__anonymous_object32=___src__4sVad_1.__anonymous_object32) /* ?{} */);
     398    ((void)((*___dst__R4sVad_1).__anonymous_object33=___src__4sVad_1.__anonymous_object33) /* ?{} */);
     399    {
     400        signed int _index1 = 0;
     401        for (;(_index1<10);((void)(++_index1))) {
     402            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index1])))=___src__4sVad_1.__anonymous_object34[_index1]) /* ?{} */);
     403        }
     404
     405    }
     406
     407    ((void)((*___dst__R4sVad_1).__anonymous_object35=___src__4sVad_1.__anonymous_object35) /* ?{} */);
    346408}
    347409static inline void ___destructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1){
     410    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ^?{} */);
     411    {
     412        signed int _index2 = (10-1);
     413        for (;(_index2>=0);((void)(--_index2))) {
     414            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index2])))) /* ^?{} */);
     415        }
     416
     417    }
     418
     419    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ^?{} */);
     420    ((void)((*___dst__R4sVad_1).__anonymous_object32) /* ^?{} */);
    348421}
    349422static inline struct Vad ___operator_assign__F4sVad_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1){
    350423    struct Vad ___ret__4sVad_1;
    351     ((void)___constructor__F_R4sVad4sVad_autogen___1((&___ret__4sVad_1), ___src__4sVad_1));
    352     return ((struct Vad )___ret__4sVad_1);
    353 }
     424    ((void)((*___dst__R4sVad_1).__anonymous_object32=___src__4sVad_1.__anonymous_object32));
     425    ((void)((*___dst__R4sVad_1).__anonymous_object33=___src__4sVad_1.__anonymous_object33));
     426    {
     427        signed int _index3 = 0;
     428        for (;(_index3<10);((void)(++_index3))) {
     429            ((void)((*___dst__R4sVad_1).__anonymous_object34[_index3]=___src__4sVad_1.__anonymous_object34[_index3]));
     430        }
     431
     432    }
     433
     434    ((void)((*___dst__R4sVad_1).__anonymous_object35=___src__4sVad_1.__anonymous_object35));
     435    ((void)___constructor__F_R4sVad4sVad_autogen___1((&___ret__4sVad_1), (*___dst__R4sVad_1)));
     436    return ___ret__4sVad_1;
     437}
     438static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object46){
     439    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object46) /* ?{} */);
     440    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ?{} */);
     441    {
     442        signed int _index4 = 0;
     443        for (;(_index4<10);((void)(++_index4))) {
     444            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index4])))) /* ?{} */);
     445        }
     446
     447    }
     448
     449    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     450}
     451static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object47, signed int *__anonymous_object48){
     452    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object47) /* ?{} */);
     453    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object48) /* ?{} */);
     454    {
     455        signed int _index5 = 0;
     456        for (;(_index5<10);((void)(++_index5))) {
     457            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index5])))) /* ?{} */);
     458        }
     459
     460    }
     461
     462    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     463}
     464static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object49, signed int *__anonymous_object50, signed int __anonymous_object51[((unsigned int )10)]){
     465    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object49) /* ?{} */);
     466    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object50) /* ?{} */);
     467    {
     468        signed int _index6 = 0;
     469        for (;(_index6<10);((void)(++_index6))) {
     470            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index6])))=__anonymous_object51[_index6]) /* ?{} */);
     471        }
     472
     473    }
     474
     475    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     476}
     477static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object52, signed int *__anonymous_object53, signed int __anonymous_object54[((unsigned int )10)], signed int (*__anonymous_object55)()){
     478    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object52) /* ?{} */);
     479    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object53) /* ?{} */);
     480    {
     481        signed int _index7 = 0;
     482        for (;(_index7<10);((void)(++_index7))) {
     483            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[_index7])))=__anonymous_object54[_index7]) /* ?{} */);
     484        }
     485
     486    }
     487
     488    ((void)((*___dst__R4sVad_1).__anonymous_object35=__anonymous_object55) /* ?{} */);
     489}
  • src/tests/.expect/32/declarationSpecifier.txt

    rb96ec83 r6840e7c  
    2020static inline void ___destructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1);
    2121static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_R13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1);
     22static inline void ___constructor__F_R13s__anonymous0i_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, signed int __i__i_1);
    2223static inline void ___constructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1){
    2324    ((void)((*___dst__R13s__anonymous0_1).__i__i_1) /* ?{} */);
     
    3233    struct __anonymous0 ___ret__13s__anonymous0_1;
    3334    ((void)((*___dst__R13s__anonymous0_1).__i__i_1=___src__13s__anonymous0_1.__i__i_1));
    34     ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), ___src__13s__anonymous0_1));
    35     return ((struct __anonymous0 )___ret__13s__anonymous0_1);
     35    ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), (*___dst__R13s__anonymous0_1)));
     36    return ___ret__13s__anonymous0_1;
    3637}
    3738static inline void ___constructor__F_R13s__anonymous0i_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, signed int __i__i_1){
     
    4647static inline void ___destructor__F_R13s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1);
    4748static inline struct __anonymous1 ___operator_assign__F13s__anonymous1_R13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1);
     49static inline void ___constructor__F_R13s__anonymous1i_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, signed int __i__i_1);
    4850static inline void ___constructor__F_R13s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1){
    4951    ((void)((*___dst__R13s__anonymous1_1).__i__i_1) /* ?{} */);
     
    5860    struct __anonymous1 ___ret__13s__anonymous1_1;
    5961    ((void)((*___dst__R13s__anonymous1_1).__i__i_1=___src__13s__anonymous1_1.__i__i_1));
    60     ((void)___constructor__F_R13s__anonymous113s__anonymous1_autogen___1((&___ret__13s__anonymous1_1), ___src__13s__anonymous1_1));
    61     return ((struct __anonymous1 )___ret__13s__anonymous1_1);
     62    ((void)___constructor__F_R13s__anonymous113s__anonymous1_autogen___1((&___ret__13s__anonymous1_1), (*___dst__R13s__anonymous1_1)));
     63    return ___ret__13s__anonymous1_1;
    6264}
    6365static inline void ___constructor__F_R13s__anonymous1i_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, signed int __i__i_1){
     
    7274static inline void ___destructor__F_R13s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1);
    7375static inline struct __anonymous2 ___operator_assign__F13s__anonymous2_R13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1);
     76static inline void ___constructor__F_R13s__anonymous2i_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, signed int __i__i_1);
    7477static inline void ___constructor__F_R13s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1){
    7578    ((void)((*___dst__R13s__anonymous2_1).__i__i_1) /* ?{} */);
     
    8487    struct __anonymous2 ___ret__13s__anonymous2_1;
    8588    ((void)((*___dst__R13s__anonymous2_1).__i__i_1=___src__13s__anonymous2_1.__i__i_1));
    86     ((void)___constructor__F_R13s__anonymous213s__anonymous2_autogen___1((&___ret__13s__anonymous2_1), ___src__13s__anonymous2_1));
    87     return ((struct __anonymous2 )___ret__13s__anonymous2_1);
     89    ((void)___constructor__F_R13s__anonymous213s__anonymous2_autogen___1((&___ret__13s__anonymous2_1), (*___dst__R13s__anonymous2_1)));
     90    return ___ret__13s__anonymous2_1;
    8891}
    8992static inline void ___constructor__F_R13s__anonymous2i_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, signed int __i__i_1){
     
    98101static inline void ___destructor__F_R13s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1);
    99102static inline struct __anonymous3 ___operator_assign__F13s__anonymous3_R13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1);
     103static inline void ___constructor__F_R13s__anonymous3i_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, signed int __i__i_1);
    100104static inline void ___constructor__F_R13s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1){
    101105    ((void)((*___dst__R13s__anonymous3_1).__i__i_1) /* ?{} */);
     
    110114    struct __anonymous3 ___ret__13s__anonymous3_1;
    111115    ((void)((*___dst__R13s__anonymous3_1).__i__i_1=___src__13s__anonymous3_1.__i__i_1));
    112     ((void)___constructor__F_R13s__anonymous313s__anonymous3_autogen___1((&___ret__13s__anonymous3_1), ___src__13s__anonymous3_1));
    113     return ((struct __anonymous3 )___ret__13s__anonymous3_1);
     116    ((void)___constructor__F_R13s__anonymous313s__anonymous3_autogen___1((&___ret__13s__anonymous3_1), (*___dst__R13s__anonymous3_1)));
     117    return ___ret__13s__anonymous3_1;
    114118}
    115119static inline void ___constructor__F_R13s__anonymous3i_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, signed int __i__i_1){
     
    124128static inline void ___destructor__F_R13s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1);
    125129static inline struct __anonymous4 ___operator_assign__F13s__anonymous4_R13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1);
     130static inline void ___constructor__F_R13s__anonymous4i_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, signed int __i__i_1);
    126131static inline void ___constructor__F_R13s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1){
    127132    ((void)((*___dst__R13s__anonymous4_1).__i__i_1) /* ?{} */);
     
    136141    struct __anonymous4 ___ret__13s__anonymous4_1;
    137142    ((void)((*___dst__R13s__anonymous4_1).__i__i_1=___src__13s__anonymous4_1.__i__i_1));
    138     ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___1((&___ret__13s__anonymous4_1), ___src__13s__anonymous4_1));
    139     return ((struct __anonymous4 )___ret__13s__anonymous4_1);
     143    ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___1((&___ret__13s__anonymous4_1), (*___dst__R13s__anonymous4_1)));
     144    return ___ret__13s__anonymous4_1;
    140145}
    141146static inline void ___constructor__F_R13s__anonymous4i_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, signed int __i__i_1){
     
    150155static inline void ___destructor__F_R13s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1);
    151156static inline struct __anonymous5 ___operator_assign__F13s__anonymous5_R13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1);
     157static inline void ___constructor__F_R13s__anonymous5i_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, signed int __i__i_1);
    152158static inline void ___constructor__F_R13s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1){
    153159    ((void)((*___dst__R13s__anonymous5_1).__i__i_1) /* ?{} */);
     
    162168    struct __anonymous5 ___ret__13s__anonymous5_1;
    163169    ((void)((*___dst__R13s__anonymous5_1).__i__i_1=___src__13s__anonymous5_1.__i__i_1));
    164     ((void)___constructor__F_R13s__anonymous513s__anonymous5_autogen___1((&___ret__13s__anonymous5_1), ___src__13s__anonymous5_1));
    165     return ((struct __anonymous5 )___ret__13s__anonymous5_1);
     170    ((void)___constructor__F_R13s__anonymous513s__anonymous5_autogen___1((&___ret__13s__anonymous5_1), (*___dst__R13s__anonymous5_1)));
     171    return ___ret__13s__anonymous5_1;
    166172}
    167173static inline void ___constructor__F_R13s__anonymous5i_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, signed int __i__i_1){
     
    176182static inline void ___destructor__F_R13s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1);
    177183static inline struct __anonymous6 ___operator_assign__F13s__anonymous6_R13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1);
     184static inline void ___constructor__F_R13s__anonymous6i_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, signed int __i__i_1);
    178185static inline void ___constructor__F_R13s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1){
    179186    ((void)((*___dst__R13s__anonymous6_1).__i__i_1) /* ?{} */);
     
    188195    struct __anonymous6 ___ret__13s__anonymous6_1;
    189196    ((void)((*___dst__R13s__anonymous6_1).__i__i_1=___src__13s__anonymous6_1.__i__i_1));
    190     ((void)___constructor__F_R13s__anonymous613s__anonymous6_autogen___1((&___ret__13s__anonymous6_1), ___src__13s__anonymous6_1));
    191     return ((struct __anonymous6 )___ret__13s__anonymous6_1);
     197    ((void)___constructor__F_R13s__anonymous613s__anonymous6_autogen___1((&___ret__13s__anonymous6_1), (*___dst__R13s__anonymous6_1)));
     198    return ___ret__13s__anonymous6_1;
    192199}
    193200static inline void ___constructor__F_R13s__anonymous6i_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, signed int __i__i_1){
     
    202209static inline void ___destructor__F_R13s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1);
    203210static inline struct __anonymous7 ___operator_assign__F13s__anonymous7_R13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1);
     211static inline void ___constructor__F_R13s__anonymous7i_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, signed int __i__i_1);
    204212static inline void ___constructor__F_R13s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1){
    205213    ((void)((*___dst__R13s__anonymous7_1).__i__i_1) /* ?{} */);
     
    214222    struct __anonymous7 ___ret__13s__anonymous7_1;
    215223    ((void)((*___dst__R13s__anonymous7_1).__i__i_1=___src__13s__anonymous7_1.__i__i_1));
    216     ((void)___constructor__F_R13s__anonymous713s__anonymous7_autogen___1((&___ret__13s__anonymous7_1), ___src__13s__anonymous7_1));
    217     return ((struct __anonymous7 )___ret__13s__anonymous7_1);
     224    ((void)___constructor__F_R13s__anonymous713s__anonymous7_autogen___1((&___ret__13s__anonymous7_1), (*___dst__R13s__anonymous7_1)));
     225    return ___ret__13s__anonymous7_1;
    218226}
    219227static inline void ___constructor__F_R13s__anonymous7i_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, signed int __i__i_1){
     
    236244static inline void ___destructor__F_R13s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1);
    237245static inline struct __anonymous8 ___operator_assign__F13s__anonymous8_R13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1);
     246static inline void ___constructor__F_R13s__anonymous8s_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, signed short int __i__s_1);
    238247static inline void ___constructor__F_R13s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1){
    239248    ((void)((*___dst__R13s__anonymous8_1).__i__s_1) /* ?{} */);
     
    248257    struct __anonymous8 ___ret__13s__anonymous8_1;
    249258    ((void)((*___dst__R13s__anonymous8_1).__i__s_1=___src__13s__anonymous8_1.__i__s_1));
    250     ((void)___constructor__F_R13s__anonymous813s__anonymous8_autogen___1((&___ret__13s__anonymous8_1), ___src__13s__anonymous8_1));
    251     return ((struct __anonymous8 )___ret__13s__anonymous8_1);
     259    ((void)___constructor__F_R13s__anonymous813s__anonymous8_autogen___1((&___ret__13s__anonymous8_1), (*___dst__R13s__anonymous8_1)));
     260    return ___ret__13s__anonymous8_1;
    252261}
    253262static inline void ___constructor__F_R13s__anonymous8s_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, signed short int __i__s_1){
     
    262271static inline void ___destructor__F_R13s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1);
    263272static inline struct __anonymous9 ___operator_assign__F13s__anonymous9_R13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1);
     273static inline void ___constructor__F_R13s__anonymous9s_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, signed short int __i__s_1);
    264274static inline void ___constructor__F_R13s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1){
    265275    ((void)((*___dst__R13s__anonymous9_1).__i__s_1) /* ?{} */);
     
    274284    struct __anonymous9 ___ret__13s__anonymous9_1;
    275285    ((void)((*___dst__R13s__anonymous9_1).__i__s_1=___src__13s__anonymous9_1.__i__s_1));
    276     ((void)___constructor__F_R13s__anonymous913s__anonymous9_autogen___1((&___ret__13s__anonymous9_1), ___src__13s__anonymous9_1));
    277     return ((struct __anonymous9 )___ret__13s__anonymous9_1);
     286    ((void)___constructor__F_R13s__anonymous913s__anonymous9_autogen___1((&___ret__13s__anonymous9_1), (*___dst__R13s__anonymous9_1)));
     287    return ___ret__13s__anonymous9_1;
    278288}
    279289static inline void ___constructor__F_R13s__anonymous9s_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, signed short int __i__s_1){
     
    288298static inline void ___destructor__F_R14s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1);
    289299static inline struct __anonymous10 ___operator_assign__F14s__anonymous10_R14s__anonymous1014s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, struct __anonymous10 ___src__14s__anonymous10_1);
     300static inline void ___constructor__F_R14s__anonymous10s_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, signed short int __i__s_1);
    290301static inline void ___constructor__F_R14s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1){
    291302    ((void)((*___dst__R14s__anonymous10_1).__i__s_1) /* ?{} */);
     
    300311    struct __anonymous10 ___ret__14s__anonymous10_1;
    301312    ((void)((*___dst__R14s__anonymous10_1).__i__s_1=___src__14s__anonymous10_1.__i__s_1));
    302     ((void)___constructor__F_R14s__anonymous1014s__anonymous10_autogen___1((&___ret__14s__anonymous10_1), ___src__14s__anonymous10_1));
    303     return ((struct __anonymous10 )___ret__14s__anonymous10_1);
     313    ((void)___constructor__F_R14s__anonymous1014s__anonymous10_autogen___1((&___ret__14s__anonymous10_1), (*___dst__R14s__anonymous10_1)));
     314    return ___ret__14s__anonymous10_1;
    304315}
    305316static inline void ___constructor__F_R14s__anonymous10s_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, signed short int __i__s_1){
     
    314325static inline void ___destructor__F_R14s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1);
    315326static inline struct __anonymous11 ___operator_assign__F14s__anonymous11_R14s__anonymous1114s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, struct __anonymous11 ___src__14s__anonymous11_1);
     327static inline void ___constructor__F_R14s__anonymous11s_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, signed short int __i__s_1);
    316328static inline void ___constructor__F_R14s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1){
    317329    ((void)((*___dst__R14s__anonymous11_1).__i__s_1) /* ?{} */);
     
    326338    struct __anonymous11 ___ret__14s__anonymous11_1;
    327339    ((void)((*___dst__R14s__anonymous11_1).__i__s_1=___src__14s__anonymous11_1.__i__s_1));
    328     ((void)___constructor__F_R14s__anonymous1114s__anonymous11_autogen___1((&___ret__14s__anonymous11_1), ___src__14s__anonymous11_1));
    329     return ((struct __anonymous11 )___ret__14s__anonymous11_1);
     340    ((void)___constructor__F_R14s__anonymous1114s__anonymous11_autogen___1((&___ret__14s__anonymous11_1), (*___dst__R14s__anonymous11_1)));
     341    return ___ret__14s__anonymous11_1;
    330342}
    331343static inline void ___constructor__F_R14s__anonymous11s_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, signed short int __i__s_1){
     
    340352static inline void ___destructor__F_R14s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1);
    341353static inline struct __anonymous12 ___operator_assign__F14s__anonymous12_R14s__anonymous1214s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, struct __anonymous12 ___src__14s__anonymous12_1);
     354static inline void ___constructor__F_R14s__anonymous12s_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, signed short int __i__s_1);
    342355static inline void ___constructor__F_R14s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1){
    343356    ((void)((*___dst__R14s__anonymous12_1).__i__s_1) /* ?{} */);
     
    352365    struct __anonymous12 ___ret__14s__anonymous12_1;
    353366    ((void)((*___dst__R14s__anonymous12_1).__i__s_1=___src__14s__anonymous12_1.__i__s_1));
    354     ((void)___constructor__F_R14s__anonymous1214s__anonymous12_autogen___1((&___ret__14s__anonymous12_1), ___src__14s__anonymous12_1));
    355     return ((struct __anonymous12 )___ret__14s__anonymous12_1);
     367    ((void)___constructor__F_R14s__anonymous1214s__anonymous12_autogen___1((&___ret__14s__anonymous12_1), (*___dst__R14s__anonymous12_1)));
     368    return ___ret__14s__anonymous12_1;
    356369}
    357370static inline void ___constructor__F_R14s__anonymous12s_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, signed short int __i__s_1){
     
    366379static inline void ___destructor__F_R14s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1);
    367380static inline struct __anonymous13 ___operator_assign__F14s__anonymous13_R14s__anonymous1314s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, struct __anonymous13 ___src__14s__anonymous13_1);
     381static inline void ___constructor__F_R14s__anonymous13s_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, signed short int __i__s_1);
    368382static inline void ___constructor__F_R14s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1){
    369383    ((void)((*___dst__R14s__anonymous13_1).__i__s_1) /* ?{} */);
     
    378392    struct __anonymous13 ___ret__14s__anonymous13_1;
    379393    ((void)((*___dst__R14s__anonymous13_1).__i__s_1=___src__14s__anonymous13_1.__i__s_1));
    380     ((void)___constructor__F_R14s__anonymous1314s__anonymous13_autogen___1((&___ret__14s__anonymous13_1), ___src__14s__anonymous13_1));
    381     return ((struct __anonymous13 )___ret__14s__anonymous13_1);
     394    ((void)___constructor__F_R14s__anonymous1314s__anonymous13_autogen___1((&___ret__14s__anonymous13_1), (*___dst__R14s__anonymous13_1)));
     395    return ___ret__14s__anonymous13_1;
    382396}
    383397static inline void ___constructor__F_R14s__anonymous13s_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, signed short int __i__s_1){
     
    392406static inline void ___destructor__F_R14s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1);
    393407static inline struct __anonymous14 ___operator_assign__F14s__anonymous14_R14s__anonymous1414s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, struct __anonymous14 ___src__14s__anonymous14_1);
     408static inline void ___constructor__F_R14s__anonymous14s_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, signed short int __i__s_1);
    394409static inline void ___constructor__F_R14s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1){
    395410    ((void)((*___dst__R14s__anonymous14_1).__i__s_1) /* ?{} */);
     
    404419    struct __anonymous14 ___ret__14s__anonymous14_1;
    405420    ((void)((*___dst__R14s__anonymous14_1).__i__s_1=___src__14s__anonymous14_1.__i__s_1));
    406     ((void)___constructor__F_R14s__anonymous1414s__anonymous14_autogen___1((&___ret__14s__anonymous14_1), ___src__14s__anonymous14_1));
    407     return ((struct __anonymous14 )___ret__14s__anonymous14_1);
     421    ((void)___constructor__F_R14s__anonymous1414s__anonymous14_autogen___1((&___ret__14s__anonymous14_1), (*___dst__R14s__anonymous14_1)));
     422    return ___ret__14s__anonymous14_1;
    408423}
    409424static inline void ___constructor__F_R14s__anonymous14s_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, signed short int __i__s_1){
     
    418433static inline void ___destructor__F_R14s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1);
    419434static inline struct __anonymous15 ___operator_assign__F14s__anonymous15_R14s__anonymous1514s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, struct __anonymous15 ___src__14s__anonymous15_1);
     435static inline void ___constructor__F_R14s__anonymous15s_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, signed short int __i__s_1);
    420436static inline void ___constructor__F_R14s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1){
    421437    ((void)((*___dst__R14s__anonymous15_1).__i__s_1) /* ?{} */);
     
    430446    struct __anonymous15 ___ret__14s__anonymous15_1;
    431447    ((void)((*___dst__R14s__anonymous15_1).__i__s_1=___src__14s__anonymous15_1.__i__s_1));
    432     ((void)___constructor__F_R14s__anonymous1514s__anonymous15_autogen___1((&___ret__14s__anonymous15_1), ___src__14s__anonymous15_1));
    433     return ((struct __anonymous15 )___ret__14s__anonymous15_1);
     448    ((void)___constructor__F_R14s__anonymous1514s__anonymous15_autogen___1((&___ret__14s__anonymous15_1), (*___dst__R14s__anonymous15_1)));
     449    return ___ret__14s__anonymous15_1;
    434450}
    435451static inline void ___constructor__F_R14s__anonymous15s_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, signed short int __i__s_1){
     
    460476static inline void ___destructor__F_R14s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1);
    461477static inline struct __anonymous16 ___operator_assign__F14s__anonymous16_R14s__anonymous1614s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, struct __anonymous16 ___src__14s__anonymous16_1);
     478static inline void ___constructor__F_R14s__anonymous16i_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, signed int __i__i_1);
    462479static inline void ___constructor__F_R14s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1){
    463480    ((void)((*___dst__R14s__anonymous16_1).__i__i_1) /* ?{} */);
     
    472489    struct __anonymous16 ___ret__14s__anonymous16_1;
    473490    ((void)((*___dst__R14s__anonymous16_1).__i__i_1=___src__14s__anonymous16_1.__i__i_1));
    474     ((void)___constructor__F_R14s__anonymous1614s__anonymous16_autogen___1((&___ret__14s__anonymous16_1), ___src__14s__anonymous16_1));
    475     return ((struct __anonymous16 )___ret__14s__anonymous16_1);
     491    ((void)___constructor__F_R14s__anonymous1614s__anonymous16_autogen___1((&___ret__14s__anonymous16_1), (*___dst__R14s__anonymous16_1)));
     492    return ___ret__14s__anonymous16_1;
    476493}
    477494static inline void ___constructor__F_R14s__anonymous16i_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, signed int __i__i_1){
     
    486503static inline void ___destructor__F_R14s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1);
    487504static inline struct __anonymous17 ___operator_assign__F14s__anonymous17_R14s__anonymous1714s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, struct __anonymous17 ___src__14s__anonymous17_1);
     505static inline void ___constructor__F_R14s__anonymous17i_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, signed int __i__i_1);
    488506static inline void ___constructor__F_R14s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1){
    489507    ((void)((*___dst__R14s__anonymous17_1).__i__i_1) /* ?{} */);
     
    498516    struct __anonymous17 ___ret__14s__anonymous17_1;
    499517    ((void)((*___dst__R14s__anonymous17_1).__i__i_1=___src__14s__anonymous17_1.__i__i_1));
    500     ((void)___constructor__F_R14s__anonymous1714s__anonymous17_autogen___1((&___ret__14s__anonymous17_1), ___src__14s__anonymous17_1));
    501     return ((struct __anonymous17 )___ret__14s__anonymous17_1);
     518    ((void)___constructor__F_R14s__anonymous1714s__anonymous17_autogen___1((&___ret__14s__anonymous17_1), (*___dst__R14s__anonymous17_1)));
     519    return ___ret__14s__anonymous17_1;
    502520}
    503521static inline void ___constructor__F_R14s__anonymous17i_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, signed int __i__i_1){
     
    512530static inline void ___destructor__F_R14s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1);
    513531static inline struct __anonymous18 ___operator_assign__F14s__anonymous18_R14s__anonymous1814s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, struct __anonymous18 ___src__14s__anonymous18_1);
     532static inline void ___constructor__F_R14s__anonymous18i_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, signed int __i__i_1);
    514533static inline void ___constructor__F_R14s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1){
    515534    ((void)((*___dst__R14s__anonymous18_1).__i__i_1) /* ?{} */);
     
    524543    struct __anonymous18 ___ret__14s__anonymous18_1;
    525544    ((void)((*___dst__R14s__anonymous18_1).__i__i_1=___src__14s__anonymous18_1.__i__i_1));
    526     ((void)___constructor__F_R14s__anonymous1814s__anonymous18_autogen___1((&___ret__14s__anonymous18_1), ___src__14s__anonymous18_1));
    527     return ((struct __anonymous18 )___ret__14s__anonymous18_1);
     545    ((void)___constructor__F_R14s__anonymous1814s__anonymous18_autogen___1((&___ret__14s__anonymous18_1), (*___dst__R14s__anonymous18_1)));
     546    return ___ret__14s__anonymous18_1;
    528547}
    529548static inline void ___constructor__F_R14s__anonymous18i_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, signed int __i__i_1){
     
    538557static inline void ___destructor__F_R14s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1);
    539558static inline struct __anonymous19 ___operator_assign__F14s__anonymous19_R14s__anonymous1914s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, struct __anonymous19 ___src__14s__anonymous19_1);
     559static inline void ___constructor__F_R14s__anonymous19i_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, signed int __i__i_1);
    540560static inline void ___constructor__F_R14s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1){
    541561    ((void)((*___dst__R14s__anonymous19_1).__i__i_1) /* ?{} */);
     
    550570    struct __anonymous19 ___ret__14s__anonymous19_1;
    551571    ((void)((*___dst__R14s__anonymous19_1).__i__i_1=___src__14s__anonymous19_1.__i__i_1));
    552     ((void)___constructor__F_R14s__anonymous1914s__anonymous19_autogen___1((&___ret__14s__anonymous19_1), ___src__14s__anonymous19_1));
    553     return ((struct __anonymous19 )___ret__14s__anonymous19_1);
     572    ((void)___constructor__F_R14s__anonymous1914s__anonymous19_autogen___1((&___ret__14s__anonymous19_1), (*___dst__R14s__anonymous19_1)));
     573    return ___ret__14s__anonymous19_1;
    554574}
    555575static inline void ___constructor__F_R14s__anonymous19i_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, signed int __i__i_1){
     
    564584static inline void ___destructor__F_R14s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1);
    565585static inline struct __anonymous20 ___operator_assign__F14s__anonymous20_R14s__anonymous2014s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, struct __anonymous20 ___src__14s__anonymous20_1);
     586static inline void ___constructor__F_R14s__anonymous20i_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, signed int __i__i_1);
    566587static inline void ___constructor__F_R14s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1){
    567588    ((void)((*___dst__R14s__anonymous20_1).__i__i_1) /* ?{} */);
     
    576597    struct __anonymous20 ___ret__14s__anonymous20_1;
    577598    ((void)((*___dst__R14s__anonymous20_1).__i__i_1=___src__14s__anonymous20_1.__i__i_1));
    578     ((void)___constructor__F_R14s__anonymous2014s__anonymous20_autogen___1((&___ret__14s__anonymous20_1), ___src__14s__anonymous20_1));
    579     return ((struct __anonymous20 )___ret__14s__anonymous20_1);
     599    ((void)___constructor__F_R14s__anonymous2014s__anonymous20_autogen___1((&___ret__14s__anonymous20_1), (*___dst__R14s__anonymous20_1)));
     600    return ___ret__14s__anonymous20_1;
    580601}
    581602static inline void ___constructor__F_R14s__anonymous20i_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, signed int __i__i_1){
     
    590611static inline void ___destructor__F_R14s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1);
    591612static inline struct __anonymous21 ___operator_assign__F14s__anonymous21_R14s__anonymous2114s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, struct __anonymous21 ___src__14s__anonymous21_1);
     613static inline void ___constructor__F_R14s__anonymous21i_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, signed int __i__i_1);
    592614static inline void ___constructor__F_R14s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1){
    593615    ((void)((*___dst__R14s__anonymous21_1).__i__i_1) /* ?{} */);
     
    602624    struct __anonymous21 ___ret__14s__anonymous21_1;
    603625    ((void)((*___dst__R14s__anonymous21_1).__i__i_1=___src__14s__anonymous21_1.__i__i_1));
    604     ((void)___constructor__F_R14s__anonymous2114s__anonymous21_autogen___1((&___ret__14s__anonymous21_1), ___src__14s__anonymous21_1));
    605     return ((struct __anonymous21 )___ret__14s__anonymous21_1);
     626    ((void)___constructor__F_R14s__anonymous2114s__anonymous21_autogen___1((&___ret__14s__anonymous21_1), (*___dst__R14s__anonymous21_1)));
     627    return ___ret__14s__anonymous21_1;
    606628}
    607629static inline void ___constructor__F_R14s__anonymous21i_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, signed int __i__i_1){
     
    616638static inline void ___destructor__F_R14s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1);
    617639static inline struct __anonymous22 ___operator_assign__F14s__anonymous22_R14s__anonymous2214s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, struct __anonymous22 ___src__14s__anonymous22_1);
     640static inline void ___constructor__F_R14s__anonymous22i_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, signed int __i__i_1);
    618641static inline void ___constructor__F_R14s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1){
    619642    ((void)((*___dst__R14s__anonymous22_1).__i__i_1) /* ?{} */);
     
    628651    struct __anonymous22 ___ret__14s__anonymous22_1;
    629652    ((void)((*___dst__R14s__anonymous22_1).__i__i_1=___src__14s__anonymous22_1.__i__i_1));
    630     ((void)___constructor__F_R14s__anonymous2214s__anonymous22_autogen___1((&___ret__14s__anonymous22_1), ___src__14s__anonymous22_1));
    631     return ((struct __anonymous22 )___ret__14s__anonymous22_1);
     653    ((void)___constructor__F_R14s__anonymous2214s__anonymous22_autogen___1((&___ret__14s__anonymous22_1), (*___dst__R14s__anonymous22_1)));
     654    return ___ret__14s__anonymous22_1;
    632655}
    633656static inline void ___constructor__F_R14s__anonymous22i_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, signed int __i__i_1){
     
    642665static inline void ___destructor__F_R14s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1);
    643666static inline struct __anonymous23 ___operator_assign__F14s__anonymous23_R14s__anonymous2314s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, struct __anonymous23 ___src__14s__anonymous23_1);
     667static inline void ___constructor__F_R14s__anonymous23i_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, signed int __i__i_1);
    644668static inline void ___constructor__F_R14s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1){
    645669    ((void)((*___dst__R14s__anonymous23_1).__i__i_1) /* ?{} */);
     
    654678    struct __anonymous23 ___ret__14s__anonymous23_1;
    655679    ((void)((*___dst__R14s__anonymous23_1).__i__i_1=___src__14s__anonymous23_1.__i__i_1));
    656     ((void)___constructor__F_R14s__anonymous2314s__anonymous23_autogen___1((&___ret__14s__anonymous23_1), ___src__14s__anonymous23_1));
    657     return ((struct __anonymous23 )___ret__14s__anonymous23_1);
     680    ((void)___constructor__F_R14s__anonymous2314s__anonymous23_autogen___1((&___ret__14s__anonymous23_1), (*___dst__R14s__anonymous23_1)));
     681    return ___ret__14s__anonymous23_1;
    658682}
    659683static inline void ___constructor__F_R14s__anonymous23i_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, signed int __i__i_1){
     
    672696    __attribute__ ((unused)) signed int ___retval_main__i_1;
    673697    ((void)(___retval_main__i_1=((signed int )0)) /* ?{} */);
    674     return ((signed int )___retval_main__i_1);
     698    return ___retval_main__i_1;
    675699    ((void)(___retval_main__i_1=0) /* ?{} */);
    676     return ((signed int )___retval_main__i_1);
     700    return ___retval_main__i_1;
    677701}
    678702static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi_iPPCc__1(argc, argv); }
     
    689713    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    690714    ((void)(_tmp_cp_ret0) /* ^?{} */);
    691     return ((signed int )___retval_main__i_1);
    692 }
     715    return ___retval_main__i_1;
     716}
  • src/tests/.expect/32/extension.txt

    rb96ec83 r6840e7c  
    1717static inline void ___destructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1);
    1818static inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___1(struct S *___dst__R2sS_1, struct S ___src__2sS_1);
     19static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1);
     20static inline void ___constructor__F_R2sSii_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1, signed int __b__i_1);
     21static inline void ___constructor__F_R2sSiii_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1, signed int __b__i_1, signed int __c__i_1);
    1922static inline void ___constructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1){
    2023    ((void)((*___dst__R2sS_1).__a__i_1) /* ?{} */);
     
    3740    ((void)((*___dst__R2sS_1).__b__i_1=___src__2sS_1.__b__i_1));
    3841    ((void)((*___dst__R2sS_1).__c__i_1=___src__2sS_1.__c__i_1));
    39     ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), ___src__2sS_1));
    40     return ((struct S )___ret__2sS_1);
     42    ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), (*___dst__R2sS_1)));
     43    return ___ret__2sS_1;
    4144}
    4245static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1){
     
    6063    __extension__ signed int __c__i_1;
    6164};
     65static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     66static inline void ___constructor__F_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     67static inline void ___destructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     68static inline union U ___operator_assign__F2uU_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     69static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1);
    6270static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1){
    6371}
     
    7078    union U ___ret__2uU_1;
    7179    ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&___src__2uU_1)), sizeof(union U )));
    72     ((void)___constructor__F_R2uU2uU_autogen___1((&___ret__2uU_1), ___src__2uU_1));
    73     return ((union U )___ret__2uU_1);
    74 }
    75 static inline void ___constructor__F_R2uUi_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1, signed int __src__i_1){
    76     ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__src__i_1)), sizeof(signed int )));
     80    ((void)___constructor__F_R2uU2uU_autogen___1((&___ret__2uU_1), (*___dst__R2uU_1)));
     81    return ___ret__2uU_1;
     82}
     83static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1){
     84    ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__a__i_1)), sizeof(signed int )));
    7785}
    7886__extension__ enum E {
     
    94102        __extension__ signed int *__z__Pi_2;
    95103    };
    96     signed int __i__i_2 = ((signed int )(__extension__ __a__i_1+__extension__ 3));
     104    inline void ___constructor__F_R2sS_autogen___2(struct S *___dst__R2sS_2){
     105        ((void)((*___dst__R2sS_2).__a__i_2) /* ?{} */);
     106        ((void)((*___dst__R2sS_2).__b__i_2) /* ?{} */);
     107        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     108        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     109        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     110        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     111    }
     112    inline void ___constructor__F_R2sS2sS_autogen___2(struct S *___dst__R2sS_2, struct S ___src__2sS_2){
     113        ((void)((*___dst__R2sS_2).__a__i_2=___src__2sS_2.__a__i_2) /* ?{} */);
     114        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2) /* ?{} */);
     115        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2) /* ?{} */);
     116        ((void)((*___dst__R2sS_2).__x__Pi_2=___src__2sS_2.__x__Pi_2) /* ?{} */);
     117        ((void)((*___dst__R2sS_2).__y__Pi_2=___src__2sS_2.__y__Pi_2) /* ?{} */);
     118        ((void)((*___dst__R2sS_2).__z__Pi_2=___src__2sS_2.__z__Pi_2) /* ?{} */);
     119    }
     120    inline void ___destructor__F_R2sS_autogen___2(struct S *___dst__R2sS_2){
     121        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ^?{} */);
     122        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ^?{} */);
     123        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ^?{} */);
     124        ((void)((*___dst__R2sS_2).__c__i_2) /* ^?{} */);
     125        ((void)((*___dst__R2sS_2).__b__i_2) /* ^?{} */);
     126        ((void)((*___dst__R2sS_2).__a__i_2) /* ^?{} */);
     127    }
     128    inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___2(struct S *___dst__R2sS_2, struct S ___src__2sS_2){
     129        struct S ___ret__2sS_2;
     130        ((void)((*___dst__R2sS_2).__a__i_2=___src__2sS_2.__a__i_2));
     131        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2));
     132        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2));
     133        ((void)((*___dst__R2sS_2).__x__Pi_2=___src__2sS_2.__x__Pi_2));
     134        ((void)((*___dst__R2sS_2).__y__Pi_2=___src__2sS_2.__y__Pi_2));
     135        ((void)((*___dst__R2sS_2).__z__Pi_2=___src__2sS_2.__z__Pi_2));
     136        ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), (*___dst__R2sS_2)));
     137        return ___ret__2sS_2;
     138    }
     139    inline void ___constructor__F_R2sSi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2){
     140        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     141        ((void)((*___dst__R2sS_2).__b__i_2) /* ?{} */);
     142        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     143        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     144        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     145        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     146    }
     147    inline void ___constructor__F_R2sSii_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2){
     148        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     149        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     150        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     151        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     152        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     153        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     154    }
     155    inline void ___constructor__F_R2sSiii_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2){
     156        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     157        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     158        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     159        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     160        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     161        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     162    }
     163    inline void ___constructor__F_R2sSiiiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2){
     164        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     165        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     166        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     167        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     168        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     169        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     170    }
     171    inline void ___constructor__F_R2sSiiiPiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2, signed int *__y__Pi_2){
     172        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     173        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     174        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     175        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     176        ((void)((*___dst__R2sS_2).__y__Pi_2=__y__Pi_2) /* ?{} */);
     177        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     178    }
     179    inline void ___constructor__F_R2sSiiiPiPiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2, signed int *__y__Pi_2, signed int *__z__Pi_2){
     180        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     181        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     182        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     183        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     184        ((void)((*___dst__R2sS_2).__y__Pi_2=__y__Pi_2) /* ?{} */);
     185        ((void)((*___dst__R2sS_2).__z__Pi_2=__z__Pi_2) /* ?{} */);
     186    }
     187    signed int __i__i_2 = (__extension__ __a__i_1+__extension__ 3);
    97188    ((void)__extension__ 3);
    98189    ((void)__extension__ __a__i_1);
  • src/tests/.expect/32/gccExtensions.txt

    rb96ec83 r6840e7c  
    6363        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2));
    6464        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2));
    65         ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), ___src__2sS_2));
    66         return ((struct S )___ret__2sS_2);
     65        ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), (*___dst__R2sS_2)));
     66        return ___ret__2sS_2;
    6767    }
    6868    inline void ___constructor__F_R2sSi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2){
     
    8181        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
    8282    }
    83     signed int __i__i_2 = ((signed int )__extension__ 3);
     83    signed int __i__i_2 = __extension__ 3;
    8484    __extension__ signed int __a__i_2;
    8585    __extension__ signed int __b__i_2;
     
    113113        struct s2 ___ret__3ss2_2;
    114114        ((void)((*___dst__R3ss2_2).__i__i_2=___src__3ss2_2.__i__i_2));
    115         ((void)___constructor__F_R3ss23ss2_autogen___2((&___ret__3ss2_2), ___src__3ss2_2));
    116         return ((struct s2 )___ret__3ss2_2);
     115        ((void)___constructor__F_R3ss23ss2_autogen___2((&___ret__3ss2_2), (*___dst__R3ss2_2)));
     116        return ___ret__3ss2_2;
    117117    }
    118118    inline void ___constructor__F_R3ss2i_autogen___2(struct s2 *___dst__R3ss2_2, signed int __i__i_2){
     
    134134        struct s3 ___ret__3ss3_2;
    135135        ((void)((*___dst__R3ss3_2).__i__i_2=___src__3ss3_2.__i__i_2));
    136         ((void)___constructor__F_R3ss33ss3_autogen___2((&___ret__3ss3_2), ___src__3ss3_2));
    137         return ((struct s3 )___ret__3ss3_2);
     136        ((void)___constructor__F_R3ss33ss3_autogen___2((&___ret__3ss3_2), (*___dst__R3ss3_2)));
     137        return ___ret__3ss3_2;
    138138    }
    139139    inline void ___constructor__F_R3ss3i_autogen___2(struct s3 *___dst__R3ss3_2, signed int __i__i_2){
     
    157157        struct s4 ___ret__3ss4_2;
    158158        ((void)((*___dst__R3ss4_2).__i__i_2=___src__3ss4_2.__i__i_2));
    159         ((void)___constructor__F_R3ss43ss4_autogen___2((&___ret__3ss4_2), ___src__3ss4_2));
    160         return ((struct s4 )___ret__3ss4_2);
     159        ((void)___constructor__F_R3ss43ss4_autogen___2((&___ret__3ss4_2), (*___dst__R3ss4_2)));
     160        return ___ret__3ss4_2;
    161161    }
    162162    inline void ___constructor__F_R3ss4i_autogen___2(struct s4 *___dst__R3ss4_2, signed int __i__i_2){
     
    169169    signed int __m3__A0A0i_2[((unsigned int )10)][((unsigned int )10)];
    170170    ((void)(___retval_main__i_1=((signed int )0)) /* ?{} */);
    171     return ((signed int )___retval_main__i_1);
     171    return ___retval_main__i_1;
    172172    ((void)(___retval_main__i_1=0) /* ?{} */);
    173     return ((signed int )___retval_main__i_1);
     173    return ___retval_main__i_1;
    174174}
    175175static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi_iPPCc__1(argc, argv); }
     
    186186    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    187187    ((void)(_tmp_cp_ret0) /* ^?{} */);
    188     return ((signed int )___retval_main__i_1);
     188    return ___retval_main__i_1;
    189189}
  • src/tests/.expect/32/literals.txt

    rb96ec83 r6840e7c  
    6464static inline void ___destructor__F_R16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1);
    6565static inline struct _Istream_cstrUC ___operator_assign__F16s_Istream_cstrUC_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, struct _Istream_cstrUC ___src__16s_Istream_cstrUC_1);
     66static inline void ___constructor__F_R16s_Istream_cstrUCPc_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, char *__s__Pc_1);
    6667static inline void ___constructor__F_R16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1){
    6768    ((void)((*___dst__R16s_Istream_cstrUC_1).__s__Pc_1) /* ?{} */);
     
    7677    struct _Istream_cstrUC ___ret__16s_Istream_cstrUC_1;
    7778    ((void)((*___dst__R16s_Istream_cstrUC_1).__s__Pc_1=___src__16s_Istream_cstrUC_1.__s__Pc_1));
    78     ((void)___constructor__F_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1((&___ret__16s_Istream_cstrUC_1), ___src__16s_Istream_cstrUC_1));
    79     return ((struct _Istream_cstrUC )___ret__16s_Istream_cstrUC_1);
     79    ((void)___constructor__F_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1((&___ret__16s_Istream_cstrUC_1), (*___dst__R16s_Istream_cstrUC_1)));
     80    return ___ret__16s_Istream_cstrUC_1;
    8081}
    8182static inline void ___constructor__F_R16s_Istream_cstrUCPc_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, char *__s__Pc_1){
     
    9293static inline void ___destructor__F_R15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1);
    9394static inline struct _Istream_cstrC ___operator_assign__F15s_Istream_cstrC_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, struct _Istream_cstrC ___src__15s_Istream_cstrC_1);
     95static inline void ___constructor__F_R15s_Istream_cstrCPc_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1);
     96static inline void ___constructor__F_R15s_Istream_cstrCPci_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1, signed int __size__i_1);
    9497static inline void ___constructor__F_R15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1){
    9598    ((void)((*___dst__R15s_Istream_cstrC_1).__s__Pc_1) /* ?{} */);
     
    108111    ((void)((*___dst__R15s_Istream_cstrC_1).__s__Pc_1=___src__15s_Istream_cstrC_1.__s__Pc_1));
    109112    ((void)((*___dst__R15s_Istream_cstrC_1).__size__i_1=___src__15s_Istream_cstrC_1.__size__i_1));
    110     ((void)___constructor__F_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1((&___ret__15s_Istream_cstrC_1), ___src__15s_Istream_cstrC_1));
    111     return ((struct _Istream_cstrC )___ret__15s_Istream_cstrC_1);
     113    ((void)___constructor__F_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1((&___ret__15s_Istream_cstrC_1), (*___dst__R15s_Istream_cstrC_1)));
     114    return ___ret__15s_Istream_cstrC_1;
    112115}
    113116static inline void ___constructor__F_R15s_Istream_cstrCPc_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1){
     
    122125void *___operator_bitor__A0_1_0_0___fail__PFi_Pd0___eof__PFi_Pd0___open__PF_Pd0PCcPCc___close__PF_Pd0___read__PFPd0_Pd0PcUl___ungetc__PFPd0_Pd0c___fmt__PFi_Pd0PCc__FPd0_Pd015s_Istream_cstrC__1(__attribute__ ((unused)) signed int (*__fail__PFi_P7tistype__1)(void *__anonymous_object1284), __attribute__ ((unused)) signed int (*__eof__PFi_P7tistype__1)(void *__anonymous_object1285), __attribute__ ((unused)) void (*__open__PF_P7tistypePCcPCc__1)(void *__is__P7tistype_1, const char *__name__PCc_1, const char *__mode__PCc_1), __attribute__ ((unused)) void (*__close__PF_P7tistype__1)(void *__is__P7tistype_1), __attribute__ ((unused)) void *(*__read__PFP7tistype_P7tistypePcUl__1)(void *__anonymous_object1286, char *__anonymous_object1287, unsigned long int __anonymous_object1288), __attribute__ ((unused)) void *(*__ungetc__PFP7tistype_P7tistypec__1)(void *__anonymous_object1289, char __anonymous_object1290), __attribute__ ((unused)) signed int (*__fmt__PFi_P7tistypePCc__1)(void *__anonymous_object1291, const char *__fmt__PCc_1, ...), void *__anonymous_object1292, struct _Istream_cstrC __anonymous_object1293);
    123126enum __anonymous0 {
    124     __sepSize__C13e__anonymous0_1 = ((signed int )16),
     127    __sepSize__C13e__anonymous0_1 = 16,
    125128};
    126129struct ofstream {
     
    137140static inline void ___destructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1);
    138141static inline struct ofstream ___operator_assign__F9sofstream_R9sofstream9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1, struct ofstream ___src__9sofstream_1);
     142static inline void ___constructor__F_R9sofstreamPv_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1);
     143static inline void ___constructor__F_R9sofstreamPvb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1);
     144static inline void ___constructor__F_R9sofstreamPvbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1);
     145static inline void ___constructor__F_R9sofstreamPvbbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1);
     146static inline void ___constructor__F_R9sofstreamPvbbbPCc_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1);
     147static inline void ___constructor__F_R9sofstreamPvbbbPCcA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)]);
     148static inline void ___constructor__F_R9sofstreamPvbbbPCcA0cA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)], char __tupleSeparator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)]);
    139149static inline void ___constructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1){
    140150    ((void)((*___dst__R9sofstream_1).__file__Pv_1) /* ?{} */);
     
    144154    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    145155    {
    146         signed int _index0 = ((signed int )0);
     156        signed int _index0 = 0;
    147157        for (;(_index0<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index0))) {
    148158            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index0])))) /* ?{} */);
     
    150160
    151161    }
    152     {
    153         signed int _index1 = ((signed int )0);
     162
     163    {
     164        signed int _index1 = 0;
    154165        for (;(_index1<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index1))) {
    155166            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index1])))) /* ?{} */);
     
    157168
    158169    }
     170
    159171}
    160172static inline void ___constructor__F_R9sofstream9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1, struct ofstream ___src__9sofstream_1){
     
    165177    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=___src__9sofstream_1.__sepCur__PCc_1) /* ?{} */);
    166178    {
    167         signed int _index2 = ((signed int )0);
     179        signed int _index2 = 0;
    168180        for (;(_index2<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index2))) {
    169181            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index2])))=___src__9sofstream_1.__separator__A0c_1[_index2]) /* ?{} */);
     
    171183
    172184    }
    173     {
    174         signed int _index3 = ((signed int )0);
     185
     186    {
     187        signed int _index3 = 0;
    175188        for (;(_index3<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index3))) {
    176189            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index3])))=___src__9sofstream_1.__tupleSeparator__A0c_1[_index3]) /* ?{} */);
     
    178191
    179192    }
     193
    180194}
    181195static inline void ___destructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1){
    182196    {
    183         signed int _index4 = ((signed int )(((signed int )__sepSize__C13e__anonymous0_1)-1));
     197        signed int _index4 = (((signed int )__sepSize__C13e__anonymous0_1)-1);
    184198        for (;(_index4>=0);((void)(--_index4))) {
    185199            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index4])))) /* ^?{} */);
     
    187201
    188202    }
    189     {
    190         signed int _index5 = ((signed int )(((signed int )__sepSize__C13e__anonymous0_1)-1));
     203
     204    {
     205        signed int _index5 = (((signed int )__sepSize__C13e__anonymous0_1)-1);
    191206        for (;(_index5>=0);((void)(--_index5))) {
    192207            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index5])))) /* ^?{} */);
     
    194209
    195210    }
     211
    196212    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ^?{} */);
    197213    ((void)((*___dst__R9sofstream_1).__sawNL__b_1) /* ^?{} */);
     
    208224    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=___src__9sofstream_1.__sepCur__PCc_1));
    209225    {
    210         signed int _index6 = ((signed int )0);
     226        signed int _index6 = 0;
    211227        for (;(_index6<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index6))) {
    212228            ((void)((*___dst__R9sofstream_1).__separator__A0c_1[_index6]=___src__9sofstream_1.__separator__A0c_1[_index6]));
     
    216232
    217233    {
    218         signed int _index7 = ((signed int )0);
     234        signed int _index7 = 0;
    219235        for (;(_index7<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index7))) {
    220236            ((void)((*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index7]=___src__9sofstream_1.__tupleSeparator__A0c_1[_index7]));
     
    223239    }
    224240
    225     ((void)___constructor__F_R9sofstream9sofstream_autogen___1((&___ret__9sofstream_1), ___src__9sofstream_1));
    226     return ((struct ofstream )___ret__9sofstream_1);
     241    ((void)___constructor__F_R9sofstream9sofstream_autogen___1((&___ret__9sofstream_1), (*___dst__R9sofstream_1)));
     242    return ___ret__9sofstream_1;
    227243}
    228244static inline void ___constructor__F_R9sofstreamPv_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1){
     
    233249    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    234250    {
    235         signed int _index8 = ((signed int )0);
     251        signed int _index8 = 0;
    236252        for (;(_index8<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index8))) {
    237253            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index8])))) /* ?{} */);
     
    239255
    240256    }
    241     {
    242         signed int _index9 = ((signed int )0);
     257
     258    {
     259        signed int _index9 = 0;
    243260        for (;(_index9<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index9))) {
    244261            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index9])))) /* ?{} */);
     
    246263
    247264    }
     265
    248266}
    249267static inline void ___constructor__F_R9sofstreamPvb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1){
     
    254272    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    255273    {
    256         signed int _index10 = ((signed int )0);
     274        signed int _index10 = 0;
    257275        for (;(_index10<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index10))) {
    258276            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index10])))) /* ?{} */);
     
    260278
    261279    }
    262     {
    263         signed int _index11 = ((signed int )0);
     280
     281    {
     282        signed int _index11 = 0;
    264283        for (;(_index11<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index11))) {
    265284            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index11])))) /* ?{} */);
     
    267286
    268287    }
     288
    269289}
    270290static inline void ___constructor__F_R9sofstreamPvbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1){
     
    275295    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    276296    {
    277         signed int _index12 = ((signed int )0);
     297        signed int _index12 = 0;
    278298        for (;(_index12<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index12))) {
    279299            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index12])))) /* ?{} */);
     
    281301
    282302    }
    283     {
    284         signed int _index13 = ((signed int )0);
     303
     304    {
     305        signed int _index13 = 0;
    285306        for (;(_index13<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index13))) {
    286307            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index13])))) /* ?{} */);
     
    288309
    289310    }
     311
    290312}
    291313static inline void ___constructor__F_R9sofstreamPvbbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1){
     
    296318    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    297319    {
    298         signed int _index14 = ((signed int )0);
     320        signed int _index14 = 0;
    299321        for (;(_index14<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index14))) {
    300322            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index14])))) /* ?{} */);
     
    302324
    303325    }
    304     {
    305         signed int _index15 = ((signed int )0);
     326
     327    {
     328        signed int _index15 = 0;
    306329        for (;(_index15<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index15))) {
    307330            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index15])))) /* ?{} */);
     
    309332
    310333    }
     334
    311335}
    312336static inline void ___constructor__F_R9sofstreamPvbbbPCc_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1){
     
    317341    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    318342    {
    319         signed int _index16 = ((signed int )0);
     343        signed int _index16 = 0;
    320344        for (;(_index16<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index16))) {
    321345            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index16])))) /* ?{} */);
     
    323347
    324348    }
    325     {
    326         signed int _index17 = ((signed int )0);
     349
     350    {
     351        signed int _index17 = 0;
    327352        for (;(_index17<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index17))) {
    328353            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index17])))) /* ?{} */);
     
    330355
    331356    }
     357
    332358}
    333359static inline void ___constructor__F_R9sofstreamPvbbbPCcA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)]){
     
    338364    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    339365    {
    340         signed int _index18 = ((signed int )0);
     366        signed int _index18 = 0;
    341367        for (;(_index18<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index18))) {
    342368            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index18])))=__separator__A0c_1[_index18]) /* ?{} */);
     
    344370
    345371    }
    346     {
    347         signed int _index19 = ((signed int )0);
     372
     373    {
     374        signed int _index19 = 0;
    348375        for (;(_index19<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index19))) {
    349376            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index19])))) /* ?{} */);
     
    351378
    352379    }
     380
    353381}
    354382static inline void ___constructor__F_R9sofstreamPvbbbPCcA0cA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)], char __tupleSeparator__A0c_1[((unsigned int )__sepSize__C13e__anonymous0_1)]){
     
    359387    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    360388    {
    361         signed int _index20 = ((signed int )0);
     389        signed int _index20 = 0;
    362390        for (;(_index20<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index20))) {
    363391            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[_index20])))=__separator__A0c_1[_index20]) /* ?{} */);
     
    365393
    366394    }
    367     {
    368         signed int _index21 = ((signed int )0);
     395
     396    {
     397        signed int _index21 = 0;
    369398        for (;(_index21<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index21))) {
    370399            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[_index21])))=__tupleSeparator__A0c_1[_index21]) /* ?{} */);
     
    372401
    373402    }
     403
    374404}
    375405_Bool __sepPrt__Fb_P9sofstream__1(struct ofstream *__anonymous_object1294);
     
    404434static inline void ___destructor__F_R9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1);
    405435static inline struct ifstream ___operator_assign__F9sifstream_R9sifstream9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1, struct ifstream ___src__9sifstream_1);
     436static inline void ___constructor__F_R9sifstreamPv_autogen___1(struct ifstream *___dst__R9sifstream_1, void *__file__Pv_1);
    406437static inline void ___constructor__F_R9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1){
    407438    ((void)((*___dst__R9sifstream_1).__file__Pv_1) /* ?{} */);
     
    416447    struct ifstream ___ret__9sifstream_1;
    417448    ((void)((*___dst__R9sifstream_1).__file__Pv_1=___src__9sifstream_1.__file__Pv_1));
    418     ((void)___constructor__F_R9sifstream9sifstream_autogen___1((&___ret__9sifstream_1), ___src__9sifstream_1));
    419     return ((struct ifstream )___ret__9sifstream_1);
     449    ((void)___constructor__F_R9sifstream9sifstream_autogen___1((&___ret__9sifstream_1), (*___dst__R9sifstream_1)));
     450    return ___ret__9sifstream_1;
    420451}
    421452static inline void ___constructor__F_R9sifstreamPv_autogen___1(struct ifstream *___dst__R9sifstream_1, void *__file__Pv_1){
     
    708739    ((void)0123456789.e-09L);
    709740    ((void)0123456789.e-09DL);
    710     ((void)(-0123456789.e-09));
    711     ((void)(-0123456789.e-09f));
    712     ((void)(-0123456789.e-09l));
    713     ((void)(-0123456789.e-09F));
    714     ((void)(-0123456789.e-09L));
    715     ((void)(-0123456789.e-09DL));
     741    ((void)(+0123456789.e-09));
     742    ((void)(+0123456789.e-09f));
     743    ((void)(+0123456789.e-09l));
     744    ((void)(+0123456789.e-09F));
     745    ((void)(+0123456789.e-09L));
     746    ((void)(+0123456789.e-09DL));
    716747    ((void)(-0123456789.e-09));
    717748    ((void)(-0123456789.e-09f));
     
    852883    ((void)0123456789.0123456789E-09L);
    853884    ((void)0123456789.0123456789E-09DL);
    854     ((void)(-0123456789.0123456789E-09));
    855     ((void)(-0123456789.0123456789E-09f));
    856     ((void)(-0123456789.0123456789E-09l));
    857     ((void)(-0123456789.0123456789E-09F));
    858     ((void)(-0123456789.0123456789E-09L));
    859     ((void)(-0123456789.0123456789E-09DL));
     885    ((void)(+0123456789.0123456789E-09));
     886    ((void)(+0123456789.0123456789E-09f));
     887    ((void)(+0123456789.0123456789E-09l));
     888    ((void)(+0123456789.0123456789E-09F));
     889    ((void)(+0123456789.0123456789E-09L));
     890    ((void)(+0123456789.0123456789E-09DL));
    860891    ((void)(-0123456789.0123456789E-09));
    861892    ((void)(-0123456789.0123456789E-09f));
     
    899930    ((void)0x0123456789.p-09F);
    900931    ((void)0x0123456789.p-09L);
    901     ((void)(-0x0123456789.p-09));
    902     ((void)(-0x0123456789.p-09f));
    903     ((void)(-0x0123456789.p-09l));
    904     ((void)(-0x0123456789.p-09F));
    905     ((void)(-0x0123456789.p-09L));
     932    ((void)(+0x0123456789.p-09));
     933    ((void)(+0x0123456789.p-09f));
     934    ((void)(+0x0123456789.p-09l));
     935    ((void)(+0x0123456789.p-09F));
     936    ((void)(+0x0123456789.p-09L));
    906937    ((void)(-0x0123456789.p-09));
    907938    ((void)(-0x0123456789.p-09f));
     
    944975    ((void)0x.0123456789P-09F);
    945976    ((void)0x.0123456789P-09L);
    946     ((void)(-0x.0123456789P-09));
    947     ((void)(-0x.0123456789P-09f));
    948     ((void)(-0x.0123456789P-09l));
    949     ((void)(-0x.0123456789P-09F));
    950     ((void)(-0x.0123456789P-09L));
     977    ((void)(+0x.0123456789P-09));
     978    ((void)(+0x.0123456789P-09f));
     979    ((void)(+0x.0123456789P-09l));
     980    ((void)(+0x.0123456789P-09F));
     981    ((void)(+0x.0123456789P-09L));
    951982    ((void)(-0x.0123456789P-09));
    952983    ((void)(-0x.0123456789P-09f));
     
    9891020    ((void)0X0123456789.0123456789P-09F);
    9901021    ((void)0X0123456789.0123456789P-09L);
     1022    ((void)(+0X0123456789.0123456789P-09));
     1023    ((void)(+0X0123456789.0123456789P-09f));
     1024    ((void)(+0X0123456789.0123456789P-09l));
     1025    ((void)(+0X0123456789.0123456789P-09F));
     1026    ((void)(+0X0123456789.0123456789P-09L));
    9911027    ((void)(-0X0123456789.0123456789P-09));
    9921028    ((void)(-0X0123456789.0123456789P-09f));
     
    9941030    ((void)(-0X0123456789.0123456789P-09F));
    9951031    ((void)(-0X0123456789.0123456789P-09L));
    996     ((void)(-0X0123456789.0123456789P-09));
    997     ((void)(-0X0123456789.0123456789P-09f));
    998     ((void)(-0X0123456789.0123456789P-09l));
    999     ((void)(-0X0123456789.0123456789P-09F));
    1000     ((void)(-0X0123456789.0123456789P-09L));
     1032    ((void)((signed char )01234567));
     1033    ((void)((signed short int )01234567));
     1034    ((void)((signed int )01234567));
     1035    ((void)((signed long long int )01234567));
     1036    ((void)((__int128 )01234567));
     1037    ((void)((unsigned char )01234567u));
     1038    ((void)((signed short int )01234567u));
     1039    ((void)((unsigned int )01234567u));
     1040    ((void)((signed long long int )01234567u));
     1041    ((void)((__int128 )01234567u));
     1042    ((void)(+((signed int )((signed char )01234567))));
     1043    ((void)(+((signed int )((signed short int )01234567))));
     1044    ((void)(+((signed int )01234567)));
     1045    ((void)(+((signed long long int )01234567)));
     1046    ((void)(+((float )((__int128 )01234567))));
     1047    ((void)(+((signed int )((unsigned char )01234567u))));
     1048    ((void)(+((signed int )((signed short int )01234567u))));
     1049    ((void)(+((unsigned int )01234567u)));
     1050    ((void)(+((signed long long int )01234567u)));
     1051    ((void)(+((float )((__int128 )01234567u))));
     1052    ((void)(-((signed int )((signed char )01234567))));
     1053    ((void)(-((signed int )((signed short int )01234567))));
     1054    ((void)(-((signed int )01234567)));
     1055    ((void)(-((signed long long int )01234567)));
     1056    ((void)(-((float )((__int128 )01234567))));
     1057    ((void)(-((signed int )((unsigned char )01234567u))));
     1058    ((void)(-((signed int )((signed short int )01234567u))));
     1059    ((void)(-((unsigned int )01234567u)));
     1060    ((void)(-((signed long long int )01234567u)));
     1061    ((void)(-((float )((__int128 )01234567u))));
     1062    ((void)((signed char )1234567890));
     1063    ((void)((signed short int )1234567890));
     1064    ((void)((signed int )1234567890));
     1065    ((void)((signed long long int )1234567890));
     1066    ((void)((__int128 )1234567890));
     1067    ((void)((signed char )1234567890U));
     1068    ((void)((unsigned short int )1234567890U));
     1069    ((void)((signed int )1234567890U));
     1070    ((void)((unsigned long long int )1234567890u));
     1071    ((void)((unsigned __int128 )1234567890u));
     1072    ((void)(+((signed int )((signed char )1234567890))));
     1073    ((void)(+((signed int )((signed short int )1234567890))));
     1074    ((void)(+((signed int )1234567890)));
     1075    ((void)(+((signed long long int )1234567890)));
     1076    ((void)(+((float )((__int128 )1234567890))));
     1077    ((void)(+((signed int )((signed char )1234567890U))));
     1078    ((void)(+((signed int )((unsigned short int )1234567890U))));
     1079    ((void)(+((signed int )1234567890U)));
     1080    ((void)(+((unsigned long long int )1234567890u)));
     1081    ((void)(+((float )((unsigned __int128 )1234567890u))));
     1082    ((void)(-((signed int )((signed char )1234567890))));
     1083    ((void)(-((signed int )((signed short int )1234567890))));
     1084    ((void)(-((signed int )1234567890)));
     1085    ((void)(-((signed long long int )1234567890)));
     1086    ((void)(-((float )((__int128 )1234567890))));
     1087    ((void)(-((signed int )((signed char )1234567890U))));
     1088    ((void)(-((signed int )((unsigned short int )1234567890U))));
     1089    ((void)(-((signed int )1234567890U)));
     1090    ((void)(-((unsigned long long int )1234567890u)));
     1091    ((void)(-((float )((unsigned __int128 )1234567890u))));
     1092    ((void)((signed char )0x0123456789abcdef));
     1093    ((void)((signed short int )0x0123456789abcdef));
     1094    ((void)((signed int )0x0123456789abcdef));
     1095    ((void)((signed long long int )0x0123456789abcdef));
     1096    ((void)((signed char )0x0123456789abcdefu));
     1097    ((void)((unsigned short int )0x0123456789abcdefu));
     1098    ((void)((signed int )0x0123456789abcdefu));
     1099    ((void)((unsigned long long int )0x0123456789abcdefu));
     1100    ((void)(+((signed int )((signed char )0x0123456789abcdef))));
     1101    ((void)(+((signed int )((signed short int )0x0123456789abcdef))));
     1102    ((void)(+((signed int )0x0123456789abcdef)));
     1103    ((void)(+((signed long long int )0x0123456789abcdef)));
     1104    ((void)(+((signed int )((signed char )0x0123456789abcdefu))));
     1105    ((void)(+((signed int )((unsigned short int )0x0123456789abcdefu))));
     1106    ((void)(+((signed int )0x0123456789abcdefu)));
     1107    ((void)(+((unsigned long long int )0x0123456789abcdefu)));
     1108    ((void)(-((signed int )((signed char )0x0123456789abcdef))));
     1109    ((void)(-((signed int )((signed short int )0x0123456789abcdef))));
     1110    ((void)(-((signed int )0x0123456789abcdef)));
     1111    ((void)(-((signed long long int )0x0123456789abcdef)));
     1112    ((void)(-((signed int )((signed char )0x0123456789abcdefu))));
     1113    ((void)(-((signed int )((unsigned short int )0x0123456789abcdefu))));
     1114    ((void)(-((signed int )0x0123456789abcdefu)));
     1115    ((void)(-((unsigned long long int )0x0123456789abcdefu)));
     1116    ((void)((signed char )0x0123456789ABCDEF));
     1117    ((void)((signed short int )0x0123456789ABCDEF));
     1118    ((void)((signed int )0x0123456789ABCDEF));
     1119    ((void)((signed long long int )0x0123456789ABCDEF));
     1120    ((void)((signed char )0x0123456789ABCDEFu));
     1121    ((void)((unsigned short int )0x0123456789ABCDEFu));
     1122    ((void)((signed int )0x0123456789ABCDEFu));
     1123    ((void)((unsigned long long int )0x0123456789ABCDEFu));
     1124    ((void)(+((signed int )((signed char )0x0123456789ABCDEF))));
     1125    ((void)(+((signed int )((signed short int )0x0123456789ABCDEF))));
     1126    ((void)(+((signed int )0x0123456789ABCDEF)));
     1127    ((void)(+((signed long long int )0x0123456789ABCDEF)));
     1128    ((void)(+((signed int )((signed char )0x0123456789ABCDEFu))));
     1129    ((void)(+((signed int )((unsigned short int )0x0123456789ABCDEFu))));
     1130    ((void)(+((signed int )0x0123456789ABCDEFu)));
     1131    ((void)(+((unsigned long long int )0x0123456789ABCDEFu)));
     1132    ((void)(-((signed int )((signed char )0x0123456789ABCDEF))));
     1133    ((void)(-((signed int )((signed short int )0x0123456789ABCDEF))));
     1134    ((void)(-((signed int )0x0123456789ABCDEF)));
     1135    ((void)(-((signed long long int )0x0123456789ABCDEF)));
     1136    ((void)(-((signed int )((signed char )0x0123456789ABCDEFu))));
     1137    ((void)(-((signed int )((unsigned short int )0x0123456789ABCDEFu))));
     1138    ((void)(-((signed int )0x0123456789ABCDEFu)));
     1139    ((void)(-((unsigned long long int )0x0123456789ABCDEFu)));
     1140    ((void)((signed char )0X0123456789abcdef));
     1141    ((void)((signed short int )0X0123456789abcdef));
     1142    ((void)((signed int )0X0123456789abcdef));
     1143    ((void)((signed long long int )0X0123456789abcdef));
     1144    ((void)((signed char )0X0123456789abcdefu));
     1145    ((void)((unsigned short int )0X0123456789abcdefu));
     1146    ((void)((signed int )0X0123456789abcdefu));
     1147    ((void)((unsigned long long int )0X0123456789abcdefu));
     1148    ((void)(+((signed int )((signed char )0X0123456789abcdef))));
     1149    ((void)(+((signed int )((signed short int )0X0123456789abcdef))));
     1150    ((void)(+((signed int )0X0123456789abcdef)));
     1151    ((void)(+((signed long long int )0X0123456789abcdef)));
     1152    ((void)(+((signed int )((signed char )0X0123456789abcdefu))));
     1153    ((void)(+((signed int )((unsigned short int )0X0123456789abcdefu))));
     1154    ((void)(+((signed int )0X0123456789abcdefu)));
     1155    ((void)(+((unsigned long long int )0X0123456789abcdefu)));
     1156    ((void)(-((signed int )((signed char )0X0123456789abcdef))));
     1157    ((void)(-((signed int )((signed short int )0X0123456789abcdef))));
     1158    ((void)(-((signed int )0X0123456789abcdef)));
     1159    ((void)(-((signed long long int )0X0123456789abcdef)));
     1160    ((void)(-((signed int )((signed char )0X0123456789abcdefu))));
     1161    ((void)(-((signed int )((unsigned short int )0X0123456789abcdefu))));
     1162    ((void)(-((signed int )0X0123456789abcdefu)));
     1163    ((void)(-((unsigned long long int )0X0123456789abcdefu)));
     1164    ((void)((signed char )0X0123456789ABCDEF));
     1165    ((void)((signed short int )0X0123456789ABCDEF));
     1166    ((void)((signed int )0X0123456789ABCDEF));
     1167    ((void)((signed long long int )0X0123456789ABCDEF));
     1168    ((void)((signed char )0X0123456789ABCDEFu));
     1169    ((void)((unsigned short int )0X0123456789ABCDEFu));
     1170    ((void)((signed int )0X0123456789ABCDEFu));
     1171    ((void)((unsigned long long int )0X0123456789ABCDEFu));
     1172    ((void)(+((signed int )((signed char )0X0123456789ABCDEF))));
     1173    ((void)(+((signed int )((signed short int )0X0123456789ABCDEF))));
     1174    ((void)(+((signed int )0X0123456789ABCDEF)));
     1175    ((void)(+((signed long long int )0X0123456789ABCDEF)));
     1176    ((void)(+((signed int )((signed char )0X0123456789ABCDEFu))));
     1177    ((void)(+((signed int )((unsigned short int )0X0123456789ABCDEFu))));
     1178    ((void)(+((signed int )0X0123456789ABCDEFu)));
     1179    ((void)(+((unsigned long long int )0X0123456789ABCDEFu)));
     1180    ((void)(-((signed int )((signed char )0X0123456789ABCDEF))));
     1181    ((void)(-((signed int )((signed short int )0X0123456789ABCDEF))));
     1182    ((void)(-((signed int )0X0123456789ABCDEF)));
     1183    ((void)(-((signed long long int )0X0123456789ABCDEF)));
     1184    ((void)(-((signed int )((signed char )0X0123456789ABCDEFu))));
     1185    ((void)(-((signed int )((unsigned short int )0X0123456789ABCDEFu))));
     1186    ((void)(-((signed int )0X0123456789ABCDEFu)));
     1187    ((void)(-((unsigned long long int )0X0123456789ABCDEFu)));
     1188    ((void)((float )0123456789.));
     1189    ((void)((double )0123456789.));
     1190    ((void)((long double )0123456789.));
     1191    ((void)((long double )0123456789.));
     1192    ((void)(+((float )0123456789.)));
     1193    ((void)(+((double )0123456789.)));
     1194    ((void)(+((long double )0123456789.)));
     1195    ((void)(+((long double )0123456789.)));
     1196    ((void)(-((float )0123456789.)));
     1197    ((void)(-((double )0123456789.)));
     1198    ((void)(-((long double )0123456789.)));
     1199    ((void)(-((long double )0123456789.)));
     1200    ((void)((float )0123456789.e09));
     1201    ((void)((double )0123456789.e09));
     1202    ((void)((long double )0123456789.e09));
     1203    ((void)((long double )0123456789.e09));
     1204    ((void)(+((float )0123456789.e+09)));
     1205    ((void)(+((double )0123456789.e+09)));
     1206    ((void)(+((long double )0123456789.e+09)));
     1207    ((void)(+((long double )0123456789.e+09)));
     1208    ((void)(-((float )0123456789.e-09)));
     1209    ((void)(-((double )0123456789.e-09)));
     1210    ((void)(-((long double )0123456789.e-09)));
     1211    ((void)(-((long double )0123456789.e-09)));
     1212    ((void)((float ).0123456789e09));
     1213    ((void)((double ).0123456789e09));
     1214    ((void)((long double ).0123456789e09));
     1215    ((void)((long double ).0123456789e09));
     1216    ((void)(+((float ).0123456789E+09)));
     1217    ((void)(+((double ).0123456789E+09)));
     1218    ((void)(+((long double ).0123456789E+09)));
     1219    ((void)(+((long double ).0123456789E+09)));
     1220    ((void)(-((float ).0123456789E-09)));
     1221    ((void)(-((double ).0123456789E-09)));
     1222    ((void)(-((long double ).0123456789E-09)));
     1223    ((void)(-((long double ).0123456789E-09)));
     1224    ((void)((float )0123456789.0123456789));
     1225    ((void)((double )0123456789.0123456789));
     1226    ((void)((long double )0123456789.0123456789));
     1227    ((void)((long double )0123456789.0123456789));
     1228    ((void)(+((float )0123456789.0123456789E09)));
     1229    ((void)(+((double )0123456789.0123456789E09)));
     1230    ((void)(+((long double )0123456789.0123456789E09)));
     1231    ((void)(+((long double )0123456789.0123456789E09)));
     1232    ((void)(-((float )0123456789.0123456789E+09)));
     1233    ((void)(-((double )0123456789.0123456789E+09)));
     1234    ((void)(-((long double )0123456789.0123456789E+09)));
     1235    ((void)(-((long double )0123456789.0123456789E+09)));
     1236    ((void)((float )0123456789.0123456789E-09));
     1237    ((void)((double )0123456789.0123456789E-09));
     1238    ((void)((long double )0123456789.0123456789E-09));
     1239    ((void)((long double )0123456789.0123456789E-09));
     1240    ((void)((float )0x0123456789.p09));
     1241    ((void)((double )0x0123456789.p09));
     1242    ((void)((long double )0x0123456789.p09));
     1243    ((void)((long double )0x0123456789.p09));
     1244    ((void)(+((float )0x0123456789.p09)));
     1245    ((void)(+((double )0x0123456789.p09)));
     1246    ((void)(+((long double )0x0123456789.p09)));
     1247    ((void)(+((long double )0x0123456789.p09)));
     1248    ((void)(-((float )0x0123456789.p09)));
     1249    ((void)(-((double )0x0123456789.p09)));
     1250    ((void)(-((long double )0x0123456789.p09)));
     1251    ((void)(-((long double )0x0123456789.p09)));
     1252    ((void)((float )0x0123456789.p+09));
     1253    ((void)((double )0x0123456789.p+09));
     1254    ((void)((long double )0x0123456789.p+09));
     1255    ((void)((long double )0x0123456789.p+09));
     1256    ((void)(+((float )0x0123456789.p-09)));
     1257    ((void)(+((double )0x0123456789.p-09)));
     1258    ((void)(+((long double )0x0123456789.p-09)));
     1259    ((void)(+((long double )0x0123456789.p-09)));
     1260    ((void)(-((float )0x.0123456789p09)));
     1261    ((void)(-((double )0x.0123456789p09)));
     1262    ((void)(-((long double )0x.0123456789p09)));
     1263    ((void)(-((long double )0x.0123456789p09)));
    10011264    ((void)__f__F_c__1('a'));
    10021265    ((void)__f__F_Sc__1(20));
     
    11111374    ((void)L"a" "b" "c");
    11121375    ((void)(___retval_main__i_1=0) /* ?{} */);
    1113     return ((signed int )___retval_main__i_1);
     1376    return ___retval_main__i_1;
    11141377}
    11151378static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi___1(); }
     
    11261389    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    11271390    ((void)(_tmp_cp_ret0) /* ^?{} */);
    1128     return ((signed int )___retval_main__i_1);
    1129 }
     1391    return ___retval_main__i_1;
     1392}
  • src/tests/.expect/64/KRfunctions.txt

    rb96ec83 r6840e7c  
    2121static inline void ___destructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1);
    2222static inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___1(struct S *___dst__R2sS_1, struct S ___src__2sS_1);
     23static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __i__i_1);
    2324static inline void ___constructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1){
    2425    ((void)((*___dst__R2sS_1).__i__i_1) /* ?{} */);
     
    3334    struct S ___ret__2sS_1;
    3435    ((void)((*___dst__R2sS_1).__i__i_1=___src__2sS_1.__i__i_1));
    35     ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), ___src__2sS_1));
    36     return ((struct S )___ret__2sS_1);
     36    ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), (*___dst__R2sS_1)));
     37    return ___ret__2sS_1;
    3738}
    3839static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __i__i_1){
     
    6566    signed int *__x__FPi_ii__2(signed int __anonymous_object2, signed int __anonymous_object3);
    6667    ((void)(___retval_f10__PFPi_ii__1=__x__FPi_ii__2) /* ?{} */);
    67     return ((signed int *(*)(signed int __x__i_1, signed int __y__i_1))___retval_f10__PFPi_ii__1);
     68    return ___retval_f10__PFPi_ii__1;
    6869}
    6970signed int (*__f11__FPA0i_iPiPi__1(signed int __a__i_1, signed int *__b__Pi_1, signed int *__c__Pi_1))[]{
  • src/tests/.expect/64/attributes.txt

    rb96ec83 r6840e7c  
    2323static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_R13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1){
    2424    struct __anonymous0 ___ret__13s__anonymous0_1;
    25     ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), ___src__13s__anonymous0_1));
    26     return ((struct __anonymous0 )___ret__13s__anonymous0_1);
     25    ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), (*___dst__R13s__anonymous0_1)));
     26    return ___ret__13s__anonymous0_1;
    2727}
    2828__attribute__ ((unused)) struct Agn1;
     
    4141static inline struct Agn2 ___operator_assign__F5sAgn2_R5sAgn25sAgn2_autogen___1(struct Agn2 *___dst__R5sAgn2_1, struct Agn2 ___src__5sAgn2_1){
    4242    struct Agn2 ___ret__5sAgn2_1;
    43     ((void)___constructor__F_R5sAgn25sAgn2_autogen___1((&___ret__5sAgn2_1), ___src__5sAgn2_1));
    44     return ((struct Agn2 )___ret__5sAgn2_1);
     43    ((void)___constructor__F_R5sAgn25sAgn2_autogen___1((&___ret__5sAgn2_1), (*___dst__R5sAgn2_1)));
     44    return ___ret__5sAgn2_1;
    4545}
    4646enum __attribute__ ((unused)) __anonymous1 {
     
    6969static inline void ___destructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1);
    7070static inline struct Fdl ___operator_assign__F4sFdl_R4sFdl4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1, struct Fdl ___src__4sFdl_1);
     71static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1);
     72static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1);
     73static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1);
     74static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1);
     75static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1);
     76static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1);
     77static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1);
     78static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1);
     79static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object1);
     80static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object2, signed int *__f9__Pi_1);
    7181static inline void ___constructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1){
    7282    ((void)((*___dst__R4sFdl_1).__f1__i_1) /* ?{} */);
     
    7888    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    7989    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     90    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    8091    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    8192}
     
    89100    ((void)((*___dst__R4sFdl_1).__f7__i_1=___src__4sFdl_1.__f7__i_1) /* ?{} */);
    90101    ((void)((*___dst__R4sFdl_1).__f8__i_1=___src__4sFdl_1.__f8__i_1) /* ?{} */);
     102    ((void)((*___dst__R4sFdl_1).__anonymous_object0=___src__4sFdl_1.__anonymous_object0) /* ?{} */);
    91103    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=___src__4sFdl_1.__f9__Pi_1) /* ?{} */);
    92104}
    93105static inline void ___destructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1){
    94106    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ^?{} */);
     107    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ^?{} */);
    95108    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ^?{} */);
    96109    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ^?{} */);
     
    112125    ((void)((*___dst__R4sFdl_1).__f7__i_1=___src__4sFdl_1.__f7__i_1));
    113126    ((void)((*___dst__R4sFdl_1).__f8__i_1=___src__4sFdl_1.__f8__i_1));
     127    ((void)((*___dst__R4sFdl_1).__anonymous_object0=___src__4sFdl_1.__anonymous_object0));
    114128    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=___src__4sFdl_1.__f9__Pi_1));
    115     ((void)___constructor__F_R4sFdl4sFdl_autogen___1((&___ret__4sFdl_1), ___src__4sFdl_1));
    116     return ((struct Fdl )___ret__4sFdl_1);
     129    ((void)___constructor__F_R4sFdl4sFdl_autogen___1((&___ret__4sFdl_1), (*___dst__R4sFdl_1)));
     130    return ___ret__4sFdl_1;
    117131}
    118132static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1){
     
    125139    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    126140    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     141    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    127142    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    128143}
     
    136151    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    137152    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     153    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    138154    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    139155}
     
    147163    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    148164    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     165    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    149166    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    150167}
     
    158175    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    159176    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     177    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    160178    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    161179}
     
    169187    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    170188    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     189    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    171190    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    172191}
     
    180199    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    181200    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     201    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    182202    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    183203}
     
    191211    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    192212    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     213    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    193214    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    194215}
     
    202223    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    203224    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
    204     ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    205 }
    206 static inline void ___constructor__F_R4sFdliiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int *__f9__Pi_1){
     225    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
     226    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
     227}
     228static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object3){
    207229    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    208230    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    213235    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
    214236    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
     237    ((void)((*___dst__R4sFdl_1).__anonymous_object0=__anonymous_object3) /* ?{} */);
     238    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
     239}
     240static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object4, signed int *__f9__Pi_1){
     241    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
     242    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     243    ((void)((*___dst__R4sFdl_1).__f3__i_1=__f3__i_1) /* ?{} */);
     244    ((void)((*___dst__R4sFdl_1).__f4__i_1=__f4__i_1) /* ?{} */);
     245    ((void)((*___dst__R4sFdl_1).__f5__i_1=__f5__i_1) /* ?{} */);
     246    ((void)((*___dst__R4sFdl_1).__f6__i_1=__f6__i_1) /* ?{} */);
     247    ((void)((*___dst__R4sFdl_1).__f7__i_1=__f7__i_1) /* ?{} */);
     248    ((void)((*___dst__R4sFdl_1).__f8__i_1=__f8__i_1) /* ?{} */);
     249    ((void)((*___dst__R4sFdl_1).__anonymous_object0=__anonymous_object4) /* ?{} */);
    215250    ((void)((*___dst__R4sFdl_1).__f9__Pi_1=__f9__Pi_1) /* ?{} */);
    216251}
     
    232267    __attribute__ ((unused)) signed int **const ___retval_f2__CPPi_1;
    233268}
    234 __attribute__ ((unused,used,unused)) signed int (*__f3__FPA0i_i__1(signed int __anonymous_object1))[];
     269__attribute__ ((unused,used,unused)) signed int (*__f3__FPA0i_i__1(signed int __anonymous_object5))[];
    235270__attribute__ ((unused,unused)) signed int (*__f3__FPA0i_i__1(signed int __p__i_1))[]{
    236271    __attribute__ ((unused)) signed int (*___retval_f3__PA0i_1)[];
    237272}
    238 __attribute__ ((unused,used,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object2);
    239 __attribute__ ((unused,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object3){
    240     __attribute__ ((unused)) signed int (*___retval_f4__PFi_i__1)(signed int __anonymous_object4);
     273__attribute__ ((unused,used,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object6);
     274__attribute__ ((unused,unused)) signed int (*__f4__FPFi_i____1())(signed int __anonymous_object7){
     275    __attribute__ ((unused)) signed int (*___retval_f4__PFi_i__1)(signed int __anonymous_object8);
    241276}
    242277signed int __vtr__Fi___1(){
     
    268303signed int __tpr2__Fi_PPi__1(__attribute__ ((unused,unused,unused,unused,unused,unused)) signed int **__Foo__PPi_1);
    269304signed int __tpr3__Fi_Pi__1(__attribute__ ((unused,unused,unused)) signed int *__Foo__Pi_1);
    270 signed int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) signed int (*__anonymous_object5)(__attribute__ ((unused,unused)) signed int __anonymous_object6[((unsigned long int )5)]));
     305signed int __tpr4__Fi_PFi_Pi___1(__attribute__ ((unused,unused)) signed int (*__anonymous_object9)(__attribute__ ((unused,unused)) signed int __anonymous_object10[((unsigned long int )5)]));
    271306signed int __tpr5__Fi_PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__Foo__PFi___1)());
    272307signed int __tpr6__Fi_PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__Foo__PFi___1)());
    273 signed int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) signed int (*__anonymous_object7)(__attribute__ ((unused)) signed int (*__anonymous_object8)(__attribute__ ((unused,unused)) signed int __anonymous_object9)));
     308signed int __tpr7__Fi_PFi_PFi_i____1(__attribute__ ((unused,unused)) signed int (*__anonymous_object11)(__attribute__ ((unused)) signed int (*__anonymous_object12)(__attribute__ ((unused,unused)) signed int __anonymous_object13)));
    274309signed int __ad__Fi___1(){
    275310    __attribute__ ((unused)) signed int ___retval_ad__i_1;
     
    300335        struct __anonymous4 ___ret__13s__anonymous4_2;
    301336        ((void)((*___dst__R13s__anonymous4_2).__i__i_2=___src__13s__anonymous4_2.__i__i_2));
    302         ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___2((&___ret__13s__anonymous4_2), ___src__13s__anonymous4_2));
    303         return ((struct __anonymous4 )___ret__13s__anonymous4_2);
     337        ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___2((&___ret__13s__anonymous4_2), (*___dst__R13s__anonymous4_2)));
     338        return ___ret__13s__anonymous4_2;
    304339    }
    305340    inline void ___constructor__F_R13s__anonymous4i_autogen___2(struct __anonymous4 *___dst__R13s__anonymous4_2, signed int __i__i_2){
     
    313348    }
    314349    inline void ___constructor__F_R13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__R13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
    315         ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2));
     350        ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2) /* ?{} */);
    316351    }
    317352    inline void ___destructor__F_R13e__anonymous5_intrinsic___2(__attribute__ ((unused)) enum __anonymous5 *___dst__R13e__anonymous5_2){
     
    319354    inline enum __anonymous5 ___operator_assign__F13e__anonymous5_R13e__anonymous513e__anonymous5_intrinsic___2(enum __anonymous5 *___dst__R13e__anonymous5_2, enum __anonymous5 ___src__13e__anonymous5_2){
    320355        enum __anonymous5 ___ret__13e__anonymous5_2;
    321         ((void)(___ret__13e__anonymous5_2=((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2)) /* ?{} */);
    322         return ((enum __anonymous5 )___ret__13e__anonymous5_2);
     356        ((void)((*___dst__R13e__anonymous5_2)=___src__13e__anonymous5_2));
     357        ((void)(___ret__13e__anonymous5_2=(*___dst__R13e__anonymous5_2)) /* ?{} */);
     358        return ___ret__13e__anonymous5_2;
    323359    }
    324360    ((void)sizeof(enum __anonymous5 ));
    325361}
    326 signed int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object10, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object11);
    327 signed int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object12, __attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object13);
    328 signed int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object14, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object15);
    329 signed int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)());
    330 signed int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object18)(__attribute__ ((unused)) signed int __anonymous_object19), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object20)(__attribute__ ((unused)) signed int __anonymous_object21));
    331 signed int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object22)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object23)());
    332 signed int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object24)(__attribute__ ((unused)) signed int __anonymous_object25), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object26)(__attribute__ ((unused)) signed int __anonymous_object27));
     362signed int __apd1__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object14, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object15);
     363signed int __apd2__Fi_PPiPPi__1(__attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object16, __attribute__ ((unused,unused,unused,unused)) signed int **__anonymous_object17);
     364signed int __apd3__Fi_PiPi__1(__attribute__ ((unused,unused,unused)) signed int *__anonymous_object18, __attribute__ ((unused,unused,unused)) signed int *__anonymous_object19);
     365signed int __apd4__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object20)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object21)());
     366signed int __apd5__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object22)(__attribute__ ((unused)) signed int __anonymous_object23), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object24)(__attribute__ ((unused)) signed int __anonymous_object25));
     367signed int __apd6__Fi_PFi__PFi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object26)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object27)());
     368signed int __apd7__Fi_PFi_i_PFi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object28)(__attribute__ ((unused)) signed int __anonymous_object29), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object30)(__attribute__ ((unused)) signed int __anonymous_object31));
    333369struct Vad {
    334     __attribute__ ((unused)) signed int __anonymous_object28;
    335     __attribute__ ((unused,unused)) signed int *__anonymous_object29;
    336     __attribute__ ((unused,unused)) signed int __anonymous_object30[((unsigned long int )10)];
    337     __attribute__ ((unused,unused)) signed int (*__anonymous_object31)();
     370    __attribute__ ((unused)) signed int __anonymous_object32;
     371    __attribute__ ((unused,unused)) signed int *__anonymous_object33;
     372    __attribute__ ((unused,unused)) signed int __anonymous_object34[((unsigned long int )10)];
     373    __attribute__ ((unused,unused)) signed int (*__anonymous_object35)();
    338374};
    339375static inline void ___constructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1);
     
    341377static inline void ___destructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1);
    342378static inline struct Vad ___operator_assign__F4sVad_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1);
     379static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object36);
     380static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object37, signed int *__anonymous_object38);
     381static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object39, signed int *__anonymous_object40, signed int __anonymous_object41[((unsigned long int )10)]);
     382static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object42, signed int *__anonymous_object43, signed int __anonymous_object44[((unsigned long int )10)], signed int (*__anonymous_object45)());
    343383static inline void ___constructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1){
     384    ((void)((*___dst__R4sVad_1).__anonymous_object32) /* ?{} */);
     385    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ?{} */);
     386    {
     387        signed int _index0 = 0;
     388        for (;(_index0<10);((void)(++_index0))) {
     389            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index0)])))) /* ?{} */);
     390        }
     391
     392    }
     393
     394    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
    344395}
    345396static inline void ___constructor__F_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1){
     397    ((void)((*___dst__R4sVad_1).__anonymous_object32=___src__4sVad_1.__anonymous_object32) /* ?{} */);
     398    ((void)((*___dst__R4sVad_1).__anonymous_object33=___src__4sVad_1.__anonymous_object33) /* ?{} */);
     399    {
     400        signed int _index1 = 0;
     401        for (;(_index1<10);((void)(++_index1))) {
     402            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index1)])))=___src__4sVad_1.__anonymous_object34[((signed long int )_index1)]) /* ?{} */);
     403        }
     404
     405    }
     406
     407    ((void)((*___dst__R4sVad_1).__anonymous_object35=___src__4sVad_1.__anonymous_object35) /* ?{} */);
    346408}
    347409static inline void ___destructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1){
     410    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ^?{} */);
     411    {
     412        signed int _index2 = (10-1);
     413        for (;(_index2>=0);((void)(--_index2))) {
     414            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index2)])))) /* ^?{} */);
     415        }
     416
     417    }
     418
     419    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ^?{} */);
     420    ((void)((*___dst__R4sVad_1).__anonymous_object32) /* ^?{} */);
    348421}
    349422static inline struct Vad ___operator_assign__F4sVad_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1){
    350423    struct Vad ___ret__4sVad_1;
    351     ((void)___constructor__F_R4sVad4sVad_autogen___1((&___ret__4sVad_1), ___src__4sVad_1));
    352     return ((struct Vad )___ret__4sVad_1);
    353 }
     424    ((void)((*___dst__R4sVad_1).__anonymous_object32=___src__4sVad_1.__anonymous_object32));
     425    ((void)((*___dst__R4sVad_1).__anonymous_object33=___src__4sVad_1.__anonymous_object33));
     426    {
     427        signed int _index3 = 0;
     428        for (;(_index3<10);((void)(++_index3))) {
     429            ((void)((*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index3)]=___src__4sVad_1.__anonymous_object34[((signed long int )_index3)]));
     430        }
     431
     432    }
     433
     434    ((void)((*___dst__R4sVad_1).__anonymous_object35=___src__4sVad_1.__anonymous_object35));
     435    ((void)___constructor__F_R4sVad4sVad_autogen___1((&___ret__4sVad_1), (*___dst__R4sVad_1)));
     436    return ___ret__4sVad_1;
     437}
     438static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object46){
     439    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object46) /* ?{} */);
     440    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ?{} */);
     441    {
     442        signed int _index4 = 0;
     443        for (;(_index4<10);((void)(++_index4))) {
     444            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index4)])))) /* ?{} */);
     445        }
     446
     447    }
     448
     449    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     450}
     451static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object47, signed int *__anonymous_object48){
     452    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object47) /* ?{} */);
     453    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object48) /* ?{} */);
     454    {
     455        signed int _index5 = 0;
     456        for (;(_index5<10);((void)(++_index5))) {
     457            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index5)])))) /* ?{} */);
     458        }
     459
     460    }
     461
     462    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     463}
     464static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object49, signed int *__anonymous_object50, signed int __anonymous_object51[((unsigned long int )10)]){
     465    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object49) /* ?{} */);
     466    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object50) /* ?{} */);
     467    {
     468        signed int _index6 = 0;
     469        for (;(_index6<10);((void)(++_index6))) {
     470            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index6)])))=__anonymous_object51[((signed long int )_index6)]) /* ?{} */);
     471        }
     472
     473    }
     474
     475    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
     476}
     477static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object52, signed int *__anonymous_object53, signed int __anonymous_object54[((unsigned long int )10)], signed int (*__anonymous_object55)()){
     478    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object52) /* ?{} */);
     479    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object53) /* ?{} */);
     480    {
     481        signed int _index7 = 0;
     482        for (;(_index7<10);((void)(++_index7))) {
     483            ((void)((*((signed int *)(&(*___dst__R4sVad_1).__anonymous_object34[((signed long int )_index7)])))=__anonymous_object54[((signed long int )_index7)]) /* ?{} */);
     484        }
     485
     486    }
     487
     488    ((void)((*___dst__R4sVad_1).__anonymous_object35=__anonymous_object55) /* ?{} */);
     489}
  • src/tests/.expect/64/declarationSpecifier.txt

    rb96ec83 r6840e7c  
    2020static inline void ___destructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1);
    2121static inline struct __anonymous0 ___operator_assign__F13s__anonymous0_R13s__anonymous013s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, struct __anonymous0 ___src__13s__anonymous0_1);
     22static inline void ___constructor__F_R13s__anonymous0i_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, signed int __i__i_1);
    2223static inline void ___constructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1){
    2324    ((void)((*___dst__R13s__anonymous0_1).__i__i_1) /* ?{} */);
     
    3233    struct __anonymous0 ___ret__13s__anonymous0_1;
    3334    ((void)((*___dst__R13s__anonymous0_1).__i__i_1=___src__13s__anonymous0_1.__i__i_1));
    34     ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), ___src__13s__anonymous0_1));
    35     return ((struct __anonymous0 )___ret__13s__anonymous0_1);
     35    ((void)___constructor__F_R13s__anonymous013s__anonymous0_autogen___1((&___ret__13s__anonymous0_1), (*___dst__R13s__anonymous0_1)));
     36    return ___ret__13s__anonymous0_1;
    3637}
    3738static inline void ___constructor__F_R13s__anonymous0i_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1, signed int __i__i_1){
     
    4647static inline void ___destructor__F_R13s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1);
    4748static inline struct __anonymous1 ___operator_assign__F13s__anonymous1_R13s__anonymous113s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, struct __anonymous1 ___src__13s__anonymous1_1);
     49static inline void ___constructor__F_R13s__anonymous1i_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, signed int __i__i_1);
    4850static inline void ___constructor__F_R13s__anonymous1_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1){
    4951    ((void)((*___dst__R13s__anonymous1_1).__i__i_1) /* ?{} */);
     
    5860    struct __anonymous1 ___ret__13s__anonymous1_1;
    5961    ((void)((*___dst__R13s__anonymous1_1).__i__i_1=___src__13s__anonymous1_1.__i__i_1));
    60     ((void)___constructor__F_R13s__anonymous113s__anonymous1_autogen___1((&___ret__13s__anonymous1_1), ___src__13s__anonymous1_1));
    61     return ((struct __anonymous1 )___ret__13s__anonymous1_1);
     62    ((void)___constructor__F_R13s__anonymous113s__anonymous1_autogen___1((&___ret__13s__anonymous1_1), (*___dst__R13s__anonymous1_1)));
     63    return ___ret__13s__anonymous1_1;
    6264}
    6365static inline void ___constructor__F_R13s__anonymous1i_autogen___1(struct __anonymous1 *___dst__R13s__anonymous1_1, signed int __i__i_1){
     
    7274static inline void ___destructor__F_R13s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1);
    7375static inline struct __anonymous2 ___operator_assign__F13s__anonymous2_R13s__anonymous213s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, struct __anonymous2 ___src__13s__anonymous2_1);
     76static inline void ___constructor__F_R13s__anonymous2i_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, signed int __i__i_1);
    7477static inline void ___constructor__F_R13s__anonymous2_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1){
    7578    ((void)((*___dst__R13s__anonymous2_1).__i__i_1) /* ?{} */);
     
    8487    struct __anonymous2 ___ret__13s__anonymous2_1;
    8588    ((void)((*___dst__R13s__anonymous2_1).__i__i_1=___src__13s__anonymous2_1.__i__i_1));
    86     ((void)___constructor__F_R13s__anonymous213s__anonymous2_autogen___1((&___ret__13s__anonymous2_1), ___src__13s__anonymous2_1));
    87     return ((struct __anonymous2 )___ret__13s__anonymous2_1);
     89    ((void)___constructor__F_R13s__anonymous213s__anonymous2_autogen___1((&___ret__13s__anonymous2_1), (*___dst__R13s__anonymous2_1)));
     90    return ___ret__13s__anonymous2_1;
    8891}
    8992static inline void ___constructor__F_R13s__anonymous2i_autogen___1(struct __anonymous2 *___dst__R13s__anonymous2_1, signed int __i__i_1){
     
    98101static inline void ___destructor__F_R13s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1);
    99102static inline struct __anonymous3 ___operator_assign__F13s__anonymous3_R13s__anonymous313s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, struct __anonymous3 ___src__13s__anonymous3_1);
     103static inline void ___constructor__F_R13s__anonymous3i_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, signed int __i__i_1);
    100104static inline void ___constructor__F_R13s__anonymous3_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1){
    101105    ((void)((*___dst__R13s__anonymous3_1).__i__i_1) /* ?{} */);
     
    110114    struct __anonymous3 ___ret__13s__anonymous3_1;
    111115    ((void)((*___dst__R13s__anonymous3_1).__i__i_1=___src__13s__anonymous3_1.__i__i_1));
    112     ((void)___constructor__F_R13s__anonymous313s__anonymous3_autogen___1((&___ret__13s__anonymous3_1), ___src__13s__anonymous3_1));
    113     return ((struct __anonymous3 )___ret__13s__anonymous3_1);
     116    ((void)___constructor__F_R13s__anonymous313s__anonymous3_autogen___1((&___ret__13s__anonymous3_1), (*___dst__R13s__anonymous3_1)));
     117    return ___ret__13s__anonymous3_1;
    114118}
    115119static inline void ___constructor__F_R13s__anonymous3i_autogen___1(struct __anonymous3 *___dst__R13s__anonymous3_1, signed int __i__i_1){
     
    124128static inline void ___destructor__F_R13s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1);
    125129static inline struct __anonymous4 ___operator_assign__F13s__anonymous4_R13s__anonymous413s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, struct __anonymous4 ___src__13s__anonymous4_1);
     130static inline void ___constructor__F_R13s__anonymous4i_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, signed int __i__i_1);
    126131static inline void ___constructor__F_R13s__anonymous4_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1){
    127132    ((void)((*___dst__R13s__anonymous4_1).__i__i_1) /* ?{} */);
     
    136141    struct __anonymous4 ___ret__13s__anonymous4_1;
    137142    ((void)((*___dst__R13s__anonymous4_1).__i__i_1=___src__13s__anonymous4_1.__i__i_1));
    138     ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___1((&___ret__13s__anonymous4_1), ___src__13s__anonymous4_1));
    139     return ((struct __anonymous4 )___ret__13s__anonymous4_1);
     143    ((void)___constructor__F_R13s__anonymous413s__anonymous4_autogen___1((&___ret__13s__anonymous4_1), (*___dst__R13s__anonymous4_1)));
     144    return ___ret__13s__anonymous4_1;
    140145}
    141146static inline void ___constructor__F_R13s__anonymous4i_autogen___1(struct __anonymous4 *___dst__R13s__anonymous4_1, signed int __i__i_1){
     
    150155static inline void ___destructor__F_R13s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1);
    151156static inline struct __anonymous5 ___operator_assign__F13s__anonymous5_R13s__anonymous513s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, struct __anonymous5 ___src__13s__anonymous5_1);
     157static inline void ___constructor__F_R13s__anonymous5i_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, signed int __i__i_1);
    152158static inline void ___constructor__F_R13s__anonymous5_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1){
    153159    ((void)((*___dst__R13s__anonymous5_1).__i__i_1) /* ?{} */);
     
    162168    struct __anonymous5 ___ret__13s__anonymous5_1;
    163169    ((void)((*___dst__R13s__anonymous5_1).__i__i_1=___src__13s__anonymous5_1.__i__i_1));
    164     ((void)___constructor__F_R13s__anonymous513s__anonymous5_autogen___1((&___ret__13s__anonymous5_1), ___src__13s__anonymous5_1));
    165     return ((struct __anonymous5 )___ret__13s__anonymous5_1);
     170    ((void)___constructor__F_R13s__anonymous513s__anonymous5_autogen___1((&___ret__13s__anonymous5_1), (*___dst__R13s__anonymous5_1)));
     171    return ___ret__13s__anonymous5_1;
    166172}
    167173static inline void ___constructor__F_R13s__anonymous5i_autogen___1(struct __anonymous5 *___dst__R13s__anonymous5_1, signed int __i__i_1){
     
    176182static inline void ___destructor__F_R13s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1);
    177183static inline struct __anonymous6 ___operator_assign__F13s__anonymous6_R13s__anonymous613s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, struct __anonymous6 ___src__13s__anonymous6_1);
     184static inline void ___constructor__F_R13s__anonymous6i_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, signed int __i__i_1);
    178185static inline void ___constructor__F_R13s__anonymous6_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1){
    179186    ((void)((*___dst__R13s__anonymous6_1).__i__i_1) /* ?{} */);
     
    188195    struct __anonymous6 ___ret__13s__anonymous6_1;
    189196    ((void)((*___dst__R13s__anonymous6_1).__i__i_1=___src__13s__anonymous6_1.__i__i_1));
    190     ((void)___constructor__F_R13s__anonymous613s__anonymous6_autogen___1((&___ret__13s__anonymous6_1), ___src__13s__anonymous6_1));
    191     return ((struct __anonymous6 )___ret__13s__anonymous6_1);
     197    ((void)___constructor__F_R13s__anonymous613s__anonymous6_autogen___1((&___ret__13s__anonymous6_1), (*___dst__R13s__anonymous6_1)));
     198    return ___ret__13s__anonymous6_1;
    192199}
    193200static inline void ___constructor__F_R13s__anonymous6i_autogen___1(struct __anonymous6 *___dst__R13s__anonymous6_1, signed int __i__i_1){
     
    202209static inline void ___destructor__F_R13s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1);
    203210static inline struct __anonymous7 ___operator_assign__F13s__anonymous7_R13s__anonymous713s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, struct __anonymous7 ___src__13s__anonymous7_1);
     211static inline void ___constructor__F_R13s__anonymous7i_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, signed int __i__i_1);
    204212static inline void ___constructor__F_R13s__anonymous7_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1){
    205213    ((void)((*___dst__R13s__anonymous7_1).__i__i_1) /* ?{} */);
     
    214222    struct __anonymous7 ___ret__13s__anonymous7_1;
    215223    ((void)((*___dst__R13s__anonymous7_1).__i__i_1=___src__13s__anonymous7_1.__i__i_1));
    216     ((void)___constructor__F_R13s__anonymous713s__anonymous7_autogen___1((&___ret__13s__anonymous7_1), ___src__13s__anonymous7_1));
    217     return ((struct __anonymous7 )___ret__13s__anonymous7_1);
     224    ((void)___constructor__F_R13s__anonymous713s__anonymous7_autogen___1((&___ret__13s__anonymous7_1), (*___dst__R13s__anonymous7_1)));
     225    return ___ret__13s__anonymous7_1;
    218226}
    219227static inline void ___constructor__F_R13s__anonymous7i_autogen___1(struct __anonymous7 *___dst__R13s__anonymous7_1, signed int __i__i_1){
     
    236244static inline void ___destructor__F_R13s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1);
    237245static inline struct __anonymous8 ___operator_assign__F13s__anonymous8_R13s__anonymous813s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, struct __anonymous8 ___src__13s__anonymous8_1);
     246static inline void ___constructor__F_R13s__anonymous8s_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, signed short int __i__s_1);
    238247static inline void ___constructor__F_R13s__anonymous8_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1){
    239248    ((void)((*___dst__R13s__anonymous8_1).__i__s_1) /* ?{} */);
     
    248257    struct __anonymous8 ___ret__13s__anonymous8_1;
    249258    ((void)((*___dst__R13s__anonymous8_1).__i__s_1=___src__13s__anonymous8_1.__i__s_1));
    250     ((void)___constructor__F_R13s__anonymous813s__anonymous8_autogen___1((&___ret__13s__anonymous8_1), ___src__13s__anonymous8_1));
    251     return ((struct __anonymous8 )___ret__13s__anonymous8_1);
     259    ((void)___constructor__F_R13s__anonymous813s__anonymous8_autogen___1((&___ret__13s__anonymous8_1), (*___dst__R13s__anonymous8_1)));
     260    return ___ret__13s__anonymous8_1;
    252261}
    253262static inline void ___constructor__F_R13s__anonymous8s_autogen___1(struct __anonymous8 *___dst__R13s__anonymous8_1, signed short int __i__s_1){
     
    262271static inline void ___destructor__F_R13s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1);
    263272static inline struct __anonymous9 ___operator_assign__F13s__anonymous9_R13s__anonymous913s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, struct __anonymous9 ___src__13s__anonymous9_1);
     273static inline void ___constructor__F_R13s__anonymous9s_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, signed short int __i__s_1);
    264274static inline void ___constructor__F_R13s__anonymous9_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1){
    265275    ((void)((*___dst__R13s__anonymous9_1).__i__s_1) /* ?{} */);
     
    274284    struct __anonymous9 ___ret__13s__anonymous9_1;
    275285    ((void)((*___dst__R13s__anonymous9_1).__i__s_1=___src__13s__anonymous9_1.__i__s_1));
    276     ((void)___constructor__F_R13s__anonymous913s__anonymous9_autogen___1((&___ret__13s__anonymous9_1), ___src__13s__anonymous9_1));
    277     return ((struct __anonymous9 )___ret__13s__anonymous9_1);
     286    ((void)___constructor__F_R13s__anonymous913s__anonymous9_autogen___1((&___ret__13s__anonymous9_1), (*___dst__R13s__anonymous9_1)));
     287    return ___ret__13s__anonymous9_1;
    278288}
    279289static inline void ___constructor__F_R13s__anonymous9s_autogen___1(struct __anonymous9 *___dst__R13s__anonymous9_1, signed short int __i__s_1){
     
    288298static inline void ___destructor__F_R14s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1);
    289299static inline struct __anonymous10 ___operator_assign__F14s__anonymous10_R14s__anonymous1014s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, struct __anonymous10 ___src__14s__anonymous10_1);
     300static inline void ___constructor__F_R14s__anonymous10s_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, signed short int __i__s_1);
    290301static inline void ___constructor__F_R14s__anonymous10_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1){
    291302    ((void)((*___dst__R14s__anonymous10_1).__i__s_1) /* ?{} */);
     
    300311    struct __anonymous10 ___ret__14s__anonymous10_1;
    301312    ((void)((*___dst__R14s__anonymous10_1).__i__s_1=___src__14s__anonymous10_1.__i__s_1));
    302     ((void)___constructor__F_R14s__anonymous1014s__anonymous10_autogen___1((&___ret__14s__anonymous10_1), ___src__14s__anonymous10_1));
    303     return ((struct __anonymous10 )___ret__14s__anonymous10_1);
     313    ((void)___constructor__F_R14s__anonymous1014s__anonymous10_autogen___1((&___ret__14s__anonymous10_1), (*___dst__R14s__anonymous10_1)));
     314    return ___ret__14s__anonymous10_1;
    304315}
    305316static inline void ___constructor__F_R14s__anonymous10s_autogen___1(struct __anonymous10 *___dst__R14s__anonymous10_1, signed short int __i__s_1){
     
    314325static inline void ___destructor__F_R14s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1);
    315326static inline struct __anonymous11 ___operator_assign__F14s__anonymous11_R14s__anonymous1114s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, struct __anonymous11 ___src__14s__anonymous11_1);
     327static inline void ___constructor__F_R14s__anonymous11s_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, signed short int __i__s_1);
    316328static inline void ___constructor__F_R14s__anonymous11_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1){
    317329    ((void)((*___dst__R14s__anonymous11_1).__i__s_1) /* ?{} */);
     
    326338    struct __anonymous11 ___ret__14s__anonymous11_1;
    327339    ((void)((*___dst__R14s__anonymous11_1).__i__s_1=___src__14s__anonymous11_1.__i__s_1));
    328     ((void)___constructor__F_R14s__anonymous1114s__anonymous11_autogen___1((&___ret__14s__anonymous11_1), ___src__14s__anonymous11_1));
    329     return ((struct __anonymous11 )___ret__14s__anonymous11_1);
     340    ((void)___constructor__F_R14s__anonymous1114s__anonymous11_autogen___1((&___ret__14s__anonymous11_1), (*___dst__R14s__anonymous11_1)));
     341    return ___ret__14s__anonymous11_1;
    330342}
    331343static inline void ___constructor__F_R14s__anonymous11s_autogen___1(struct __anonymous11 *___dst__R14s__anonymous11_1, signed short int __i__s_1){
     
    340352static inline void ___destructor__F_R14s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1);
    341353static inline struct __anonymous12 ___operator_assign__F14s__anonymous12_R14s__anonymous1214s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, struct __anonymous12 ___src__14s__anonymous12_1);
     354static inline void ___constructor__F_R14s__anonymous12s_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, signed short int __i__s_1);
    342355static inline void ___constructor__F_R14s__anonymous12_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1){
    343356    ((void)((*___dst__R14s__anonymous12_1).__i__s_1) /* ?{} */);
     
    352365    struct __anonymous12 ___ret__14s__anonymous12_1;
    353366    ((void)((*___dst__R14s__anonymous12_1).__i__s_1=___src__14s__anonymous12_1.__i__s_1));
    354     ((void)___constructor__F_R14s__anonymous1214s__anonymous12_autogen___1((&___ret__14s__anonymous12_1), ___src__14s__anonymous12_1));
    355     return ((struct __anonymous12 )___ret__14s__anonymous12_1);
     367    ((void)___constructor__F_R14s__anonymous1214s__anonymous12_autogen___1((&___ret__14s__anonymous12_1), (*___dst__R14s__anonymous12_1)));
     368    return ___ret__14s__anonymous12_1;
    356369}
    357370static inline void ___constructor__F_R14s__anonymous12s_autogen___1(struct __anonymous12 *___dst__R14s__anonymous12_1, signed short int __i__s_1){
     
    366379static inline void ___destructor__F_R14s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1);
    367380static inline struct __anonymous13 ___operator_assign__F14s__anonymous13_R14s__anonymous1314s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, struct __anonymous13 ___src__14s__anonymous13_1);
     381static inline void ___constructor__F_R14s__anonymous13s_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, signed short int __i__s_1);
    368382static inline void ___constructor__F_R14s__anonymous13_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1){
    369383    ((void)((*___dst__R14s__anonymous13_1).__i__s_1) /* ?{} */);
     
    378392    struct __anonymous13 ___ret__14s__anonymous13_1;
    379393    ((void)((*___dst__R14s__anonymous13_1).__i__s_1=___src__14s__anonymous13_1.__i__s_1));
    380     ((void)___constructor__F_R14s__anonymous1314s__anonymous13_autogen___1((&___ret__14s__anonymous13_1), ___src__14s__anonymous13_1));
    381     return ((struct __anonymous13 )___ret__14s__anonymous13_1);
     394    ((void)___constructor__F_R14s__anonymous1314s__anonymous13_autogen___1((&___ret__14s__anonymous13_1), (*___dst__R14s__anonymous13_1)));
     395    return ___ret__14s__anonymous13_1;
    382396}
    383397static inline void ___constructor__F_R14s__anonymous13s_autogen___1(struct __anonymous13 *___dst__R14s__anonymous13_1, signed short int __i__s_1){
     
    392406static inline void ___destructor__F_R14s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1);
    393407static inline struct __anonymous14 ___operator_assign__F14s__anonymous14_R14s__anonymous1414s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, struct __anonymous14 ___src__14s__anonymous14_1);
     408static inline void ___constructor__F_R14s__anonymous14s_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, signed short int __i__s_1);
    394409static inline void ___constructor__F_R14s__anonymous14_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1){
    395410    ((void)((*___dst__R14s__anonymous14_1).__i__s_1) /* ?{} */);
     
    404419    struct __anonymous14 ___ret__14s__anonymous14_1;
    405420    ((void)((*___dst__R14s__anonymous14_1).__i__s_1=___src__14s__anonymous14_1.__i__s_1));
    406     ((void)___constructor__F_R14s__anonymous1414s__anonymous14_autogen___1((&___ret__14s__anonymous14_1), ___src__14s__anonymous14_1));
    407     return ((struct __anonymous14 )___ret__14s__anonymous14_1);
     421    ((void)___constructor__F_R14s__anonymous1414s__anonymous14_autogen___1((&___ret__14s__anonymous14_1), (*___dst__R14s__anonymous14_1)));
     422    return ___ret__14s__anonymous14_1;
    408423}
    409424static inline void ___constructor__F_R14s__anonymous14s_autogen___1(struct __anonymous14 *___dst__R14s__anonymous14_1, signed short int __i__s_1){
     
    418433static inline void ___destructor__F_R14s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1);
    419434static inline struct __anonymous15 ___operator_assign__F14s__anonymous15_R14s__anonymous1514s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, struct __anonymous15 ___src__14s__anonymous15_1);
     435static inline void ___constructor__F_R14s__anonymous15s_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, signed short int __i__s_1);
    420436static inline void ___constructor__F_R14s__anonymous15_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1){
    421437    ((void)((*___dst__R14s__anonymous15_1).__i__s_1) /* ?{} */);
     
    430446    struct __anonymous15 ___ret__14s__anonymous15_1;
    431447    ((void)((*___dst__R14s__anonymous15_1).__i__s_1=___src__14s__anonymous15_1.__i__s_1));
    432     ((void)___constructor__F_R14s__anonymous1514s__anonymous15_autogen___1((&___ret__14s__anonymous15_1), ___src__14s__anonymous15_1));
    433     return ((struct __anonymous15 )___ret__14s__anonymous15_1);
     448    ((void)___constructor__F_R14s__anonymous1514s__anonymous15_autogen___1((&___ret__14s__anonymous15_1), (*___dst__R14s__anonymous15_1)));
     449    return ___ret__14s__anonymous15_1;
    434450}
    435451static inline void ___constructor__F_R14s__anonymous15s_autogen___1(struct __anonymous15 *___dst__R14s__anonymous15_1, signed short int __i__s_1){
     
    460476static inline void ___destructor__F_R14s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1);
    461477static inline struct __anonymous16 ___operator_assign__F14s__anonymous16_R14s__anonymous1614s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, struct __anonymous16 ___src__14s__anonymous16_1);
     478static inline void ___constructor__F_R14s__anonymous16i_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, signed int __i__i_1);
    462479static inline void ___constructor__F_R14s__anonymous16_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1){
    463480    ((void)((*___dst__R14s__anonymous16_1).__i__i_1) /* ?{} */);
     
    472489    struct __anonymous16 ___ret__14s__anonymous16_1;
    473490    ((void)((*___dst__R14s__anonymous16_1).__i__i_1=___src__14s__anonymous16_1.__i__i_1));
    474     ((void)___constructor__F_R14s__anonymous1614s__anonymous16_autogen___1((&___ret__14s__anonymous16_1), ___src__14s__anonymous16_1));
    475     return ((struct __anonymous16 )___ret__14s__anonymous16_1);
     491    ((void)___constructor__F_R14s__anonymous1614s__anonymous16_autogen___1((&___ret__14s__anonymous16_1), (*___dst__R14s__anonymous16_1)));
     492    return ___ret__14s__anonymous16_1;
    476493}
    477494static inline void ___constructor__F_R14s__anonymous16i_autogen___1(struct __anonymous16 *___dst__R14s__anonymous16_1, signed int __i__i_1){
     
    486503static inline void ___destructor__F_R14s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1);
    487504static inline struct __anonymous17 ___operator_assign__F14s__anonymous17_R14s__anonymous1714s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, struct __anonymous17 ___src__14s__anonymous17_1);
     505static inline void ___constructor__F_R14s__anonymous17i_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, signed int __i__i_1);
    488506static inline void ___constructor__F_R14s__anonymous17_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1){
    489507    ((void)((*___dst__R14s__anonymous17_1).__i__i_1) /* ?{} */);
     
    498516    struct __anonymous17 ___ret__14s__anonymous17_1;
    499517    ((void)((*___dst__R14s__anonymous17_1).__i__i_1=___src__14s__anonymous17_1.__i__i_1));
    500     ((void)___constructor__F_R14s__anonymous1714s__anonymous17_autogen___1((&___ret__14s__anonymous17_1), ___src__14s__anonymous17_1));
    501     return ((struct __anonymous17 )___ret__14s__anonymous17_1);
     518    ((void)___constructor__F_R14s__anonymous1714s__anonymous17_autogen___1((&___ret__14s__anonymous17_1), (*___dst__R14s__anonymous17_1)));
     519    return ___ret__14s__anonymous17_1;
    502520}
    503521static inline void ___constructor__F_R14s__anonymous17i_autogen___1(struct __anonymous17 *___dst__R14s__anonymous17_1, signed int __i__i_1){
     
    512530static inline void ___destructor__F_R14s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1);
    513531static inline struct __anonymous18 ___operator_assign__F14s__anonymous18_R14s__anonymous1814s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, struct __anonymous18 ___src__14s__anonymous18_1);
     532static inline void ___constructor__F_R14s__anonymous18i_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, signed int __i__i_1);
    514533static inline void ___constructor__F_R14s__anonymous18_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1){
    515534    ((void)((*___dst__R14s__anonymous18_1).__i__i_1) /* ?{} */);
     
    524543    struct __anonymous18 ___ret__14s__anonymous18_1;
    525544    ((void)((*___dst__R14s__anonymous18_1).__i__i_1=___src__14s__anonymous18_1.__i__i_1));
    526     ((void)___constructor__F_R14s__anonymous1814s__anonymous18_autogen___1((&___ret__14s__anonymous18_1), ___src__14s__anonymous18_1));
    527     return ((struct __anonymous18 )___ret__14s__anonymous18_1);
     545    ((void)___constructor__F_R14s__anonymous1814s__anonymous18_autogen___1((&___ret__14s__anonymous18_1), (*___dst__R14s__anonymous18_1)));
     546    return ___ret__14s__anonymous18_1;
    528547}
    529548static inline void ___constructor__F_R14s__anonymous18i_autogen___1(struct __anonymous18 *___dst__R14s__anonymous18_1, signed int __i__i_1){
     
    538557static inline void ___destructor__F_R14s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1);
    539558static inline struct __anonymous19 ___operator_assign__F14s__anonymous19_R14s__anonymous1914s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, struct __anonymous19 ___src__14s__anonymous19_1);
     559static inline void ___constructor__F_R14s__anonymous19i_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, signed int __i__i_1);
    540560static inline void ___constructor__F_R14s__anonymous19_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1){
    541561    ((void)((*___dst__R14s__anonymous19_1).__i__i_1) /* ?{} */);
     
    550570    struct __anonymous19 ___ret__14s__anonymous19_1;
    551571    ((void)((*___dst__R14s__anonymous19_1).__i__i_1=___src__14s__anonymous19_1.__i__i_1));
    552     ((void)___constructor__F_R14s__anonymous1914s__anonymous19_autogen___1((&___ret__14s__anonymous19_1), ___src__14s__anonymous19_1));
    553     return ((struct __anonymous19 )___ret__14s__anonymous19_1);
     572    ((void)___constructor__F_R14s__anonymous1914s__anonymous19_autogen___1((&___ret__14s__anonymous19_1), (*___dst__R14s__anonymous19_1)));
     573    return ___ret__14s__anonymous19_1;
    554574}
    555575static inline void ___constructor__F_R14s__anonymous19i_autogen___1(struct __anonymous19 *___dst__R14s__anonymous19_1, signed int __i__i_1){
     
    564584static inline void ___destructor__F_R14s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1);
    565585static inline struct __anonymous20 ___operator_assign__F14s__anonymous20_R14s__anonymous2014s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, struct __anonymous20 ___src__14s__anonymous20_1);
     586static inline void ___constructor__F_R14s__anonymous20i_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, signed int __i__i_1);
    566587static inline void ___constructor__F_R14s__anonymous20_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1){
    567588    ((void)((*___dst__R14s__anonymous20_1).__i__i_1) /* ?{} */);
     
    576597    struct __anonymous20 ___ret__14s__anonymous20_1;
    577598    ((void)((*___dst__R14s__anonymous20_1).__i__i_1=___src__14s__anonymous20_1.__i__i_1));
    578     ((void)___constructor__F_R14s__anonymous2014s__anonymous20_autogen___1((&___ret__14s__anonymous20_1), ___src__14s__anonymous20_1));
    579     return ((struct __anonymous20 )___ret__14s__anonymous20_1);
     599    ((void)___constructor__F_R14s__anonymous2014s__anonymous20_autogen___1((&___ret__14s__anonymous20_1), (*___dst__R14s__anonymous20_1)));
     600    return ___ret__14s__anonymous20_1;
    580601}
    581602static inline void ___constructor__F_R14s__anonymous20i_autogen___1(struct __anonymous20 *___dst__R14s__anonymous20_1, signed int __i__i_1){
     
    590611static inline void ___destructor__F_R14s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1);
    591612static inline struct __anonymous21 ___operator_assign__F14s__anonymous21_R14s__anonymous2114s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, struct __anonymous21 ___src__14s__anonymous21_1);
     613static inline void ___constructor__F_R14s__anonymous21i_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, signed int __i__i_1);
    592614static inline void ___constructor__F_R14s__anonymous21_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1){
    593615    ((void)((*___dst__R14s__anonymous21_1).__i__i_1) /* ?{} */);
     
    602624    struct __anonymous21 ___ret__14s__anonymous21_1;
    603625    ((void)((*___dst__R14s__anonymous21_1).__i__i_1=___src__14s__anonymous21_1.__i__i_1));
    604     ((void)___constructor__F_R14s__anonymous2114s__anonymous21_autogen___1((&___ret__14s__anonymous21_1), ___src__14s__anonymous21_1));
    605     return ((struct __anonymous21 )___ret__14s__anonymous21_1);
     626    ((void)___constructor__F_R14s__anonymous2114s__anonymous21_autogen___1((&___ret__14s__anonymous21_1), (*___dst__R14s__anonymous21_1)));
     627    return ___ret__14s__anonymous21_1;
    606628}
    607629static inline void ___constructor__F_R14s__anonymous21i_autogen___1(struct __anonymous21 *___dst__R14s__anonymous21_1, signed int __i__i_1){
     
    616638static inline void ___destructor__F_R14s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1);
    617639static inline struct __anonymous22 ___operator_assign__F14s__anonymous22_R14s__anonymous2214s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, struct __anonymous22 ___src__14s__anonymous22_1);
     640static inline void ___constructor__F_R14s__anonymous22i_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, signed int __i__i_1);
    618641static inline void ___constructor__F_R14s__anonymous22_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1){
    619642    ((void)((*___dst__R14s__anonymous22_1).__i__i_1) /* ?{} */);
     
    628651    struct __anonymous22 ___ret__14s__anonymous22_1;
    629652    ((void)((*___dst__R14s__anonymous22_1).__i__i_1=___src__14s__anonymous22_1.__i__i_1));
    630     ((void)___constructor__F_R14s__anonymous2214s__anonymous22_autogen___1((&___ret__14s__anonymous22_1), ___src__14s__anonymous22_1));
    631     return ((struct __anonymous22 )___ret__14s__anonymous22_1);
     653    ((void)___constructor__F_R14s__anonymous2214s__anonymous22_autogen___1((&___ret__14s__anonymous22_1), (*___dst__R14s__anonymous22_1)));
     654    return ___ret__14s__anonymous22_1;
    632655}
    633656static inline void ___constructor__F_R14s__anonymous22i_autogen___1(struct __anonymous22 *___dst__R14s__anonymous22_1, signed int __i__i_1){
     
    642665static inline void ___destructor__F_R14s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1);
    643666static inline struct __anonymous23 ___operator_assign__F14s__anonymous23_R14s__anonymous2314s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, struct __anonymous23 ___src__14s__anonymous23_1);
     667static inline void ___constructor__F_R14s__anonymous23i_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, signed int __i__i_1);
    644668static inline void ___constructor__F_R14s__anonymous23_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1){
    645669    ((void)((*___dst__R14s__anonymous23_1).__i__i_1) /* ?{} */);
     
    654678    struct __anonymous23 ___ret__14s__anonymous23_1;
    655679    ((void)((*___dst__R14s__anonymous23_1).__i__i_1=___src__14s__anonymous23_1.__i__i_1));
    656     ((void)___constructor__F_R14s__anonymous2314s__anonymous23_autogen___1((&___ret__14s__anonymous23_1), ___src__14s__anonymous23_1));
    657     return ((struct __anonymous23 )___ret__14s__anonymous23_1);
     680    ((void)___constructor__F_R14s__anonymous2314s__anonymous23_autogen___1((&___ret__14s__anonymous23_1), (*___dst__R14s__anonymous23_1)));
     681    return ___ret__14s__anonymous23_1;
    658682}
    659683static inline void ___constructor__F_R14s__anonymous23i_autogen___1(struct __anonymous23 *___dst__R14s__anonymous23_1, signed int __i__i_1){
     
    672696    __attribute__ ((unused)) signed int ___retval_main__i_1;
    673697    ((void)(___retval_main__i_1=((signed int )0)) /* ?{} */);
    674     return ((signed int )___retval_main__i_1);
     698    return ___retval_main__i_1;
    675699    ((void)(___retval_main__i_1=0) /* ?{} */);
    676     return ((signed int )___retval_main__i_1);
     700    return ___retval_main__i_1;
    677701}
    678702static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi_iPPCc__1(argc, argv); }
     
    689713    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    690714    ((void)(_tmp_cp_ret0) /* ^?{} */);
    691     return ((signed int )___retval_main__i_1);
    692 }
     715    return ___retval_main__i_1;
     716}
  • src/tests/.expect/64/extension.txt

    rb96ec83 r6840e7c  
    1717static inline void ___destructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1);
    1818static inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___1(struct S *___dst__R2sS_1, struct S ___src__2sS_1);
     19static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1);
     20static inline void ___constructor__F_R2sSii_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1, signed int __b__i_1);
     21static inline void ___constructor__F_R2sSiii_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1, signed int __b__i_1, signed int __c__i_1);
    1922static inline void ___constructor__F_R2sS_autogen___1(struct S *___dst__R2sS_1){
    2023    ((void)((*___dst__R2sS_1).__a__i_1) /* ?{} */);
     
    3740    ((void)((*___dst__R2sS_1).__b__i_1=___src__2sS_1.__b__i_1));
    3841    ((void)((*___dst__R2sS_1).__c__i_1=___src__2sS_1.__c__i_1));
    39     ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), ___src__2sS_1));
    40     return ((struct S )___ret__2sS_1);
     42    ((void)___constructor__F_R2sS2sS_autogen___1((&___ret__2sS_1), (*___dst__R2sS_1)));
     43    return ___ret__2sS_1;
    4144}
    4245static inline void ___constructor__F_R2sSi_autogen___1(struct S *___dst__R2sS_1, signed int __a__i_1){
     
    6063    __extension__ signed int __c__i_1;
    6164};
     65static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     66static inline void ___constructor__F_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     67static inline void ___destructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1);
     68static inline union U ___operator_assign__F2uU_R2uU2uU_autogen___1(union U *___dst__R2uU_1, union U ___src__2uU_1);
     69static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1);
    6270static inline void ___constructor__F_R2uU_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1){
    6371}
     
    7078    union U ___ret__2uU_1;
    7179    ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&___src__2uU_1)), sizeof(union U )));
    72     ((void)___constructor__F_R2uU2uU_autogen___1((&___ret__2uU_1), ___src__2uU_1));
    73     return ((union U )___ret__2uU_1);
    74 }
    75 static inline void ___constructor__F_R2uUi_autogen___1(__attribute__ ((unused)) union U *___dst__R2uU_1, signed int __src__i_1){
    76     ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__src__i_1)), sizeof(signed int )));
     80    ((void)___constructor__F_R2uU2uU_autogen___1((&___ret__2uU_1), (*___dst__R2uU_1)));
     81    return ___ret__2uU_1;
     82}
     83static inline void ___constructor__F_R2uUi_autogen___1(union U *___dst__R2uU_1, signed int __a__i_1){
     84    ((void)__builtin_memcpy(((void *)___dst__R2uU_1), ((const void *)(&__a__i_1)), sizeof(signed int )));
    7785}
    7886__extension__ enum E {
     
    94102        __extension__ signed int *__z__Pi_2;
    95103    };
    96     signed int __i__i_2 = ((signed int )(__extension__ __a__i_1+__extension__ 3));
     104    inline void ___constructor__F_R2sS_autogen___2(struct S *___dst__R2sS_2){
     105        ((void)((*___dst__R2sS_2).__a__i_2) /* ?{} */);
     106        ((void)((*___dst__R2sS_2).__b__i_2) /* ?{} */);
     107        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     108        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     109        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     110        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     111    }
     112    inline void ___constructor__F_R2sS2sS_autogen___2(struct S *___dst__R2sS_2, struct S ___src__2sS_2){
     113        ((void)((*___dst__R2sS_2).__a__i_2=___src__2sS_2.__a__i_2) /* ?{} */);
     114        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2) /* ?{} */);
     115        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2) /* ?{} */);
     116        ((void)((*___dst__R2sS_2).__x__Pi_2=___src__2sS_2.__x__Pi_2) /* ?{} */);
     117        ((void)((*___dst__R2sS_2).__y__Pi_2=___src__2sS_2.__y__Pi_2) /* ?{} */);
     118        ((void)((*___dst__R2sS_2).__z__Pi_2=___src__2sS_2.__z__Pi_2) /* ?{} */);
     119    }
     120    inline void ___destructor__F_R2sS_autogen___2(struct S *___dst__R2sS_2){
     121        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ^?{} */);
     122        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ^?{} */);
     123        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ^?{} */);
     124        ((void)((*___dst__R2sS_2).__c__i_2) /* ^?{} */);
     125        ((void)((*___dst__R2sS_2).__b__i_2) /* ^?{} */);
     126        ((void)((*___dst__R2sS_2).__a__i_2) /* ^?{} */);
     127    }
     128    inline struct S ___operator_assign__F2sS_R2sS2sS_autogen___2(struct S *___dst__R2sS_2, struct S ___src__2sS_2){
     129        struct S ___ret__2sS_2;
     130        ((void)((*___dst__R2sS_2).__a__i_2=___src__2sS_2.__a__i_2));
     131        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2));
     132        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2));
     133        ((void)((*___dst__R2sS_2).__x__Pi_2=___src__2sS_2.__x__Pi_2));
     134        ((void)((*___dst__R2sS_2).__y__Pi_2=___src__2sS_2.__y__Pi_2));
     135        ((void)((*___dst__R2sS_2).__z__Pi_2=___src__2sS_2.__z__Pi_2));
     136        ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), (*___dst__R2sS_2)));
     137        return ___ret__2sS_2;
     138    }
     139    inline void ___constructor__F_R2sSi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2){
     140        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     141        ((void)((*___dst__R2sS_2).__b__i_2) /* ?{} */);
     142        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     143        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     144        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     145        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     146    }
     147    inline void ___constructor__F_R2sSii_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2){
     148        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     149        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     150        ((void)((*___dst__R2sS_2).__c__i_2) /* ?{} */);
     151        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     152        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     153        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     154    }
     155    inline void ___constructor__F_R2sSiii_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2){
     156        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     157        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     158        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     159        ((void)((*___dst__R2sS_2).__x__Pi_2) /* ?{} */);
     160        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     161        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     162    }
     163    inline void ___constructor__F_R2sSiiiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2){
     164        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     165        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     166        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     167        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     168        ((void)((*___dst__R2sS_2).__y__Pi_2) /* ?{} */);
     169        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     170    }
     171    inline void ___constructor__F_R2sSiiiPiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2, signed int *__y__Pi_2){
     172        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     173        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     174        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     175        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     176        ((void)((*___dst__R2sS_2).__y__Pi_2=__y__Pi_2) /* ?{} */);
     177        ((void)((*___dst__R2sS_2).__z__Pi_2) /* ?{} */);
     178    }
     179    inline void ___constructor__F_R2sSiiiPiPiPi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2, signed int __b__i_2, signed int __c__i_2, signed int *__x__Pi_2, signed int *__y__Pi_2, signed int *__z__Pi_2){
     180        ((void)((*___dst__R2sS_2).__a__i_2=__a__i_2) /* ?{} */);
     181        ((void)((*___dst__R2sS_2).__b__i_2=__b__i_2) /* ?{} */);
     182        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
     183        ((void)((*___dst__R2sS_2).__x__Pi_2=__x__Pi_2) /* ?{} */);
     184        ((void)((*___dst__R2sS_2).__y__Pi_2=__y__Pi_2) /* ?{} */);
     185        ((void)((*___dst__R2sS_2).__z__Pi_2=__z__Pi_2) /* ?{} */);
     186    }
     187    signed int __i__i_2 = (__extension__ __a__i_1+__extension__ 3);
    97188    ((void)__extension__ 3);
    98189    ((void)__extension__ __a__i_1);
  • src/tests/.expect/64/gccExtensions.txt

    rb96ec83 r6840e7c  
    6363        ((void)((*___dst__R2sS_2).__b__i_2=___src__2sS_2.__b__i_2));
    6464        ((void)((*___dst__R2sS_2).__c__i_2=___src__2sS_2.__c__i_2));
    65         ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), ___src__2sS_2));
    66         return ((struct S )___ret__2sS_2);
     65        ((void)___constructor__F_R2sS2sS_autogen___2((&___ret__2sS_2), (*___dst__R2sS_2)));
     66        return ___ret__2sS_2;
    6767    }
    6868    inline void ___constructor__F_R2sSi_autogen___2(struct S *___dst__R2sS_2, signed int __a__i_2){
     
    8181        ((void)((*___dst__R2sS_2).__c__i_2=__c__i_2) /* ?{} */);
    8282    }
    83     signed int __i__i_2 = ((signed int )__extension__ 3);
     83    signed int __i__i_2 = __extension__ 3;
    8484    __extension__ signed int __a__i_2;
    8585    __extension__ signed int __b__i_2;
     
    113113        struct s2 ___ret__3ss2_2;
    114114        ((void)((*___dst__R3ss2_2).__i__i_2=___src__3ss2_2.__i__i_2));
    115         ((void)___constructor__F_R3ss23ss2_autogen___2((&___ret__3ss2_2), ___src__3ss2_2));
    116         return ((struct s2 )___ret__3ss2_2);
     115        ((void)___constructor__F_R3ss23ss2_autogen___2((&___ret__3ss2_2), (*___dst__R3ss2_2)));
     116        return ___ret__3ss2_2;
    117117    }
    118118    inline void ___constructor__F_R3ss2i_autogen___2(struct s2 *___dst__R3ss2_2, signed int __i__i_2){
     
    134134        struct s3 ___ret__3ss3_2;
    135135        ((void)((*___dst__R3ss3_2).__i__i_2=___src__3ss3_2.__i__i_2));
    136         ((void)___constructor__F_R3ss33ss3_autogen___2((&___ret__3ss3_2), ___src__3ss3_2));
    137         return ((struct s3 )___ret__3ss3_2);
     136        ((void)___constructor__F_R3ss33ss3_autogen___2((&___ret__3ss3_2), (*___dst__R3ss3_2)));
     137        return ___ret__3ss3_2;
    138138    }
    139139    inline void ___constructor__F_R3ss3i_autogen___2(struct s3 *___dst__R3ss3_2, signed int __i__i_2){
     
    157157        struct s4 ___ret__3ss4_2;
    158158        ((void)((*___dst__R3ss4_2).__i__i_2=___src__3ss4_2.__i__i_2));
    159         ((void)___constructor__F_R3ss43ss4_autogen___2((&___ret__3ss4_2), ___src__3ss4_2));
    160         return ((struct s4 )___ret__3ss4_2);
     159        ((void)___constructor__F_R3ss43ss4_autogen___2((&___ret__3ss4_2), (*___dst__R3ss4_2)));
     160        return ___ret__3ss4_2;
    161161    }
    162162    inline void ___constructor__F_R3ss4i_autogen___2(struct s4 *___dst__R3ss4_2, signed int __i__i_2){
     
    169169    signed int __m3__A0A0i_2[((unsigned long int )10)][((unsigned long int )10)];
    170170    ((void)(___retval_main__i_1=((signed int )0)) /* ?{} */);
    171     return ((signed int )___retval_main__i_1);
     171    return ___retval_main__i_1;
    172172    ((void)(___retval_main__i_1=0) /* ?{} */);
    173     return ((signed int )___retval_main__i_1);
     173    return ___retval_main__i_1;
    174174}
    175175static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi_iPPCc__1(argc, argv); }
     
    186186    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    187187    ((void)(_tmp_cp_ret0) /* ^?{} */);
    188     return ((signed int )___retval_main__i_1);
     188    return ___retval_main__i_1;
    189189}
  • src/tests/.expect/64/literals.txt

    rb96ec83 r6840e7c  
    6464static inline void ___destructor__F_R16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1);
    6565static inline struct _Istream_cstrUC ___operator_assign__F16s_Istream_cstrUC_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, struct _Istream_cstrUC ___src__16s_Istream_cstrUC_1);
     66static inline void ___constructor__F_R16s_Istream_cstrUCPc_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, char *__s__Pc_1);
    6667static inline void ___constructor__F_R16s_Istream_cstrUC_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1){
    6768    ((void)((*___dst__R16s_Istream_cstrUC_1).__s__Pc_1) /* ?{} */);
     
    7677    struct _Istream_cstrUC ___ret__16s_Istream_cstrUC_1;
    7778    ((void)((*___dst__R16s_Istream_cstrUC_1).__s__Pc_1=___src__16s_Istream_cstrUC_1.__s__Pc_1));
    78     ((void)___constructor__F_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1((&___ret__16s_Istream_cstrUC_1), ___src__16s_Istream_cstrUC_1));
    79     return ((struct _Istream_cstrUC )___ret__16s_Istream_cstrUC_1);
     79    ((void)___constructor__F_R16s_Istream_cstrUC16s_Istream_cstrUC_autogen___1((&___ret__16s_Istream_cstrUC_1), (*___dst__R16s_Istream_cstrUC_1)));
     80    return ___ret__16s_Istream_cstrUC_1;
    8081}
    8182static inline void ___constructor__F_R16s_Istream_cstrUCPc_autogen___1(struct _Istream_cstrUC *___dst__R16s_Istream_cstrUC_1, char *__s__Pc_1){
     
    9293static inline void ___destructor__F_R15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1);
    9394static inline struct _Istream_cstrC ___operator_assign__F15s_Istream_cstrC_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, struct _Istream_cstrC ___src__15s_Istream_cstrC_1);
     95static inline void ___constructor__F_R15s_Istream_cstrCPc_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1);
     96static inline void ___constructor__F_R15s_Istream_cstrCPci_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1, signed int __size__i_1);
    9497static inline void ___constructor__F_R15s_Istream_cstrC_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1){
    9598    ((void)((*___dst__R15s_Istream_cstrC_1).__s__Pc_1) /* ?{} */);
     
    108111    ((void)((*___dst__R15s_Istream_cstrC_1).__s__Pc_1=___src__15s_Istream_cstrC_1.__s__Pc_1));
    109112    ((void)((*___dst__R15s_Istream_cstrC_1).__size__i_1=___src__15s_Istream_cstrC_1.__size__i_1));
    110     ((void)___constructor__F_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1((&___ret__15s_Istream_cstrC_1), ___src__15s_Istream_cstrC_1));
    111     return ((struct _Istream_cstrC )___ret__15s_Istream_cstrC_1);
     113    ((void)___constructor__F_R15s_Istream_cstrC15s_Istream_cstrC_autogen___1((&___ret__15s_Istream_cstrC_1), (*___dst__R15s_Istream_cstrC_1)));
     114    return ___ret__15s_Istream_cstrC_1;
    112115}
    113116static inline void ___constructor__F_R15s_Istream_cstrCPc_autogen___1(struct _Istream_cstrC *___dst__R15s_Istream_cstrC_1, char *__s__Pc_1){
     
    122125void *___operator_bitor__A0_1_0_0___fail__PFi_Pd0___eof__PFi_Pd0___open__PF_Pd0PCcPCc___close__PF_Pd0___read__PFPd0_Pd0PcUl___ungetc__PFPd0_Pd0c___fmt__PFi_Pd0PCc__FPd0_Pd015s_Istream_cstrC__1(__attribute__ ((unused)) signed int (*__fail__PFi_P7tistype__1)(void *__anonymous_object1284), __attribute__ ((unused)) signed int (*__eof__PFi_P7tistype__1)(void *__anonymous_object1285), __attribute__ ((unused)) void (*__open__PF_P7tistypePCcPCc__1)(void *__is__P7tistype_1, const char *__name__PCc_1, const char *__mode__PCc_1), __attribute__ ((unused)) void (*__close__PF_P7tistype__1)(void *__is__P7tistype_1), __attribute__ ((unused)) void *(*__read__PFP7tistype_P7tistypePcUl__1)(void *__anonymous_object1286, char *__anonymous_object1287, unsigned long int __anonymous_object1288), __attribute__ ((unused)) void *(*__ungetc__PFP7tistype_P7tistypec__1)(void *__anonymous_object1289, char __anonymous_object1290), __attribute__ ((unused)) signed int (*__fmt__PFi_P7tistypePCc__1)(void *__anonymous_object1291, const char *__fmt__PCc_1, ...), void *__anonymous_object1292, struct _Istream_cstrC __anonymous_object1293);
    123126enum __anonymous0 {
    124     __sepSize__C13e__anonymous0_1 = ((signed int )16),
     127    __sepSize__C13e__anonymous0_1 = 16,
    125128};
    126129struct ofstream {
     
    137140static inline void ___destructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1);
    138141static inline struct ofstream ___operator_assign__F9sofstream_R9sofstream9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1, struct ofstream ___src__9sofstream_1);
     142static inline void ___constructor__F_R9sofstreamPv_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1);
     143static inline void ___constructor__F_R9sofstreamPvb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1);
     144static inline void ___constructor__F_R9sofstreamPvbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1);
     145static inline void ___constructor__F_R9sofstreamPvbbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1);
     146static inline void ___constructor__F_R9sofstreamPvbbbPCc_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1);
     147static inline void ___constructor__F_R9sofstreamPvbbbPCcA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)]);
     148static inline void ___constructor__F_R9sofstreamPvbbbPCcA0cA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)], char __tupleSeparator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)]);
    139149static inline void ___constructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1){
    140150    ((void)((*___dst__R9sofstream_1).__file__Pv_1) /* ?{} */);
     
    144154    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    145155    {
    146         signed int _index0 = ((signed int )0);
     156        signed int _index0 = 0;
    147157        for (;(_index0<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index0))) {
    148158            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index0)])))) /* ?{} */);
     
    150160
    151161    }
    152     {
    153         signed int _index1 = ((signed int )0);
     162
     163    {
     164        signed int _index1 = 0;
    154165        for (;(_index1<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index1))) {
    155166            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index1)])))) /* ?{} */);
     
    157168
    158169    }
     170
    159171}
    160172static inline void ___constructor__F_R9sofstream9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1, struct ofstream ___src__9sofstream_1){
     
    165177    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=___src__9sofstream_1.__sepCur__PCc_1) /* ?{} */);
    166178    {
    167         signed int _index2 = ((signed int )0);
     179        signed int _index2 = 0;
    168180        for (;(_index2<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index2))) {
    169181            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index2)])))=___src__9sofstream_1.__separator__A0c_1[((signed long int )_index2)]) /* ?{} */);
     
    171183
    172184    }
    173     {
    174         signed int _index3 = ((signed int )0);
     185
     186    {
     187        signed int _index3 = 0;
    175188        for (;(_index3<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index3))) {
    176189            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index3)])))=___src__9sofstream_1.__tupleSeparator__A0c_1[((signed long int )_index3)]) /* ?{} */);
     
    178191
    179192    }
     193
    180194}
    181195static inline void ___destructor__F_R9sofstream_autogen___1(struct ofstream *___dst__R9sofstream_1){
    182196    {
    183         signed int _index4 = ((signed int )(((signed int )__sepSize__C13e__anonymous0_1)-1));
     197        signed int _index4 = (((signed int )__sepSize__C13e__anonymous0_1)-1);
    184198        for (;(_index4>=0);((void)(--_index4))) {
    185199            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index4)])))) /* ^?{} */);
     
    187201
    188202    }
    189     {
    190         signed int _index5 = ((signed int )(((signed int )__sepSize__C13e__anonymous0_1)-1));
     203
     204    {
     205        signed int _index5 = (((signed int )__sepSize__C13e__anonymous0_1)-1);
    191206        for (;(_index5>=0);((void)(--_index5))) {
    192207            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index5)])))) /* ^?{} */);
     
    194209
    195210    }
     211
    196212    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ^?{} */);
    197213    ((void)((*___dst__R9sofstream_1).__sawNL__b_1) /* ^?{} */);
     
    208224    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=___src__9sofstream_1.__sepCur__PCc_1));
    209225    {
    210         signed int _index6 = ((signed int )0);
     226        signed int _index6 = 0;
    211227        for (;(_index6<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index6))) {
    212228            ((void)((*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index6)]=___src__9sofstream_1.__separator__A0c_1[((signed long int )_index6)]));
     
    216232
    217233    {
    218         signed int _index7 = ((signed int )0);
     234        signed int _index7 = 0;
    219235        for (;(_index7<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index7))) {
    220236            ((void)((*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index7)]=___src__9sofstream_1.__tupleSeparator__A0c_1[((signed long int )_index7)]));
     
    223239    }
    224240
    225     ((void)___constructor__F_R9sofstream9sofstream_autogen___1((&___ret__9sofstream_1), ___src__9sofstream_1));
    226     return ((struct ofstream )___ret__9sofstream_1);
     241    ((void)___constructor__F_R9sofstream9sofstream_autogen___1((&___ret__9sofstream_1), (*___dst__R9sofstream_1)));
     242    return ___ret__9sofstream_1;
    227243}
    228244static inline void ___constructor__F_R9sofstreamPv_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1){
     
    233249    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    234250    {
    235         signed int _index8 = ((signed int )0);
     251        signed int _index8 = 0;
    236252        for (;(_index8<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index8))) {
    237253            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index8)])))) /* ?{} */);
     
    239255
    240256    }
    241     {
    242         signed int _index9 = ((signed int )0);
     257
     258    {
     259        signed int _index9 = 0;
    243260        for (;(_index9<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index9))) {
    244261            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index9)])))) /* ?{} */);
     
    246263
    247264    }
     265
    248266}
    249267static inline void ___constructor__F_R9sofstreamPvb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1){
     
    254272    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    255273    {
    256         signed int _index10 = ((signed int )0);
     274        signed int _index10 = 0;
    257275        for (;(_index10<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index10))) {
    258276            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index10)])))) /* ?{} */);
     
    260278
    261279    }
    262     {
    263         signed int _index11 = ((signed int )0);
     280
     281    {
     282        signed int _index11 = 0;
    264283        for (;(_index11<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index11))) {
    265284            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index11)])))) /* ?{} */);
     
    267286
    268287    }
     288
    269289}
    270290static inline void ___constructor__F_R9sofstreamPvbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1){
     
    275295    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    276296    {
    277         signed int _index12 = ((signed int )0);
     297        signed int _index12 = 0;
    278298        for (;(_index12<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index12))) {
    279299            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index12)])))) /* ?{} */);
     
    281301
    282302    }
    283     {
    284         signed int _index13 = ((signed int )0);
     303
     304    {
     305        signed int _index13 = 0;
    285306        for (;(_index13<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index13))) {
    286307            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index13)])))) /* ?{} */);
     
    288309
    289310    }
     311
    290312}
    291313static inline void ___constructor__F_R9sofstreamPvbbb_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1){
     
    296318    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1) /* ?{} */);
    297319    {
    298         signed int _index14 = ((signed int )0);
     320        signed int _index14 = 0;
    299321        for (;(_index14<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index14))) {
    300322            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index14)])))) /* ?{} */);
     
    302324
    303325    }
    304     {
    305         signed int _index15 = ((signed int )0);
     326
     327    {
     328        signed int _index15 = 0;
    306329        for (;(_index15<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index15))) {
    307330            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index15)])))) /* ?{} */);
     
    309332
    310333    }
     334
    311335}
    312336static inline void ___constructor__F_R9sofstreamPvbbbPCc_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1){
     
    317341    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    318342    {
    319         signed int _index16 = ((signed int )0);
     343        signed int _index16 = 0;
    320344        for (;(_index16<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index16))) {
    321345            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index16)])))) /* ?{} */);
     
    323347
    324348    }
    325     {
    326         signed int _index17 = ((signed int )0);
     349
     350    {
     351        signed int _index17 = 0;
    327352        for (;(_index17<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index17))) {
    328353            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index17)])))) /* ?{} */);
     
    330355
    331356    }
     357
    332358}
    333359static inline void ___constructor__F_R9sofstreamPvbbbPCcA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)]){
     
    338364    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    339365    {
    340         signed int _index18 = ((signed int )0);
     366        signed int _index18 = 0;
    341367        for (;(_index18<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index18))) {
    342368            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index18)])))=__separator__A0c_1[((signed long int )_index18)]) /* ?{} */);
     
    344370
    345371    }
    346     {
    347         signed int _index19 = ((signed int )0);
     372
     373    {
     374        signed int _index19 = 0;
    348375        for (;(_index19<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index19))) {
    349376            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index19)])))) /* ?{} */);
     
    351378
    352379    }
     380
    353381}
    354382static inline void ___constructor__F_R9sofstreamPvbbbPCcA0cA0c_autogen___1(struct ofstream *___dst__R9sofstream_1, void *__file__Pv_1, _Bool __sepDefault__b_1, _Bool __sepOnOff__b_1, _Bool __sawNL__b_1, const char *__sepCur__PCc_1, char __separator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)], char __tupleSeparator__A0c_1[((unsigned long int )__sepSize__C13e__anonymous0_1)]){
     
    359387    ((void)((*___dst__R9sofstream_1).__sepCur__PCc_1=__sepCur__PCc_1) /* ?{} */);
    360388    {
    361         signed int _index20 = ((signed int )0);
     389        signed int _index20 = 0;
    362390        for (;(_index20<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index20))) {
    363391            ((void)((*((char *)(&(*___dst__R9sofstream_1).__separator__A0c_1[((signed long int )_index20)])))=__separator__A0c_1[((signed long int )_index20)]) /* ?{} */);
     
    365393
    366394    }
    367     {
    368         signed int _index21 = ((signed int )0);
     395
     396    {
     397        signed int _index21 = 0;
    369398        for (;(_index21<((signed int )__sepSize__C13e__anonymous0_1));((void)(++_index21))) {
    370399            ((void)((*((char *)(&(*___dst__R9sofstream_1).__tupleSeparator__A0c_1[((signed long int )_index21)])))=__tupleSeparator__A0c_1[((signed long int )_index21)]) /* ?{} */);
     
    372401
    373402    }
     403
    374404}
    375405_Bool __sepPrt__Fb_P9sofstream__1(struct ofstream *__anonymous_object1294);
     
    404434static inline void ___destructor__F_R9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1);
    405435static inline struct ifstream ___operator_assign__F9sifstream_R9sifstream9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1, struct ifstream ___src__9sifstream_1);
     436static inline void ___constructor__F_R9sifstreamPv_autogen___1(struct ifstream *___dst__R9sifstream_1, void *__file__Pv_1);
    406437static inline void ___constructor__F_R9sifstream_autogen___1(struct ifstream *___dst__R9sifstream_1){
    407438    ((void)((*___dst__R9sifstream_1).__file__Pv_1) /* ?{} */);
     
    416447    struct ifstream ___ret__9sifstream_1;
    417448    ((void)((*___dst__R9sifstream_1).__file__Pv_1=___src__9sifstream_1.__file__Pv_1));
    418     ((void)___constructor__F_R9sifstream9sifstream_autogen___1((&___ret__9sifstream_1), ___src__9sifstream_1));
    419     return ((struct ifstream )___ret__9sifstream_1);
     449    ((void)___constructor__F_R9sifstream9sifstream_autogen___1((&___ret__9sifstream_1), (*___dst__R9sifstream_1)));
     450    return ___ret__9sifstream_1;
    420451}
    421452static inline void ___constructor__F_R9sifstreamPv_autogen___1(struct ifstream *___dst__R9sifstream_1, void *__file__Pv_1){
     
    708739    ((void)0123456789.e-09L);
    709740    ((void)0123456789.e-09DL);
    710     ((void)(-0123456789.e-09));
    711     ((void)(-0123456789.e-09f));
    712     ((void)(-0123456789.e-09l));
    713     ((void)(-0123456789.e-09F));
    714     ((void)(-0123456789.e-09L));
    715     ((void)(-0123456789.e-09DL));
     741    ((void)(+0123456789.e-09));
     742    ((void)(+0123456789.e-09f));
     743    ((void)(+0123456789.e-09l));
     744    ((void)(+0123456789.e-09F));
     745    ((void)(+0123456789.e-09L));
     746    ((void)(+0123456789.e-09DL));
    716747    ((void)(-0123456789.e-09));
    717748    ((void)(-0123456789.e-09f));
     
    852883    ((void)0123456789.0123456789E-09L);
    853884    ((void)0123456789.0123456789E-09DL);
    854     ((void)(-0123456789.0123456789E-09));
    855     ((void)(-0123456789.0123456789E-09f));
    856     ((void)(-0123456789.0123456789E-09l));
    857     ((void)(-0123456789.0123456789E-09F));
    858     ((void)(-0123456789.0123456789E-09L));
    859     ((void)(-0123456789.0123456789E-09DL));
     885    ((void)(+0123456789.0123456789E-09));
     886    ((void)(+0123456789.0123456789E-09f));
     887    ((void)(+0123456789.0123456789E-09l));
     888    ((void)(+0123456789.0123456789E-09F));
     889    ((void)(+0123456789.0123456789E-09L));
     890    ((void)(+0123456789.0123456789E-09DL));
    860891    ((void)(-0123456789.0123456789E-09));
    861892    ((void)(-0123456789.0123456789E-09f));
     
    899930    ((void)0x0123456789.p-09F);
    900931    ((void)0x0123456789.p-09L);
    901     ((void)(-0x0123456789.p-09));
    902     ((void)(-0x0123456789.p-09f));
    903     ((void)(-0x0123456789.p-09l));
    904     ((void)(-0x0123456789.p-09F));
    905     ((void)(-0x0123456789.p-09L));
     932    ((void)(+0x0123456789.p-09));
     933    ((void)(+0x0123456789.p-09f));
     934    ((void)(+0x0123456789.p-09l));
     935    ((void)(+0x0123456789.p-09F));
     936    ((void)(+0x0123456789.p-09L));
    906937    ((void)(-0x0123456789.p-09));
    907938    ((void)(-0x0123456789.p-09f));
     
    944975    ((void)0x.0123456789P-09F);
    945976    ((void)0x.0123456789P-09L);
    946     ((void)(-0x.0123456789P-09));
    947     ((void)(-0x.0123456789P-09f));
    948     ((void)(-0x.0123456789P-09l));
    949     ((void)(-0x.0123456789P-09F));
    950     ((void)(-0x.0123456789P-09L));
     977    ((void)(+0x.0123456789P-09));
     978    ((void)(+0x.0123456789P-09f));
     979    ((void)(+0x.0123456789P-09l));
     980    ((void)(+0x.0123456789P-09F));
     981    ((void)(+0x.0123456789P-09L));
    951982    ((void)(-0x.0123456789P-09));
    952983    ((void)(-0x.0123456789P-09f));
     
    9891020    ((void)0X0123456789.0123456789P-09F);
    9901021    ((void)0X0123456789.0123456789P-09L);
     1022    ((void)(+0X0123456789.0123456789P-09));
     1023    ((void)(+0X0123456789.0123456789P-09f));
     1024    ((void)(+0X0123456789.0123456789P-09l));
     1025    ((void)(+0X0123456789.0123456789P-09F));
     1026    ((void)(+0X0123456789.0123456789P-09L));
    9911027    ((void)(-0X0123456789.0123456789P-09));
    9921028    ((void)(-0X0123456789.0123456789P-09f));
     
    9941030    ((void)(-0X0123456789.0123456789P-09F));
    9951031    ((void)(-0X0123456789.0123456789P-09L));
    996     ((void)(-0X0123456789.0123456789P-09));
    997     ((void)(-0X0123456789.0123456789P-09f));
    998     ((void)(-0X0123456789.0123456789P-09l));
    999     ((void)(-0X0123456789.0123456789P-09F));
    1000     ((void)(-0X0123456789.0123456789P-09L));
     1032    ((void)((signed char )01234567));
     1033    ((void)((signed short int )01234567));
     1034    ((void)((signed int )01234567));
     1035    ((void)((signed long int )01234567));
     1036    ((void)((__int128 )01234567));
     1037    ((void)((unsigned char )01234567u));
     1038    ((void)((signed short int )01234567u));
     1039    ((void)((unsigned int )01234567u));
     1040    ((void)((signed long int )01234567u));
     1041    ((void)((__int128 )01234567u));
     1042    ((void)(+((signed int )((signed char )01234567))));
     1043    ((void)(+((signed int )((signed short int )01234567))));
     1044    ((void)(+((signed int )01234567)));
     1045    ((void)(+((signed long int )01234567)));
     1046    ((void)(+((float )((__int128 )01234567))));
     1047    ((void)(+((signed int )((unsigned char )01234567u))));
     1048    ((void)(+((signed int )((signed short int )01234567u))));
     1049    ((void)(+((unsigned int )01234567u)));
     1050    ((void)(+((signed long int )01234567u)));
     1051    ((void)(+((float )((__int128 )01234567u))));
     1052    ((void)(-((signed int )((signed char )01234567))));
     1053    ((void)(-((signed int )((signed short int )01234567))));
     1054    ((void)(-((signed int )01234567)));
     1055    ((void)(-((signed long int )01234567)));
     1056    ((void)(-((float )((__int128 )01234567))));
     1057    ((void)(-((signed int )((unsigned char )01234567u))));
     1058    ((void)(-((signed int )((signed short int )01234567u))));
     1059    ((void)(-((unsigned int )01234567u)));
     1060    ((void)(-((signed long int )01234567u)));
     1061    ((void)(-((float )((__int128 )01234567u))));
     1062    ((void)((signed char )1234567890));
     1063    ((void)((signed short int )1234567890));
     1064    ((void)((signed int )1234567890));
     1065    ((void)((signed long int )1234567890));
     1066    ((void)((__int128 )1234567890));
     1067    ((void)((signed char )1234567890U));
     1068    ((void)((unsigned short int )1234567890U));
     1069    ((void)((signed int )1234567890U));
     1070    ((void)((unsigned long int )1234567890u));
     1071    ((void)((unsigned __int128 )1234567890u));
     1072    ((void)(+((signed int )((signed char )1234567890))));
     1073    ((void)(+((signed int )((signed short int )1234567890))));
     1074    ((void)(+((signed int )1234567890)));
     1075    ((void)(+((signed long int )1234567890)));
     1076    ((void)(+((float )((__int128 )1234567890))));
     1077    ((void)(+((signed int )((signed char )1234567890U))));
     1078    ((void)(+((signed int )((unsigned short int )1234567890U))));
     1079    ((void)(+((signed int )1234567890U)));
     1080    ((void)(+((unsigned long int )1234567890u)));
     1081    ((void)(+((float )((unsigned __int128 )1234567890u))));
     1082    ((void)(-((signed int )((signed char )1234567890))));
     1083    ((void)(-((signed int )((signed short int )1234567890))));
     1084    ((void)(-((signed int )1234567890)));
     1085    ((void)(-((signed long int )1234567890)));
     1086    ((void)(-((float )((__int128 )1234567890))));
     1087    ((void)(-((signed int )((signed char )1234567890U))));
     1088    ((void)(-((signed int )((unsigned short int )1234567890U))));
     1089    ((void)(-((signed int )1234567890U)));
     1090    ((void)(-((unsigned long int )1234567890u)));
     1091    ((void)(-((float )((unsigned __int128 )1234567890u))));
     1092    ((void)((signed char )0x0123456789abcdef));
     1093    ((void)((signed short int )0x0123456789abcdef));
     1094    ((void)((signed int )0x0123456789abcdef));
     1095    ((void)((signed long int )0x0123456789abcdef));
     1096    ((void)((signed char )0x0123456789abcdefu));
     1097    ((void)((unsigned short int )0x0123456789abcdefu));
     1098    ((void)((signed int )0x0123456789abcdefu));
     1099    ((void)((unsigned long int )0x0123456789abcdefu));
     1100    ((void)(+((signed int )((signed char )0x0123456789abcdef))));
     1101    ((void)(+((signed int )((signed short int )0x0123456789abcdef))));
     1102    ((void)(+((signed int )0x0123456789abcdef)));
     1103    ((void)(+((signed long int )0x0123456789abcdef)));
     1104    ((void)(+((signed int )((signed char )0x0123456789abcdefu))));
     1105    ((void)(+((signed int )((unsigned short int )0x0123456789abcdefu))));
     1106    ((void)(+((signed int )0x0123456789abcdefu)));
     1107    ((void)(+((unsigned long int )0x0123456789abcdefu)));
     1108    ((void)(-((signed int )((signed char )0x0123456789abcdef))));
     1109    ((void)(-((signed int )((signed short int )0x0123456789abcdef))));
     1110    ((void)(-((signed int )0x0123456789abcdef)));
     1111    ((void)(-((signed long int )0x0123456789abcdef)));
     1112    ((void)(-((signed int )((signed char )0x0123456789abcdefu))));
     1113    ((void)(-((signed int )((unsigned short int )0x0123456789abcdefu))));
     1114    ((void)(-((signed int )0x0123456789abcdefu)));
     1115    ((void)(-((unsigned long int )0x0123456789abcdefu)));
     1116    ((void)((signed char )0x0123456789ABCDEF));
     1117    ((void)((signed short int )0x0123456789ABCDEF));
     1118    ((void)((signed int )0x0123456789ABCDEF));
     1119    ((void)((signed long int )0x0123456789ABCDEF));
     1120    ((void)((signed char )0x0123456789ABCDEFu));
     1121    ((void)((unsigned short int )0x0123456789ABCDEFu));
     1122    ((void)((signed int )0x0123456789ABCDEFu));
     1123    ((void)((unsigned long int )0x0123456789ABCDEFu));
     1124    ((void)(+((signed int )((signed char )0x0123456789ABCDEF))));
     1125    ((void)(+((signed int )((signed short int )0x0123456789ABCDEF))));
     1126    ((void)(+((signed int )0x0123456789ABCDEF)));
     1127    ((void)(+((signed long int )0x0123456789ABCDEF)));
     1128    ((void)(+((signed int )((signed char )0x0123456789ABCDEFu))));
     1129    ((void)(+((signed int )((unsigned short int )0x0123456789ABCDEFu))));
     1130    ((void)(+((signed int )0x0123456789ABCDEFu)));
     1131    ((void)(+((unsigned long int )0x0123456789ABCDEFu)));
     1132    ((void)(-((signed int )((signed char )0x0123456789ABCDEF))));
     1133    ((void)(-((signed int )((signed short int )0x0123456789ABCDEF))));
     1134    ((void)(-((signed int )0x0123456789ABCDEF)));
     1135    ((void)(-((signed long int )0x0123456789ABCDEF)));
     1136    ((void)(-((signed int )((signed char )0x0123456789ABCDEFu))));
     1137    ((void)(-((signed int )((unsigned short int )0x0123456789ABCDEFu))));
     1138    ((void)(-((signed int )0x0123456789ABCDEFu)));
     1139    ((void)(-((unsigned long int )0x0123456789ABCDEFu)));
     1140    ((void)((signed char )0X0123456789abcdef));
     1141    ((void)((signed short int )0X0123456789abcdef));
     1142    ((void)((signed int )0X0123456789abcdef));
     1143    ((void)((signed long int )0X0123456789abcdef));
     1144    ((void)((signed char )0X0123456789abcdefu));
     1145    ((void)((unsigned short int )0X0123456789abcdefu));
     1146    ((void)((signed int )0X0123456789abcdefu));
     1147    ((void)((unsigned long int )0X0123456789abcdefu));
     1148    ((void)(+((signed int )((signed char )0X0123456789abcdef))));
     1149    ((void)(+((signed int )((signed short int )0X0123456789abcdef))));
     1150    ((void)(+((signed int )0X0123456789abcdef)));
     1151    ((void)(+((signed long int )0X0123456789abcdef)));
     1152    ((void)(+((signed int )((signed char )0X0123456789abcdefu))));
     1153    ((void)(+((signed int )((unsigned short int )0X0123456789abcdefu))));
     1154    ((void)(+((signed int )0X0123456789abcdefu)));
     1155    ((void)(+((unsigned long int )0X0123456789abcdefu)));
     1156    ((void)(-((signed int )((signed char )0X0123456789abcdef))));
     1157    ((void)(-((signed int )((signed short int )0X0123456789abcdef))));
     1158    ((void)(-((signed int )0X0123456789abcdef)));
     1159    ((void)(-((signed long int )0X0123456789abcdef)));
     1160    ((void)(-((signed int )((signed char )0X0123456789abcdefu))));
     1161    ((void)(-((signed int )((unsigned short int )0X0123456789abcdefu))));
     1162    ((void)(-((signed int )0X0123456789abcdefu)));
     1163    ((void)(-((unsigned long int )0X0123456789abcdefu)));
     1164    ((void)((signed char )0X0123456789ABCDEF));
     1165    ((void)((signed short int )0X0123456789ABCDEF));
     1166    ((void)((signed int )0X0123456789ABCDEF));
     1167    ((void)((signed long int )0X0123456789ABCDEF));
     1168    ((void)((signed char )0X0123456789ABCDEFu));
     1169    ((void)((unsigned short int )0X0123456789ABCDEFu));
     1170    ((void)((signed int )0X0123456789ABCDEFu));
     1171    ((void)((unsigned long int )0X0123456789ABCDEFu));
     1172    ((void)(+((signed int )((signed char )0X0123456789ABCDEF))));
     1173    ((void)(+((signed int )((signed short int )0X0123456789ABCDEF))));
     1174    ((void)(+((signed int )0X0123456789ABCDEF)));
     1175    ((void)(+((signed long int )0X0123456789ABCDEF)));
     1176    ((void)(+((signed int )((signed char )0X0123456789ABCDEFu))));
     1177    ((void)(+((signed int )((unsigned short int )0X0123456789ABCDEFu))));
     1178    ((void)(+((signed int )0X0123456789ABCDEFu)));
     1179    ((void)(+((unsigned long int )0X0123456789ABCDEFu)));
     1180    ((void)(-((signed int )((signed char )0X0123456789ABCDEF))));
     1181    ((void)(-((signed int )((signed short int )0X0123456789ABCDEF))));
     1182    ((void)(-((signed int )0X0123456789ABCDEF)));
     1183    ((void)(-((signed long int )0X0123456789ABCDEF)));
     1184    ((void)(-((signed int )((signed char )0X0123456789ABCDEFu))));
     1185    ((void)(-((signed int )((unsigned short int )0X0123456789ABCDEFu))));
     1186    ((void)(-((signed int )0X0123456789ABCDEFu)));
     1187    ((void)(-((unsigned long int )0X0123456789ABCDEFu)));
     1188    ((void)((float )0123456789.));
     1189    ((void)((double )0123456789.));
     1190    ((void)((long double )0123456789.));
     1191    ((void)((long double )0123456789.));
     1192    ((void)(+((float )0123456789.)));
     1193    ((void)(+((double )0123456789.)));
     1194    ((void)(+((long double )0123456789.)));
     1195    ((void)(+((long double )0123456789.)));
     1196    ((void)(-((float )0123456789.)));
     1197    ((void)(-((double )0123456789.)));
     1198    ((void)(-((long double )0123456789.)));
     1199    ((void)(-((long double )0123456789.)));
     1200    ((void)((float )0123456789.e09));
     1201    ((void)((double )0123456789.e09));
     1202    ((void)((long double )0123456789.e09));
     1203    ((void)((long double )0123456789.e09));
     1204    ((void)(+((float )0123456789.e+09)));
     1205    ((void)(+((double )0123456789.e+09)));
     1206    ((void)(+((long double )0123456789.e+09)));
     1207    ((void)(+((long double )0123456789.e+09)));
     1208    ((void)(-((float )0123456789.e-09)));
     1209    ((void)(-((double )0123456789.e-09)));
     1210    ((void)(-((long double )0123456789.e-09)));
     1211    ((void)(-((long double )0123456789.e-09)));
     1212    ((void)((float ).0123456789e09));
     1213    ((void)((double ).0123456789e09));
     1214    ((void)((long double ).0123456789e09));
     1215    ((void)((long double ).0123456789e09));
     1216    ((void)(+((float ).0123456789E+09)));
     1217    ((void)(+((double ).0123456789E+09)));
     1218    ((void)(+((long double ).0123456789E+09)));
     1219    ((void)(+((long double ).0123456789E+09)));
     1220    ((void)(-((float ).0123456789E-09)));
     1221    ((void)(-((double ).0123456789E-09)));
     1222    ((void)(-((long double ).0123456789E-09)));
     1223    ((void)(-((long double ).0123456789E-09)));
     1224    ((void)((float )0123456789.0123456789));
     1225    ((void)((double )0123456789.0123456789));
     1226    ((void)((long double )0123456789.0123456789));
     1227    ((void)((long double )0123456789.0123456789));
     1228    ((void)(+((float )0123456789.0123456789E09)));
     1229    ((void)(+((double )0123456789.0123456789E09)));
     1230    ((void)(+((long double )0123456789.0123456789E09)));
     1231    ((void)(+((long double )0123456789.0123456789E09)));
     1232    ((void)(-((float )0123456789.0123456789E+09)));
     1233    ((void)(-((double )0123456789.0123456789E+09)));
     1234    ((void)(-((long double )0123456789.0123456789E+09)));
     1235    ((void)(-((long double )0123456789.0123456789E+09)));
     1236    ((void)((float )0123456789.0123456789E-09));
     1237    ((void)((double )0123456789.0123456789E-09));
     1238    ((void)((long double )0123456789.0123456789E-09));
     1239    ((void)((long double )0123456789.0123456789E-09));
     1240    ((void)((float )0x0123456789.p09));
     1241    ((void)((double )0x0123456789.p09));
     1242    ((void)((long double )0x0123456789.p09));
     1243    ((void)((long double )0x0123456789.p09));
     1244    ((void)(+((float )0x0123456789.p09)));
     1245    ((void)(+((double )0x0123456789.p09)));
     1246    ((void)(+((long double )0x0123456789.p09)));
     1247    ((void)(+((long double )0x0123456789.p09)));
     1248    ((void)(-((float )0x0123456789.p09)));
     1249    ((void)(-((double )0x0123456789.p09)));
     1250    ((void)(-((long double )0x0123456789.p09)));
     1251    ((void)(-((long double )0x0123456789.p09)));
     1252    ((void)((float )0x0123456789.p+09));
     1253    ((void)((double )0x0123456789.p+09));
     1254    ((void)((long double )0x0123456789.p+09));
     1255    ((void)((long double )0x0123456789.p+09));
     1256    ((void)(+((float )0x0123456789.p-09)));
     1257    ((void)(+((double )0x0123456789.p-09)));
     1258    ((void)(+((long double )0x0123456789.p-09)));
     1259    ((void)(+((long double )0x0123456789.p-09)));
     1260    ((void)(-((float )0x.0123456789p09)));
     1261    ((void)(-((double )0x.0123456789p09)));
     1262    ((void)(-((long double )0x.0123456789p09)));
     1263    ((void)(-((long double )0x.0123456789p09)));
    10011264    ((void)__f__F_c__1('a'));
    10021265    ((void)__f__F_Sc__1(20));
     
    11111374    ((void)L"a" "b" "c");
    11121375    ((void)(___retval_main__i_1=0) /* ?{} */);
    1113     return ((signed int )___retval_main__i_1);
     1376    return ___retval_main__i_1;
    11141377}
    11151378static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return __main__Fi___1(); }
     
    11261389    ((void)(___retval_main__i_1=(((void)(_tmp_cp_ret0=invoke_main(__argc__i_1, __argv__PPc_1, __envp__PPc_1))) , _tmp_cp_ret0)) /* ?{} */);
    11271390    ((void)(_tmp_cp_ret0) /* ^?{} */);
    1128     return ((signed int )___retval_main__i_1);
    1129 }
     1391    return ___retval_main__i_1;
     1392}
  • src/tests/.expect/castError.txt

    rb96ec83 r6840e7c  
    1 castError.c:7:1 error: Cannot choose between 3 alternatives for expression Cast of:
     1castError.c:7:1 error: Cannot choose between 3 alternatives for expression
     2Cast of:
    23  Name: f
     4... to:
     5  charAlternatives are:
     6Cost ( 1, 0, 0, 0 ): Cast of:
     7     Variable Expression: f: function
     8       accepting unspecified arguments
     9     ... returning nothing
    310
    4 to:
    5   char
    6 Alternatives are:        Cost ( 1, 0, 0, 0 ): Cast of:
    7           Variable Expression: f: function
    8                 accepting unspecified arguments
    9               returning
    10                 nothing
     11   ... to:
     12     char
     13 (types:
     14   char
     15 )
     16 Environment:
     17
     18Cost ( 1, 0, 0, 0 ): Cast of:
     19     Variable Expression: f: signed int
     20   ... to:
     21     char
     22 (types:
     23   char
     24 )
     25 Environment:
     26
     27Cost ( 1, 0, 0, 0 ): Cast of:
     28     Variable Expression: f: double
     29   ... to:
     30     char
     31 (types:
     32   char
     33 )
     34 Environment:
    1135
    1236
    13         to:
    14           char
    15 (types:
    16             char
    17 )
    18         Environment:
    19 
    20         Cost ( 1, 0, 0, 0 ): Cast of:
    21           Variable Expression: f: signed int
    22 
    23         to:
    24           char
    25 (types:
    26             char
    27 )
    28         Environment:
    29 
    30         Cost ( 1, 0, 0, 0 ): Cast of:
    31           Variable Expression: f: double
    32 
    33         to:
    34           char
    35 (types:
    36             char
    37 )
    38         Environment:
    39 
    40 
  • src/tests/.expect/scopeErrors.txt

    rb96ec83 r6840e7c  
    11scopeErrors.c:2:1 error: duplicate object definition for thisIsAnError: signed int
    22scopeErrors.c:20:1 error: duplicate function definition for butThisIsAnError: function
    3   with parameters
    4     double
    5   returning
    6     _retval_butThisIsAnError:       Attribute with name: unused
    7 double
    8   with body
    9     CompoundStmt
     3... with parameters
     4  double
     5... returning
     6  _retval_butThisIsAnError: double
     7  ... with attributes:
     8    Attribute with name: unused
    109
     10... with body
     11  CompoundStmt
     12
  • src/tests/Makefile.am

    rb96ec83 r6840e7c  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Sep 11 16:17:16 2017
    14 ## Update Count     : 45
     13## Last Modified On : Tue Oct 10 14:04:40 2017
     14## Update Count     : 47
    1515###############################################################################
    1616
     
    2222concurrent = yes
    2323quick_test += coroutine thread monitor
    24 concurrent_test = coroutine thread monitor multi-monitor sched-int-barge sched-int-block sched-int-disjoint sched-int-wait sched-ext sched-ext-multi preempt
     24concurrent_test =               \
     25        coroutine               \
     26        fmtLines                \
     27        pingpong                \
     28        prodcons                \
     29        thread                  \
     30        matrixSum               \
     31        monitor                 \
     32        multi-monitor           \
     33        boundedBuffer           \
     34        preempt                 \
     35        sched-int-block         \
     36        sched-int-disjoint      \
     37        sched-int-wait          \
     38        sched-ext-barge         \
     39        sched-ext-dtor          \
     40        sched-ext-else          \
     41        sched-ext-parse         \
     42        sched-ext-recurse       \
     43        sched-ext-statment      \
     44        sched-ext-when
    2545else
    2646concurrent=no
     
    113133        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    114134
     135ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
     136        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     137
    115138completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@
    116139        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
  • src/tests/Makefile.in

    rb96ec83 r6840e7c  
    320320@BUILD_CONCURRENCY_TRUE@concurrent = yes
    321321@BUILD_CONCURRENCY_FALSE@concurrent_test =
    322 @BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int-barge sched-int-block sched-int-disjoint sched-int-wait sched-ext sched-ext-multi preempt
     322@BUILD_CONCURRENCY_TRUE@concurrent_test = \
     323@BUILD_CONCURRENCY_TRUE@        coroutine               \
     324@BUILD_CONCURRENCY_TRUE@        fmtLines                \
     325@BUILD_CONCURRENCY_TRUE@        pingpong                \
     326@BUILD_CONCURRENCY_TRUE@        prodcons                \
     327@BUILD_CONCURRENCY_TRUE@        thread                  \
     328@BUILD_CONCURRENCY_TRUE@        matrixSum               \
     329@BUILD_CONCURRENCY_TRUE@        monitor                 \
     330@BUILD_CONCURRENCY_TRUE@        multi-monitor           \
     331@BUILD_CONCURRENCY_TRUE@        boundedBuffer           \
     332@BUILD_CONCURRENCY_TRUE@        preempt                 \
     333@BUILD_CONCURRENCY_TRUE@        sched-int-block         \
     334@BUILD_CONCURRENCY_TRUE@        sched-int-disjoint      \
     335@BUILD_CONCURRENCY_TRUE@        sched-int-wait          \
     336@BUILD_CONCURRENCY_TRUE@        sched-ext-barge         \
     337@BUILD_CONCURRENCY_TRUE@        sched-ext-dtor          \
     338@BUILD_CONCURRENCY_TRUE@        sched-ext-else          \
     339@BUILD_CONCURRENCY_TRUE@        sched-ext-parse         \
     340@BUILD_CONCURRENCY_TRUE@        sched-ext-recurse       \
     341@BUILD_CONCURRENCY_TRUE@        sched-ext-statment      \
     342@BUILD_CONCURRENCY_TRUE@        sched-ext-when
     343
    323344
    324345# applies to both programs
     
    865886        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    866887
     888ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@
     889        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
     890
    867891completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@
    868892        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
  • src/tests/coroutine.c

    rb96ec83 r6840e7c  
    1010// Created On       : Thu Jun  8 07:29:37 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  8 07:37:12 2017
    13 // Update Count     : 5
     12// Last Modified On : Sun Sep 17 21:38:15 2017
     13// Update Count     : 7
    1414//
    1515
     
    1818
    1919coroutine Fibonacci {
    20         int fn;                                         // used for communication
     20        int fn;                                                                                         // used for communication
    2121};
    2222
     
    2626
    2727void main( Fibonacci & this ) {
    28         int fn1, fn2;                                   // retained between resumes
    29         this.fn = 0;                                    // case 0
     28        int fn1, fn2;                                                                           // retained between resumes
     29        this.fn = 0;                                                                            // case 0
    3030        fn1 = this.fn;
    31         suspend();                                              // return to last resume
     31        suspend();                                                                                      // restart last resume
    3232
    33         this.fn = 1;                                    // case 1
    34         fn2 = fn1;
    35         fn1 = this.fn;
    36         suspend();                                              // return to last resume
     33        this.fn = 1;                                                                            // case 1
     34        fn2 = fn1;  fn1 = this.fn;
     35        suspend();                                                                                      // restart last resume
    3736
    38         for ( ;; ) {                                    // general case
     37        for ( ;; ) {                                                                            // general case
    3938                this.fn = fn1 + fn2;
    40                 fn2 = fn1;
    41                 fn1 = this.fn;
    42                 suspend();                                      // return to last resume
     39                fn2 = fn1;  fn1 = this.fn;
     40                suspend();                                                                              // restart last resume
    4341        } // for
    4442}
    4543
    4644int next( Fibonacci & this ) {
    47         resume( this );                                 // transfer to last suspend
     45        resume( this );                                                                         // restart last suspend
    4846        return this.fn;
    4947}
     
    5250        Fibonacci f1, f2;
    5351        for ( int i = 1; i <= 10; i += 1 ) {
    54                 sout | next( f1 ) | ' ' | next( f2 ) | endl;
     52                sout | next( f1 ) | next( f2 ) | endl;
    5553        } // for
    5654}
  • src/tests/fmtLines.c

    rb96ec83 r6840e7c  
    1010// Created On       : Sun Sep 17 21:56:15 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 18 11:35:57 2017
    13 // Update Count     : 31
     12// Last Modified On : Sun Oct  1 11:57:19 2017
     13// Update Count     : 34
    1414//
    1515
     
    2323
    2424void ?{}( Format & fmt ) {
    25     resume( fmt );                                                                              // start coroutine
     25        resume( fmt );                                                                          // prime (start) coroutine
    2626}
    2727
    2828void ^?{}( Format & fmt ) {
    29     if ( fmt.g != 0 || fmt.b != 0 ) sout | endl;
     29        if ( fmt.g != 0 || fmt.b != 0 ) sout | endl;
    3030}
    3131
     
    4747
    4848void prt( Format & fmt, char ch ) {
    49     fmt.ch = ch;
    50     resume( fmt );
     49        fmt.ch = ch;
     50        resume( fmt );
    5151} // prt
    5252
    5353int main() {
    54         Format fmt;
     54        Format fmt;                                                                                     // format characters into blocks of 4 and groups of 5 blocks per line
    5555        char ch;
    5656
    57         for ( ;; ) {
     57        Eof: for ( ;; ) {                                                                       // read until end of file
    5858                sin | ch;                                                                               // read one character
    59           if ( eof( sin ) ) break;                                                      // eof ?
    60                 prt( fmt, ch );
     59          if ( eof( sin ) ) break Eof;                                          // eof ?
     60                prt( fmt, ch );                                                                 // push character for formatting
    6161        } // for
    6262} // main
  • src/tests/gmp.c

    rb96ec83 r6840e7c  
    1010// Created On       : Tue Apr 19 08:55:51 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep  4 09:51:18 2017
    13 // Update Count     : 550
     12// Last Modified On : Thu Sep 28 18:33:51 2017
     13// Update Count     : 555
    1414//
    1515
     
    9797
    9898        sout | "Factorial Numbers" | endl;
    99         Int fact;
    100         fact = 1;                                                                                       // 1st case
     99        Int fact = 1;                                                                           // 1st case
    101100        sout | (int)0 | fact | endl;
    102101        for ( unsigned int i = 1; i <= 40; i += 1 ) {
  • src/tests/literals.c

    rb96ec83 r6840e7c  
    1010// Created On       : Sat Sep  9 16:34:38 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Sep 12 07:45:46 2017
    13 // Update Count     : 88
     12// Last Modified On : Mon Sep 25 20:26:00 2017
     13// Update Count     : 132
    1414//
    1515
    1616#ifdef __CFA__
     17#include <stdint.h>
    1718#include <fstream>
    1819
     
    7273
    7374         0123456789.e-09;   0123456789.e-09f;   0123456789.e-09l;   0123456789.e-09F;   0123456789.e-09L;   0123456789.e-09DL;
    74         -0123456789.e-09;  -0123456789.e-09f;  -0123456789.e-09l;  -0123456789.e-09F;  -0123456789.e-09L;  -0123456789.e-09DL;
     75        +0123456789.e-09;  +0123456789.e-09f;  +0123456789.e-09l;  +0123456789.e-09F;  +0123456789.e-09L;  +0123456789.e-09DL;
    7576        -0123456789.e-09;  -0123456789.e-09f;  -0123456789.e-09l;  -0123456789.e-09F;  -0123456789.e-09L;  -0123456789.e-09DL;
    7677
     
    104105
    105106         0123456789.0123456789E-09;   0123456789.0123456789E-09f;   0123456789.0123456789E-09l;   0123456789.0123456789E-09F;   0123456789.0123456789E-09L;   0123456789.0123456789E-09DL;
    106         -0123456789.0123456789E-09;  -0123456789.0123456789E-09f;  -0123456789.0123456789E-09l;  -0123456789.0123456789E-09F;  -0123456789.0123456789E-09L;  -0123456789.0123456789E-09DL;
     107        +0123456789.0123456789E-09;  +0123456789.0123456789E-09f;  +0123456789.0123456789E-09l;  +0123456789.0123456789E-09F;  +0123456789.0123456789E-09L;  +0123456789.0123456789E-09DL;
    107108        -0123456789.0123456789E-09;  -0123456789.0123456789E-09f;  -0123456789.0123456789E-09l;  -0123456789.0123456789E-09F;  -0123456789.0123456789E-09L;  -0123456789.0123456789E-09DL;
    108109
     
    118119
    119120         0x0123456789.p-09;   0x0123456789.p-09f;   0x0123456789.p-09l;   0x0123456789.p-09F;   0x0123456789.p-09L;
    120         -0x0123456789.p-09;  -0x0123456789.p-09f;  -0x0123456789.p-09l;  -0x0123456789.p-09F;  -0x0123456789.p-09L;
     121        +0x0123456789.p-09;  +0x0123456789.p-09f;  +0x0123456789.p-09l;  +0x0123456789.p-09F;  +0x0123456789.p-09L;
    121122        -0x0123456789.p-09;  -0x0123456789.p-09f;  -0x0123456789.p-09l;  -0x0123456789.p-09F;  -0x0123456789.p-09L;
    122123
     
    130131
    131132         0x.0123456789P-09;   0x.0123456789P-09f;   0x.0123456789P-09l;   0x.0123456789P-09F;   0x.0123456789P-09L;
    132         -0x.0123456789P-09;  -0x.0123456789P-09f;  -0x.0123456789P-09l;  -0x.0123456789P-09F;  -0x.0123456789P-09L;
     133        +0x.0123456789P-09;  +0x.0123456789P-09f;  +0x.0123456789P-09l;  +0x.0123456789P-09F;  +0x.0123456789P-09L;
    133134        -0x.0123456789P-09;  -0x.0123456789P-09f;  -0x.0123456789P-09l;  -0x.0123456789P-09F;  -0x.0123456789P-09L;
    134135
     
    142143
    143144         0X0123456789.0123456789P-09;   0X0123456789.0123456789P-09f;   0X0123456789.0123456789P-09l;   0X0123456789.0123456789P-09F;   0X0123456789.0123456789P-09L;
     145        +0X0123456789.0123456789P-09;  +0X0123456789.0123456789P-09f;  +0X0123456789.0123456789P-09l;  +0X0123456789.0123456789P-09F;  +0X0123456789.0123456789P-09L;
    144146        -0X0123456789.0123456789P-09;  -0X0123456789.0123456789P-09f;  -0X0123456789.0123456789P-09l;  -0X0123456789.0123456789P-09F;  -0X0123456789.0123456789P-09L;
    145         -0X0123456789.0123456789P-09;  -0X0123456789.0123456789P-09f;  -0X0123456789.0123456789P-09l;  -0X0123456789.0123456789P-09F;  -0X0123456789.0123456789P-09L;
     147
     148#ifdef __CFA__
     149// fixed-size length
     150
     151        // octal
     152         01234567_l8;   01234567_l16;   01234567_l32;   01234567_l64;   01234567_l128;   01234567_l8u;   01234567_ul16;   01234567_l32u;   01234567_ul64;   01234567_ul128;
     153        +01234567_l8;  +01234567_l16;  +01234567_l32;  +01234567_l64;  +01234567_l128;  +01234567_l8u;  +01234567_ul16;  +01234567_l32u;  +01234567_ul64;  +01234567_ul128;
     154        -01234567_l8;  -01234567_l16;  -01234567_l32;  -01234567_l64;  -01234567_l128;  -01234567_l8u;  -01234567_ul16;  -01234567_l32u;  -01234567_ul64;  -01234567_ul128;
     155
     156        // decimal
     157         1234567890L8;   1234567890L16;   1234567890l32;   1234567890l64;   1234567890l128;   1234567890UL8;   1234567890L16U;   1234567890Ul32;   1234567890l64u;   1234567890l128u;
     158        +1234567890L8;  +1234567890L16;  +1234567890l32;  +1234567890l64;  +1234567890l128;  +1234567890UL8;  +1234567890L16U;  +1234567890Ul32;  +1234567890l64u;  +1234567890l128u;
     159        -1234567890L8;  -1234567890L16;  -1234567890l32;  -1234567890l64;  -1234567890l128;  -1234567890UL8;  -1234567890L16U;  -1234567890Ul32;  -1234567890l64u;  -1234567890l128u;
     160
     161        // hexadecimal
     162         0x0123456789abcdef_l8;   0x0123456789abcdef_l16;   0x0123456789abcdefl32;   0x0123456789abcdefl64;   0x0123456789abcdef_ul8;   0x0123456789abcdef_l16u;   0x0123456789abcdeful32;   0x0123456789abcdefl64u;
     163        +0x0123456789abcdef_l8;  +0x0123456789abcdef_l16;  +0x0123456789abcdefl32;  +0x0123456789abcdefl64;  +0x0123456789abcdef_ul8;  +0x0123456789abcdef_l16u;  +0x0123456789abcdeful32;  +0x0123456789abcdefl64u;
     164        -0x0123456789abcdef_l8;  -0x0123456789abcdef_l16;  -0x0123456789abcdefl32;  -0x0123456789abcdefl64;  -0x0123456789abcdef_ul8;  -0x0123456789abcdef_l16u;  -0x0123456789abcdeful32;  -0x0123456789abcdefl64u;
     165
     166         0x0123456789ABCDEF_l8;   0x0123456789ABCDEF_l16;   0x0123456789ABCDEFl32;   0x0123456789ABCDEFl64;   0x0123456789ABCDEF_ul8;   0x0123456789ABCDEF_l16u;   0x0123456789ABCDEFul32;   0x0123456789ABCDEFl64u;
     167        +0x0123456789ABCDEF_l8;  +0x0123456789ABCDEF_l16;  +0x0123456789ABCDEFl32;  +0x0123456789ABCDEFl64;  +0x0123456789ABCDEF_ul8;  +0x0123456789ABCDEF_l16u;  +0x0123456789ABCDEFul32;  +0x0123456789ABCDEFl64u;
     168        -0x0123456789ABCDEF_l8;  -0x0123456789ABCDEF_l16;  -0x0123456789ABCDEFl32;  -0x0123456789ABCDEFl64;  -0x0123456789ABCDEF_ul8;  -0x0123456789ABCDEF_l16u;  -0x0123456789ABCDEFul32;  -0x0123456789ABCDEFl64u;
     169
     170         0X0123456789abcdef_l8;   0X0123456789abcdef_l16;   0X0123456789abcdefl32;   0X0123456789abcdefl64;   0X0123456789abcdef_ul8;   0X0123456789abcdef_l16u;   0X0123456789abcdeful32;   0X0123456789abcdefl64u;
     171        +0X0123456789abcdef_l8;  +0X0123456789abcdef_l16;  +0X0123456789abcdefl32;  +0X0123456789abcdefl64;  +0X0123456789abcdef_ul8;  +0X0123456789abcdef_l16u;  +0X0123456789abcdeful32;  +0X0123456789abcdefl64u;
     172        -0X0123456789abcdef_l8;  -0X0123456789abcdef_l16;  -0X0123456789abcdefl32;  -0X0123456789abcdefl64;  -0X0123456789abcdef_ul8;  -0X0123456789abcdef_l16u;  -0X0123456789abcdeful32;  -0X0123456789abcdefl64u;
     173
     174         0X0123456789ABCDEF_l8;   0X0123456789ABCDEF_l16;   0X0123456789ABCDEFl32;   0X0123456789ABCDEFl64;   0X0123456789ABCDEF_ul8;   0X0123456789ABCDEF_l16u;   0X0123456789ABCDEFul32;   0X0123456789ABCDEFl64u;
     175        +0X0123456789ABCDEF_l8;  +0X0123456789ABCDEF_l16;  +0X0123456789ABCDEFl32;  +0X0123456789ABCDEFl64;  +0X0123456789ABCDEF_ul8;  +0X0123456789ABCDEF_l16u;  +0X0123456789ABCDEFul32;  +0X0123456789ABCDEFl64u;
     176        -0X0123456789ABCDEF_l8;  -0X0123456789ABCDEF_l16;  -0X0123456789ABCDEFl32;  -0X0123456789ABCDEFl64;  -0X0123456789ABCDEF_ul8;  -0X0123456789ABCDEF_l16u;  -0X0123456789ABCDEFul32;  -0X0123456789ABCDEFl64u;
     177
     178        // floating
     179         0123456789.l32;   0123456789.l64;   0123456789.l80;   0123456789.l128;
     180        +0123456789.l32;  +0123456789.l64;  +0123456789.l80;  +0123456789.l128;
     181        -0123456789.l32;  -0123456789.l64;  -0123456789.l80;  -0123456789.l128;
     182
     183         0123456789.e09L32;    0123456789.e09L64;    0123456789.e09L80;    0123456789.e09L128;
     184        +0123456789.e+09L32;  +0123456789.e+09L64;  +0123456789.e+09L80;  +0123456789.e+09L128;
     185        -0123456789.e-09L32;  -0123456789.e-09L64;  -0123456789.e-09L80;  -0123456789.e-09L128;
     186
     187         .0123456789e09L32;    .0123456789e09L64;    .0123456789e09L80;    .0123456789e09L128;
     188        +.0123456789E+09L32;  +.0123456789E+09L64;  +.0123456789E+09L80;  +.0123456789E+09L128;
     189        -.0123456789E-09L32;  -.0123456789E-09L64;  -.0123456789E-09L80;  -.0123456789E-09L128;
     190
     191         0123456789.0123456789L32;       0123456789.0123456789L64;       0123456789.0123456789L80;       0123456789.0123456789L128;
     192        +0123456789.0123456789E09L32;   +0123456789.0123456789E09L64;   +0123456789.0123456789E09L80;   +0123456789.0123456789E09L128;
     193        -0123456789.0123456789E+09L32;  -0123456789.0123456789E+09L64;  -0123456789.0123456789E+09L80;  -0123456789.0123456789E+09L128;
     194         0123456789.0123456789E-09L32;   0123456789.0123456789E-09L64;   0123456789.0123456789E-09L80;   0123456789.0123456789E-09L128;
     195       
     196         0x0123456789.p09l32;   0x0123456789.p09l64;   0x0123456789.p09l80;   0x0123456789.p09l128;
     197        +0x0123456789.p09l32;  +0x0123456789.p09l64;  +0x0123456789.p09l80;  +0x0123456789.p09l128;
     198        -0x0123456789.p09l32;  -0x0123456789.p09l64;  -0x0123456789.p09l80;  -0x0123456789.p09l128;
     199
     200         0x0123456789.p+09l32;   0x0123456789.p+09L64;   0x0123456789.p+09L80;   0x0123456789.p+09L128;
     201        +0x0123456789.p-09l32;  +0x0123456789.p-09L64;  +0x0123456789.p-09L80;  +0x0123456789.p-09L128;
     202        -0x.0123456789p09l32;   -0x.0123456789p09L64;   -0x.0123456789p09L80;   -0x.0123456789p09L128;
    146203
    147204// char, short, int suffix overloading
    148205
    149 #ifdef __CFA__
    150206        f( 'a' );
    151207        f( 20_hh );
  • src/tests/sched-ext-parse.c

    rb96ec83 r6840e7c  
     1//----------------------------------------------------------------------------------------
     2//----------------------------------------------------------------------------------------
     3//
     4//              DEPRECATED TEST
     5//              DIFFERS BETWEEN DEBUG AND RELEASE
     6//
     7//----------------------------------------------------------------------------------------
     8//----------------------------------------------------------------------------------------
     9
    110#include <monitor>
    211
  • src/tests/sched-int-barge.c

    rb96ec83 r6840e7c  
     1//----------------------------------------------------------------------------------------
     2//----------------------------------------------------------------------------------------
     3//
     4//              DEPRECATED TEST
     5//
     6//----------------------------------------------------------------------------------------
     7//----------------------------------------------------------------------------------------
     8
    19#include <fstream>
    210#include <kernel>
  • src/tests/sched-int-block.c

    rb96ec83 r6840e7c  
     1//---------------------------------------------------------
     2// Barging test
     3// Ensures that no barging can occur between :
     4//   - the frontend of the signal_block and the signaled thread
     5//   - the signaled  threadand the backend of the signal_block
     6//---------------------------------------------------------
     7
     8
    19#include <fstream>
    210#include <kernel>
  • src/tests/sched-int-wait.c

    rb96ec83 r6840e7c  
     1//---------------------------------------------------------
     2// Multi wait test
     3// Ensures that no deadlock from waiting/signalling conditions
     4//---------------------------------------------------------
     5
     6
    17#include <fstream>
    28#include <kernel>
Note: See TracChangeset for help on using the changeset viewer.